/mcls

FQL RubyGem

The Facebook Query Language allows you to write SQL-like queries to fetch data from the Graph API. I’ve written a simple gem named fql to simplify this in ruby.

First of all install the gem by adding gem 'fql' to your Gemfile.

Now you can simply use the FQL queries like so:

1
Fql.execute('SELECT first_name, last_name FROM user WHERE uid = 4')

And it will return the matching records as an array of hashes:

Single query result
1
  [{"first_name"=>"Mark", "last_name"=>"Zuckerberg"}]

Using an access token

To access some resources you’ll need to have a valid access token.

1
2
Fql.execute('SELECT first_name, last_name FROM user WHERE uid = me()',
            :access_token => 'abc1234567')

Using a multi-query

If you want to use multi-queries then just pass in a Hash instead of a string.

1
2
3
4
Fql.execute({
  "query1" => "SELECT uid, rsvp_status FROM event_member WHERE eid = 209798352393506 LIMIT 3",
  "query2" => "SELECT name FROM user WHERE uid IN (SELECT uid FROM #query1)"
}, :access_token => "abc1234567")

Note that the result will be a bit different from that of a single query. It will still return an array of hashes, but this time the hashes will have a name and fql_result_set key.
The name is the name of the subquery and fql_result_set will contains the results for that particular query.

Multi-query result example
1
2
3
4
5
6
7
8
9
10
  [
    {
      "name" => "query1",
      "fql_result_set" => [{"uid"=>712638919, "rsvp_status"=>"attending"}, ... ]
    },
    {
      "name"=>"query2",
      "fql_result_set"=>[{"name"=>"Srikanth Nagandla"}, ... ]
    }
  ]

For more information on how the use FQL you can check out the official developer documentation.

Fixing Commits in Git

You can fix your last commit in git by doing git commit --amend. For example, if you had a typo in your last commit message you could correct it by doing:

Fixing a typo with –amend
1
2
3
4
5
6
7
$ git commit -m "Oops, a typo"
$ git log --oneline
9e29e33 Oops, a typo

$ git commit --amend -m "New commit message without typos"
$ git log --oneline
aa7faf2 New commit message without typos

The previous commit will be replaced by the new one, which is based on the current contents of the index. For clarity, I’ll add that the git index is the staging area, also known as everything that is currently being tracked by git. So if you forgot to add some file to the index in the last commit, you could do:

Adding a file
1
2
3
$ git commit -am "Made some changes" # Forgot to add forgotten-file.txt
$ git add forgotten-file.txt
$ git commit --amend -m "Made some changes and added forgotten-file.txt"

Already pushed the commit?

If you’ve already pushed your faulty commit then it’s also best to first do something like: git push -f origin HEAD^:master. Pushing your HEAD at the previous commit and then doing the amend will prevent you from having to do a pull & merge just to fix something small like a typo.

1
2
3
4
5
6
7
$ git commit -am "Typo"
$ git push
$ # Realize you had a typo, so push again but send HEAD^ upstream 
$ # ( HEAD^ means the HEAD at the previous commit )
$ git push -f origin HEAD^:master
$ git commit --amend -m "Fixed Typo"
$ git push # No pull or merge needed

Documentation

Lastly here’s the --amend option documentation from the git-commit man page.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
--amend
    Used to amend the tip of the current branch. Prepare the tree object you would want to replace
    the latest commit as usual (this includes the usual -i/-o and explicit paths), and the commit
    log editor is seeded with the commit message from the tip of the current branch. The commit
    you create replaces the current tip - if it was a merge, it will have the parents of the
    current tip as parents - so the current top commit is discarded.
    It is a rough equivalent for:

        $ git reset --soft HEAD^
        $ ... do something else to come up with the right tree ...
        $ git commit -c ORIG_HEAD

    but can be used to amend a merge commit.
    You should understand the implications of rewriting history if you amend a commit that has
    already been published. (See the "RECOVERING FROM UPSTREAM REBASE" section in git-rebase(1).)

PEAR, PHPUnit and MAMP

The problem I had

When I had initially installed PEAR I just used it’s suggested paths and didn’t think it would be any problem. I could install phpunit and use it from the command line. But when I wanted to configure NetBeans to use PHPUnit I got the following error:

Selected PHPUnit (version ?.?.?) is too old, upgrade it if possible (the minimum version in 3.3.0).

After reading some posts, trying to fix it through editing all the php.ini’s, reinstalling PHPUnit, … I still kept on getting errors. Finally I decided to take the time to restart from scratch and make sure all php related stuff would be kept in the MAMP directories so that in the future problems like this would be easier to solve. I removed the old php, phpunit, pear, … binaries from /usr/local/bin and replaced them by symlinks to the ones in the MAMP directory.

This tutorials shows how I installed PEAR and PHPUnit from scratch.

Installing PEAR for MAMP

1
2
3
cd /Applications/MAMP/bin/php/php5.3/
curl -O http://pear.php.net/go-pear.phar
./bin/php ./go-pear.phar 

Now pear will suggest a file layout for you, but it will try to put everything in your home directory, while most of it should be in your MAMP folder. The following is the correct layout:

