Showing posts with label rails_path. Show all posts
Showing posts with label rails_path. Show all posts

Thursday, November 16, 2006

The Rails Path: Tracks (Part 1)

The amazing Jamis Buck has teamed up with Michael Koziarski to offer a new coding series called The Rails Way. Some of the comments in their first installment mention the fact that some people new to rails may not have a very strong grounding in Ruby. In order to help those people understand the Rails Way wisdom, I will be explaining parts of their post in the context of a basic beginner to Ruby/Rails.

Acts_as_name_part_finder
(original code here)
The acts_acts_as_name_part_finder macro adds a method called find_by_namepart that allows for one to search by an entire name or a piece of a name. It would be used like this:

You would then be able to do things like:

The point the Rails Way is making is that it is unnecessary to declare an entirely new acts_as_* macro just for the sake of adding a single function. An additional point is that this function is only ever used in one model. The lesson here is don't abstract code into a new macro/file if its only being used in one place. Wait until you see yourself copying and pasting the code into other places before you start abstracting it.


Modules
If you're learning Ruby/Rails, you really should know what modules are and how to use them. For those that need a quick refresher, a module is just a container around some pieces of code. Usually you define methods in a module and then use the "include" keyword to add those methods/code into your class. For example:

If find_by_namepart had been used in multiple places, it would have made sense to define the function inside a module and then use "include" in the places where you need that functionality.


Acts_as_todo_container
(original code here)
The first point the Rails Way makes is that a lot of the original code for the acts_as_todo_container was solely for the purpose of having the database automatically include associated 'has_many' models in a single db query. This allows for:

With this code, if I made a call to Context.find_not_done_todos I would get back a list of Todo's as well as their associated Projects. A great majority of the actual acts_as_todo_container deals with adding in this :find_todos_include functionality. By using the :include option in the has_many association, all of this code can be eliminated and the resulting code simplified to the point where a separate acts_as_todo_container is not necessary. Instead, the Todo handling code can be placed into a basic module and be "included" as normal.

Other Simplifications
Besides removing :find_todos_include, the Rails Way introduced a number of syntactical simplifications:

1. Replacing code like:

The ||= operator checks to see if @not_done_todos is nil. If it is, it sets it to find_not_done_todos. Otherwise it just evaluates (and returns) @not_done_todos. This is exactly what the previous code did in a more succinct form.

2. Replacing code like:

Instead of making a call to Todo.find and trying to manually simulate the has_many relationship through use of statements like "#{self.class.base_class.name.singularize.downcase}_id", they use the has_many association defined in the model to make the simple "self.todos.find" call. This is again a result of moving the :include parameter to the has_many association and allowing the built in rails macros to handle all the complex stuff.

That's everything for this post. If anyone has any questions (no matter how basic) please feel free to ask. To make things clear, I am not trying to steal the Rails Ways' thunder. My goal is to elaborate on their points so that people who don't have much of a Ruby/Rails background can still understand what's going on.