Why I Prefer Ruby on Rails over CakePHP

Last year, I had a goal to learn Ruby on Rails and build an application in that framework. By learning CakePHP, I was able to wrap my mind around the rails framework concepts and make that transition a little easier. This year, I have made the full plunge into the Ruby on Rails, and I absolutely love it. As I’ve made the transition from php to ruby and from CakePHP to Ruby On Rails, I’ve written down some of the reasons why I now use Ruby on Rails over CakePHP.

[note: I still prefer to use CakePHP over no framework if a client requests an application be written in php. However, when we have the option to start the project in Rails, we really push for rails.]

Here are some of the reasons why I prefer Ruby on Rails over CakePHP:

Rails doesn’t require you to grab all of your data in the controller

When working with CakePHP, you must retrieve all of your data from the database in the controller and pass it all to your View. All of this data is stored in an associative, which makes accessing your data very easy, but lacks the functionality of using an object.

All of the data that you will need from associated models must exist in the array(s) that you pass to your view. You can grab data from associated models this by using Cake’s recursive option which will grab all of the data in surrounding models.

Lets say that you have an Author that has many Articles, Articles have many Comments and you would like to grab the Author, her articles, and comments to give to the view. You would do this with the recursive option of 2 levels of data retrieval. However, lets say that the author also has many books and books have many chapters. When you do a recursive find on the author, it will grab all of the articles and comments, books and chapters. This leads to a lot of wasted data retrieval

With Rails, you can easily walk through the data models while your are in the view, and if the object doesn’t yet have that data, it will automatically query the database behind the scenes. This is a beautiful thing. So, in the controller, you only have to grab the author. In the view you can then walk the model in the following way:

author.articles.first.comments.first.email_address

Of course you can iterate through the articles and the comments, but you can continue to move to associated models all you want. Also, to save queries to the database, you can do an eager find and specify that you also want her articles so that the articles are also returned in that first query. That is super powerful!

Rails model objects allow for dynamic attributes

Lets say that you have a User model that has the attributes of a first_name, and last_name. When displaying this information, you often want to show the full name. You might just output the first name then the last name every time, but wouldn’t it be nice if you just had a full_name attribute? In rails you can do this by defining a new method named full_name on the User model which returns the formatted full name. In Cake you can’t do this because you only have an associative array.

Lets say that the users have an image associated with their record. The image path on the server can be derived by their user id and an image extension which is stored in the users table. The path would be /images/users/[id].[image_extension]. In Rails, you can define a method on the User model named image_location which returns the formatted path. In Cake, you would have to formulate the path inside the view every time you wish to display it.

Further, if the user had no image, you can check for that inside your image_location method for the image_extension and return a no_image.gif when appropriate. In Cake, you would have to wrap some logic around your image display inside your view which makes it much uglier and prone to bugs.

Rails Has Superior Url Routing

[UPDATE: Ben has just notified me that Cake has now added similar routing capabilities. See his comment.]

Rails has amazing routing capabilities. At first glance, it appears that Cake can do everything that Rails can do, but it can’t. One of the main differences is that Cake’s routing is a one-way routing. Another difference is the way that Cake handles parameters passed to the controller.

One-way routing

Cake’s routing is one way, meaning that you set up your routes in the configuration, and then you must remember your url structure and write the urls yourself throughout the application.

For example, if you are building a social application which features personal profiles. You decide to name your controller ‘Person’ and the action to view the profile ‘view’. Each person is identified by a unique id, so you decide to use the default routing in cake and rails which would give you a url of /person/view/33 for person #33.

