Reputation: 18318
class Course < ActiveRecord::Base
belongs_to :course_category
belongs_to :client
belongs_to :user_created, :foreign_key => :user_created_by, :class_name => "User"
belongs_to :user_updated, :foreign_key => :user_last_updated_by, :class_name => "User"
has_many :course_steps, :dependent => :destroy
has_many :steps, :through => :course_steps
has_many :course_requests
end
Here is output from the rails console...
>> c=Course.first
=> #<Course id: 1, course_category_id: 1, client_id: 1, user_created_by: 1, user_last_updated_by: 1, title: "Test Course 1", summary: "", hidden: false, auto_register: false, created_at: "2011-03-08 01:03:47", updated_at: "2011-03-08 01:03:47">
>> c.course_steps
=> [#<CourseStep id: 3, step_id: 2, course_id: 1, position: nil, created_at: "2011-03-08 15:03:44", updated_at: "2011-03-08 15:03:44">, #<CourseStep id: 4, step_id: 3, course_id: 1, position: nil, created_at: "2011-03-08 15:03:46", updated_at: "2011-03-08 15:03:46">]
>> c.course_steps.order("id DESC")
=> [#<CourseStep id: 4, step_id: 3, course_id: 1, position: nil, created_at: "2011-03-08 15:03:46", updated_at: "2011-03-08 15:03:46">, #<CourseStep id: 3, step_id: 2, course_id: 1, position: nil, created_at: "2011-03-08 15:03:44", updated_at: "2011-03-08 15:03:44">]
>> c.course_steps.order("id DESC").to_sql
=> "SELECT \"course_steps\".* FROM \"course_steps\" WHERE (\"course_steps\".course_id = 1) ORDER BY id DESC"
>> c.course_steps.order("position DESC").to_sql
=> "SELECT \"course_steps\".* FROM \"course_steps\" WHERE (\"course_steps\".course_id = 1) ORDER BY position DESC"
>> c.steps.order("position DESC").to_sql
=> "SELECT \"steps\".* FROM \"steps\" INNER JOIN \"course_steps\" ON \"steps\".id = \"course_steps\".step_id WHERE ((\"course_steps\".course_id = 1)) ORDER BY position DESC"
>> c.steps.class
=> Array
>> c.course_steps.class
=> Array
>>
The parts that I am confused by are: (I am glad they work, but I am just wondering why)
The fact that I can call "order" on course_steps (which is an array) c.course_steps.order("id DESC")!?!?
The fact that I can call c.steps.order("position DESC") when position is not even part of the steps table. It somehow does a magical join.
Upvotes: 0
Views: 463
Reputation: 4043
The fact that I can call "order" on course_steps (which is an array) c.course_steps.order("id DESC")!?!?
As I see it, rails doesn't immediately query a database after each of the chained methods. Instead, it processes the whole chain and constructs the query.
So order
is not called on the course_steps
array. It just appends an order
part of the query.
Here's a qoute from the Beginning Rails:
Notice that when you call the order method, it returns an array object as you may have expected. One thing that happens on the background is that Active Record allows you to chain calls to multiple methods before sending the command to the database; so you can call all, followed by order, and some other methods we’ll talk about in the next chapter, to create more precise database queries. Also, Active Record is smart enough to use lazy loading, a practice that only hits the database when necessary—in this example, when you call the each method.
Upvotes: 1