Thursday, June 26, 2008
Render a collection
Very often we want to list a collection of data in front HTML page.
Let's say we have an animal collection. Each record of this collection contains animal Specie, Age, Weight and Risk. As you can imagine, the list is retrieved by
Now, how shuold we render the collection?
Usually we use 'for each' against the collection to render the table:
But there is a better solution with a bonus feature, a counter of records. Once you are used to this solution, you most likely will not turn back.
The solution is to use partial with :collection function and key is NAMING CONVENTION.
The collection partial is passed in by this way:
Partial's name 'animal' will be passed into partial as a varible. It represents one record in the collection. So, 'animal' can be used to reference one record in the collection.
Here is the partial:
You can also add a new column to count the rows. There is a 0 based counter avaiable in partial. By naming convention, the counter variable is called animal_counter (partial-name_counter).
Don't forget using h(...) function to sanitize your passed in variable.
Thursday, June 19, 2008
Now I can access the WEBrick server
As you know you can access a Rails project via browser by calling
or
This problem bothered me for a while. I read some articles about how WEBrick works but did find how to make visible to other computers.
Today I have to ask helps from Rails community and finally found the solution. There is nothing to with how to config the WEBrick. It is simple as this:
Now I can access the pages from other computers. Pretty happy.
http://localhost:3000/.../...But when I try to access this project from other computers by calling
http://[computer_name]:3000/.../...
or
http://[ip_address]:3000/.../..., IE or FireFox just can't reach the web page.
This problem bothered me for a while. I read some articles about how WEBrick works but did find how to make visible to other computers.
Today I have to ask helps from Rails community and finally found the solution. There is nothing to with how to config the WEBrick. It is simple as this:
Ruby script/server -b [ip_address] -p [port]
Now I can access the pages from other computers. Pretty happy.
Thursday, June 12, 2008
Polymorphic Raccoon
Yesterday night, my mom was terribly scared by a raccoon. She said it made a funny face when she was watching TV.
This brought a question to me. Is raccoon offensive? If not, why was my mom scared?
So, if I create an label and attach it to anything (I mean anything, not just animals) which are offensive, my mom should NOT be scared.
Since the label is going to be attached to ANYTHING, it brings me an association dilemma. If a Offend label is attached to Raccoon class, an association from Raccoon to Offend is established. If another Offend label is attached to Dog class, another association to Offend is also established. So, Offend must hold both 'foreign keys' to Man and Dog. But each record of Offend class always has one foreign key with Null value. For example, if Offend record 1 points to Raccoon, the foreign key to Dog must be Null. Vise versa.
In Ruby On Rails, 'polymorphic has_many association' can solve the problem. 'polymorphic has_many association' hooks a particular class to any kind and number of sources classes. These source classes may not be related.
First, let's define an INTERFACE called offensive (you can use any name) and declare it is polymorphic.
Second, let's create a Offend class which will be attached as a label to other classes. Then, we make Offend class belong to the INTERFACE.
Third, create two columns in table offends: offensive_id and offensive_type
In Rails 2.0+, a new macro style method 'references' is introduced to automatically create the INTERFACE's id and type.
But I found only offensive_id was generated, not offensive_type. The INTERFACES's type field is used to hold the classes' type of which the Offend class will be attached to, such as Raccoon or Dog. So more research on 'references' method is needed in the future.
Now we are ready to attach this class to any source classes.
First, simply declare has_many offends via offensive INTERFACE.
Second, create a Offend object and update its :offensive attribute by passing the source objects (like instance of Dog or Raccoon) in.
Now we can see, by attaching the class Offend, Raccoon is more dangerous then Dog.
Wednesday, June 11, 2008
I am a VIP
A problem I found is how Model class inheritance reflects in table relationship. When I saw the Single-Table Inheritance (STI) introduced by Martin Fowler a couple of years ago, I thought it was really stupid.
The whole idea of STI is simple: include all super/sub classes' attributes in one big fat single table and use an extra column (may be called 'type') to distinguish different type of classes.
But the default rails way is STI. :(
Now I have a Model class User and want to have another Model class called VIPUser which is a subclass of User. VIPUser has a new attribute called vip_number which User doesn't have.
OK, let's do the magic.
First, create a VIPUser Model
Second, edit the migration script for VIPUser
Notice that two new columns are created in the users table (which is for Model class User). One is the attribute of VIPUser, 'vip_number' and another is 'type' which is used to distinguish the type of classes.
If you've already had a column called 'type' or you don't like the name, you can use any other names and later declare it in VIPUser Model class.
Third, make VIPUser a subclass of User
That is it!
Now if you create a new VIPUser, you will see Rails automatically populate a string 'VIPUser' in type field.
Monday, June 9, 2008
No, you can't delete accounts!
In many cases, bank managers ask you to keep an account information even it is closed or removed. Usually we keep the record in database but mark it by a flag column like 'delete_at' or 'status'.
To provent the false deletion, a method is registered to callback before_destroy.
Notice that return false is very important. It halts the execution of the further deletion action.
Also notice that delete and delete_all ActiveRecord model methods will bypass the before_destroy callback methods.
for example:
To provent the false deletion, a method is registered to callback before_destroy.
Notice that return false is very important. It halts the execution of the further deletion action.
Also notice that delete and delete_all ActiveRecord model methods will bypass the before_destroy callback methods.
for example:
Saturday, June 7, 2008
Hey yo! one class per kitty
Kitty students start to register courses. A student can have many courses and a course can contain many students. Students and courses are many to many relationship via registration.
Now, the problem is, how to make sure each kitty is not registered more once for a particular course.
To do this, use validates_uniqueness_of
Validate the uniqueness of a kitty student id (kitty_id) against a course_id:
Remember! when validating the uniqueness via has_many :through, use specific attribute name instead of model name.
not
Tuesday, June 3, 2008
You better accept it!
Time after time you will find all kind of term of services which ask you to click 'I Agree'
Well, you better agree. Otherwise, you will be kicked out!
Here is the rails way to enforce this:
Model side:
RHTML side:
The :term_of_service is actually virtual. It has not direct value in database. ActiveRecord temperately hold it in memory.
Well, you better agree. Otherwise, you will be kicked out!
Here is the rails way to enforce this:
Model side:
RHTML side:
<%form_for :user, @user, :url => users_path do f %>
<p>
... other controls ...
</p>
<p>
<%= f.check_box :terms_of_service %>
I accept the terms of service.
</p> <p>
<%= submit_tag "Save" %>
</p>
<% end %>
The :term_of_service is actually virtual. It has not direct value in database. ActiveRecord temperately hold it in memory.
Subscribe to:
Posts (Atom)