Throughout your Rails application, you’ve linked to the personal profile pages by calling link_to(persons_name, :controller => 'person, :action => 'view', :id => persons_id). This builds a url using the default route /person/view/[id].

Throughout your Cake application, you’ve linked to the personal profile pages by calling echo $html->link($persons_name, "/person/view/".$persons_id); . This also gives you the same url: /person/view/[id].

Down the road, you realize that you would like to make your urls more friendly, and represent personal profile pages with a url like: /friend/[id].

In rails, your new route looks like this:

map.connect "friend/:id", :controller => 'person', :action => 'view'

In cake, your new route looks like this:

$Route->connect('/friend/*', array('controller' => 'person', 'action' => 'view'));

It appears that Cake can do everything that Rails can do, but what about all of your urls that you have scattered throughout your application. Rails will automatically write them to fit this new routing pattern. Cake makes you find all of your links and change them by hand.

Rails has two-way routing, where Cake’s routing is one-way.

Parameter handling

[Correction here: You can accomplish similar parameter handling capabilities with Cake. This becomes a null point. You can still concatenate a querystring to the end of the url and use $this->params[‘url’][‘param_name’] to retrieve your parameters].

Cake handles parameters on the url differently than rails. With Cake, your parameters are listed like so /find-person/[param1]/[param2]/[param3]/[etc.].

In your Cake controller, you accept the parameters like so:

function find_person($name, $city, $page)

The order in which they appear on the url determines which parameter they become in the action.

Rails checks to see if the parameter matches a url definition in its routes, and if it doesn’t fit there, it will append it to the end of the url in a querystring like so: /find-person/?name=x&city=Provo&page=3.

In your Rails controller, you would access the paramters like so:

def find_person
name = params[:name]
city = params[:city]
page = params[:page]

You might think that Cake’s way of handling the parameters is superior because it keeps the url looking prettier. However, this can be a real pain if you are writing an advanced search where any of your parameters can be optional. It’s also nice to be able to use a form with the method=GET for search. I don’t know of a way to do this in Cake. See the above message on how to do this in Cake.

There are still other reasons for using Rails over CakePHP, and there are some reasons why clients will still prefer to stick to php. What are some of the reasons you prefer CakePHP over Rails or Rails over CakePHP?

30 thoughts on “Why I Prefer Ruby on Rails over CakePHP”

  1. Nothing should prevent you from using PHP’s builtin $_GET array for your GET stuff.

    Have to say that the model stuff in Rails looks interesting – probably not possible to implement it like that in PHP, but maybe something similar could be done. As for two-way routing, maybe you should make a ticket for it in the CakePHP trac @ http://trac.cakephp.org/

  2. Having worked with CakePHP for some time–you’ve got me curious enough to really try RoR. What were your resources for learning it? Is there a book you’d recommend?

  3. Very nice article. I’ve just taken up cakePHP at work and using RoR at home gives me a few insights to cakePHP’s shortcomings. You’ve pointed out a few things to keep in mind for the future. Thanks for the heads up. But as you said better cakePHP framework than nothing at all, or quick’n’dirty for that matter.

  4. Nice article. I am doing my first PHP project and that to in Cake. I have in java for 8 long years and I just hate those associative arrays. As you rightly pointed out it makes things difficult. Also Rail’s eager loading and tranparent persistence looks so much like Hibernate in java world.

  5. First of all, you’re foolish for passing model objects to your views.. you’re giving the view the ability to call all model functions and your using up unnecessary memory. Your views only need access to data, not functions to manipulate it.

    Models and dynamic attributes..
    You can just as easily create functions in cakephp models to concatenate a string for you if you want.. and if you’re real clever you’d realize that it’s more effective to handle most everything with model functions anyway. Controllers and views should both be simple and effective.

    Cake’s URL routing also behaves in much the same fashion as rails.. $html->link(‘controller’ => ‘someController’, ‘action’ => ‘someAction’, $arg1, $arg2, …) is effectively the same thing that rails would do. I’m still not following the “2 way routing” concept though..

    And lastly, parameter handling. If the parameters in the controller function are like so..

    function view($id = null, $arg1 = null, $arg2 = null, …)

    you wouldn’t necessarily have to pass them to the controller.. and if you don’t pass the params, it’ll just default to null (or whatever you set it to if null is inappropriate)

    Blog about the things you understand, and leave the stuff you don’t get to the experts.

  6. kristofer,

    It appears that you don’t quite understand Rails’ model objects. There’s a fundamental difference in the way Cake and Rails handle the Model. Like I mentioned above, Cake uses associative arrays to handle its data transport, Rails uses objects.

    It’s foolish to say that using objects as a means of transporting data is foolish. Objects are very effective for that purpose. Java Beans are a good example of this. Object Oriented Programming in general embodies these principles. Objects help us to move away from the primitive nature of basic data structures. Of course there’s a trade-off (slight increase in memory usage), but the benefits are great.

    “you’re giving the view the ability to call all model functions …”

    It gives the ability to call model functions on that instance object, yes. But I wouldn’t ever be making Class method calls, which is the way you would do data retrieval in Cake. You wouldn’t manipulate your data in the view either, that would be ridiculous.

    The beauty of the Rails model is that the instance objects bind to the database seamlessly to give you better access to the data that you actually need.

    “… and your using up unnecessary memory”

    This type of access to your data is actually very efficient. If you’ve ever worked with a very complex data model, you would begin to realize that Cake’s recursive find method leads to hundreds of wasted queries to your database. You can remedy this with lots of lines of code to more efficiently retrieve the needed data. So, you’re either dealing with unnecessary memory and unnecessary stress to your database or unnecessary man hours, take your pick.

    As far as the parameter passing, Jiri Kupiainen’s comment is accurate, and if you want to stick to Cake conventions, you can use $this->params[‘url’][‘mygetparameter’]. Somehow I had missed that before. Jiri gave a respectful, and accurate answer.

    Handling optional parameters the way that you suggested doesn’t address the issue that I was talking about (submitting form data with a method=”get”).

    If you don’t understand the 2 way routing, it’s because you haven’t actually built anything with Rails. There’s no way to miss it if you had.

    You obviously have a good deal of experience with CakePHP. Your lack of Rails experience is also apparent.

  7. I guess I’ve always thought of frameworks as a means to separate the design from the development. I can write an appliciation and my colleagues can handle the design work.

    My apologies for using the pronoun ‘you’ with my criticisms, as it seems like a personal attack. I should use phrases like “I think it’s foolish” instead of “You’re foolish.” Regardless though, providing the views with access to model functions seems to break the MVC paradigm.

    You’re right though.. I’ve never used ruby or rails. I suppose if the model data is put into an object that has a few functions for sorting data (even thought the db does that) and such, instead of actual DB queries then it’d be remarkably simple and still maintain that level of separation I’ve fallen in love with. In fact, I bet it’d be easier.

    With cake I write model functions that return the data sets I need, manipulate them in a controller, and then pass the data to the views. It makes a lot of sense to iterate through data sets in my views, but again, I’ve never used rails and I’m sure it’s conventions are wonderful as well.

  8. hi kristofer,

    Apologies accepted. Your previous comment did seem like a personal attack. I apologize likewise for the tone in my response. I could have been more respectful.

    I don’t think that Rails breaks the MVC paradigm as much as it may seem. All of the data sorting is actually handled by the database, and is defined in the model when setting up the associations. It can also be set when you grab your data sets from inside of the controller, almost identical to how its done in Cake.

    The view code ends up being remarkably similar between Cake and Rails. I’ve found that my view code appears much cleaner in my rails apps than it does in my Cake apps.

    I still use Cake, and I think it’s a good framework. I just prefer using Rails when given the chance.

  9. From my understanding, CakePHP wasn’t meant to compete with RoR, but rather bring concepts of RoR to the PHP environment. It was developed to model RoR for us cheap guy who can’t afford a Ruby Server (although they are becoming more popular now) and those who didn’t want to get into Ruby at all.

    One of Cake’s big limitations is that it cannot harness the full power of OOP that exists in PHP 5, because it still remains backward compatible with PHP 4. Wise decision if you ask me.

  10. Good point Baz. Php definitely has wider deployment options, as every hosting solution supports php.

    I see maintaining backwards compatibility with php 4 as a major thorn in the heel of the php world. Unfortunately, developers have to conform to php4 compatibility if they are going to release software that will be widely deployed.

  11. Why use a language that requires people to mess up their servers with yet more software when you can use a language that is already installed on most webservers?

    I don’t get these people that run off onto the bleeding edge, then 8 months later realise they have no customers for their product as noone can install it.

    I’ll upgrade to PHP5 in a few years when more people use it…..

    -Ben

  12. hi Jimmy,

    I didn’t go through your whole blog but after reading the first point:
    Rails doesn’t require you to grab all of your data in the controller, I would like to make one comment.

    As I understand you are concern about redundant query that are generated because authors have books and articles, both, and you are only interested in articles. To avoid having redundant queries, you can use UNBINDMODEL before you initiate a query in a cakephp. There are many components (check in bakery) that make unbind and bind model really easily

    Regards,

  13. I hear Cake’s model is continuing to receive improvements.

    Having to unbind models is extra work that I’d prefer not to have to worry about, but at least it’s there so that you’re not pulling down the entire database to get to a specific piece of data.

  14. I would say that it’s not only a matter of how well Ruby on Rails works compared to CakePHP in relation to MVC, but also the overall picture of the two languages.

    PHP is very mature and there are tons of code and classes and stuff available for doing all kinds of things, so you don’t have to do it yourself.

    RoR is still new, and have a smaller community, and I would guess that code availability is far from reaching the level that as of PHP. This means that you’ll have to do a lot of these things yourself – which of course means spending a lot more time programming. That’s why I’m skeptical with switching to PHP.

    And besides, even having programmed a huge website over 5 years in PHP (and still developing), I haven’t found PHP unable to manage the complexity that the website requires – on the contrary, I love PHP/MySQL and it works wonder for us!

  15. While it’s true that PHP has a lot more code and classes available, I’ve had a lot easier time finding quality libraries in the Ruby community.

    Also, Ruby’s ‘gem’ library repository makes it a joy to install and use new libraries. I don’t find the same amount of quality libraries available in PEAR.

    Because Ruby is and always has been a fully Object Oriented language, all of the code available is object oriented.

    The same is not true in the PHP community. There are tons of snippets that are just plain old procedural code that is hard to reuse or extend. This leads to a lot of sifting through a lot of junk code when looking for an existing library.

    Also, there are a ton of good Rails plug-ins that are super easy to apply to your application. Plug-ins work especially well in Ruby because you can re-open classes to inject functionality, and mix in modules to gain functionality. I believe the Rails community is larger than any community gathered around a single PHP framework. It is really nice to be able to find lots of plug-ins specific to the framework that I am using. I rarely have a problem finding a good plug-in for accomplishing common web-related tasks.

    I’m not saying that Rails and Ruby are the only way to go. PHP does some things very nicely and has some good advantages.

  16. Great post dude. I have yet to jump into either Cake or Rails, and my main project is a combination of the two, but I’ll keep this in mind if I ever start looking into Cake.

    Did you try the Zend Framework at all?

  17. I’ve looked into the Zend Framework, but I haven’t used it on a real project.

    Cake and Rails both follow a principle of “Convention over Configuration” which makes them a bit less flexible, but very easy to get up and running and to maintain. Zend Framework requires a lot of configuration, so you will spend a lot of up-front time getting your configurations right rather than building your core software.

    Some people see Cake and Rails as a bloated framework, but I think their benefits far outweigh the costs of a large framework. Rails has cut down the bloat quite a bit in v2.0 by pushing a lot of the functionality into plug-ins. However the plug-in structure is really easy to maintain.

  18. One thing I’m confused about…Automatically querying data in the view? Unless I’m missing something, I wasn’t able to get this to work. Always got an existence error, unless I modify my find in the controller…

    Please enlighten me.

  19. With Cake 1.2 there are now model behaviors “Bindable” and “Containable” that allow for pretty accurate manipulation of what your model retrieves on recursive queries, so no more uneccessary data retrieval.

    Also, data manipulations like concatenation of the first_name and last name can be integrated into your model data using the afterFind() function in your model.
    Very quick and easy.

  20. You can also now do reverse routing with CakePHP. Using your /person/view/id example we can now do the Rails like $html->link($persons_name, array(‘controller’=>’person’, ‘action’=>’view’, $persons_id);.

  21. As Ben pointed out, you can also use the afterFind to inject generated fields into the returned results array without too much trouble, so you might also want to modify that section of your post – while Cake may not yet be quite as elegantly used as Rails, it does seem to be beginning to acquire it’s most popular features — now it’s still lacking the object over array find result – but it’s much closer than it was.

  22. In Reference to: “Rails model objects allow for dynamic attributes”

    CakePHP handles these scenarios via “virtual fields.” However, I do not like that if I only need the virtual field in one part of the app it has to be everywhere else as well.

Comments are closed.