1
2
3
4
5
6
7
8
9
10
11
 1. Installation base ($prefix)                   : /Applications/MAMP/bin/php5.3
 2. Temporary directory for processing            : /tmp/pear/install
 3. Temporary directory for downloads             : /tmp/pear/install
 4. Binaries directory                            : /Applications/MAMP/bin/php5.3/bin
 5. PHP code directory ($php_dir)                 : /Applications/MAMP/bin/php5.3/lib/php
 6. Documentation directory                       : /Applications/MAMP/bin/php5.3/lib/php/doc
 7. Data directory                                : /Applications/MAMP/bin/php5.3/lib/php/data
 8. User-modifiable configuration files directory : /Applications/MAMP/bin/php5.3/conf
 9. Public Web Files directory                    : /Applications/MAMP/htdocs
10. Tests directory                               : /Applications/MAMP/bin/php5.3/lib/php/tests
11. Name of configuration file                    : /Users/yourusername/.pearrc

Of course the php5.3/ and username/ could be different for you. By setting the paths this way all PEAR packages will automatically land inside the standard PHP include_path of MAMP.

Now let’s go to /usr/local/bin and create a symlink to the pear command in your MAMP directory. This is an easy way to make sure it’s in you PATH, allowing you to be able to just type pear to use it.

1
2
cd /usr/local/bin
ln -s /Applications/MAMP/bin/php5.3/bin/pear

If you want to you can repeat this for php, phpunit and the others too.

Installing PHPUnit

Now that we have PEAR installed installing PHPUnit is easy.

1
2
sudo pear channel-discover pear.phpunit.de
sudo pear install --alldeps phpunit/PHPUnit

Starting from PHPUnit 3.6.8 the functionality behind “phpunit –skeleton-class” and “phpunit –skeleton-test” is marked as deprecated and it’s going to be removed in 3.7. So it’s best to install phpunit-skelgen too:

1
sudo pear install phpunit/PHPUnit_SkeletonGenerator

Having now installed PEAR and PHPUnit properly, you should be able to easily configure NetBeans for use with PHPUnit.

POJO Binding and JPA’s orphanRemoval in Play

The orphanRemoval property allows you to easily manage OneToMany and OneToOne relationships. If a relationship has orphanRemoval set to true, then whenever a child is removed from the parent entity it will also be deleted from the database.

But when used in combination with Play’s POJO binding, it can cause some unexpected errors. Consider the following example:

1
2
3
4
5
@Entity
public class Parent extends Model {
  @OneToMany(cascade=CascadeType.ALL, orphanRemoval=true)
  List<Child> childs;
}

And our Controller:

1
2
3
4
5
6
7
public ParentController extends Controller {
  public static void update(Parent parent) {
    parent.merge();
    parent.save();
    render(parent);
  }
}

This will throw the following exception: PersistenceException occured : org.hibernate.HibernateException: A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: models.Parent.childs

The problem

To make the orphanRemoval work Hibernate has to keep track of the Collection that is referencing the childs. When update() is called, the childs List is assigned a new instance, this is what causes the PersistenceException.

The solution

We can easily solve this by providing a setter for childs which will prevent it from being assigned a new instance. Here is the fixed Parent model:

1
2
3
4
5
6
7
8
9
10
11
12
@Entity
public class Parent extends Model {
  @OneToMany(cascade=CascadeType.ALL, orphanRemoval=true)
  List<Child> childs;

  public void setChilds(List<Child> newChilds) {
    this.childs.clear();
    if (newChilds != null) {
      this.childs.addAll(newChilds);
    }
  }
}

JPA: The Difference Between Merge() and Persist()

When I started developing in Play! Framework it was my first time developing in Java and using JPA. I got a bit confused when I needed to use merge() for the first time so I decided to write a bit about it to better my understanding of Play! and JPA.

Let’s look at what the official EntityManager documentation says first.

merge()

<T> T merge(T entity)
Merge the state of the given entity into the current persistence context.

persist()

void persist(Object entity)
Make an entity instance managed and persistent.

The difference

As the documentation says persist() will make the entity instance managed and persistent, while merge() will just merge the state into the current persistence context. What this means is that both methods will add the entity to the persistence context, but persist() will also make the entity managed so that changes after the persist() call will also be persisted, whereas merge() will not do this (although it will return a managed entity instance).

An example in Play! Framework

This is where I got confused. I thought calling merge() on my model would be sufficient, but Play manages JPA a bit differently. In Play! you have to explicitly save an object using save(). Play does this because it’s more intuitive than having to call refresh() on entities. The save() method will then call persist() on the entity if needed, this is also why the models in Play don’t have a persist() method.

A very basic example (without validation etc.)

Controller

1
2
3
4
5
6
7
8
9
10
11
public class Questions extends Controller {

  public static void update(Question question) {
    // Suppose the question contains some new answers
    question.merge();
    // Save! Otherwise the state of the question entity will be refreshed!
    question.save();
    render(question);
  }

}

Question Entity

1
2
3
4
5
6
7
8
@Entity
public class Question extends Model {

  @OneToMany(cascade=CascadeType.ALL, orphanRemoval=true)
  public List<Answer> answers;

  // Other fields...
}

Resources