Let's dive a little deeper into ActiveRecord and see how we can find and search for records:
### Lookups ###
# find the "first" `Post`
# notice the ORDER BY and LIMIT in the generated SQL
Post.first
# Post Load (0.1ms) SELECT "posts".* FROM "posts" ORDER BY "posts"."id" ASC LIMIT 1
#=> #<Post:0x000000059f3378
# id: 1,
# title: "Blog 1",
# body: "Lorem ipsum dolor sit amet.",
# author: "Kevin",
# created_at: Sun, 07 Dec 2014 00:00:00 UTC +00:00,
# updated_at: Sun, 07 Dec 2014 00:00:00 UTC +00:00>
# some similar methods...
Post.second
# Post Load (0.1ms) SELECT "posts".* FROM "posts" ORDER BY "posts"."id" ASC LIMIT 1 OFFSET 1
#=> #<Post:0x00000005a8b100 id: 2, ...
Post.last
# Post Load (0.4ms) SELECT "posts".* FROM "posts" ORDER BY "posts"."id" DESC LIMIT 1
#=> #<Post:0x00000005ae99f8 id: 3, ...
# we can even get counts
Post.count
# (0.1ms) SELECT COUNT(*) FROM "posts"
# => 3
# at this point we're familiar with the idea of `.find`
Post.find 1
# Post Load (0.1ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = ? LIMIT 1 [["id", 1]]
#=> #<Post:0x00000005b86f50 id: 1, ...
# but with Active Record, we can also look up by several ids at once
Post.find [1,2]
# Post Load (0.4ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" IN (1, 2)
#=> [#<Post:0x00000005bd8558 id: 1, ...>,
# #<Post:0x00000005bd83f0 id: 2, ...>]
# we're also familiar with `.where`
Post.where(author: 'Brad')
# Post Load (0.3ms) SELECT "posts".* FROM "posts" WHERE "posts"."author" = ? [["author", "Brad"]]
#=> [#<Post:0x0000000207b528 ... author: "Brad", ...
# but we can also use special finders like this
Post.find_by_author 'Brad'
# Post Load (0.1ms) SELECT "posts".* FROM "posts" WHERE "posts"."author" = ? LIMIT 1 [["author", "Brad"]]
#=> #<Post:0x00000005c6ee68 ... author: "Brad", ...
### ActiveRecord_Relation ###
# it's important to note what `.where` really gives us
Post.where(author: 'Brad').class
# => Post::ActiveRecord_Relation
# this ActiveRecord_Relation lets us chain calls together
# for example, if we wanted, for some reason,
# the first three comments ordered by author,
# we could chain `.author` and `.limit` calls
Comment.order(:author).limit(3)
# Comment Load (0.2ms) SELECT "comments".* FROM "comments" ORDER BY "comments"."author" ASC LIMIT 3
# => [#<Comment:0x00000005f84f58
# id: 2,
# body: "Lorem ipsum dolor sit amet.",
# author: "DHH",
# post_id: 1,
# created_at: Thu, 11 Dec 2014 00:00:00 UTC +00:00,
# updated_at: Thu, 11 Dec 2014 00:00:00 UTC +00:00>,
# #<Comment:0x00000005f84df0
# id: 5,
# body: "Lorem ipsum dolor sit amet.",
# author: "DHH",
# post_id: 2,
# created_at: Sun, 14 Dec 2014 00:00:00 UTC +00:00,
# updated_at: Sun, 14 Dec 2014 00:00:00 UTC +00:00>,
# #<Comment:0x00000005f84c88
# id: 7,
# body: "Lorem ipsum dolor sit amet.",
# author: "DHH",
# post_id: 3,
# created_at: Tue, 16 Dec 2014 00:00:00 UTC +00:00,
# updated_at: Tue, 16 Dec 2014 00:00:00 UTC +00:00>]
# this is possible because each of these methods is...
Comment.order(:author).limit(3).class
# => Comment::ActiveRecord_Relation
# but when we also iterate over these objects as if they were arrays
Comment.order(:author).limit(3).map {|comment|
[comment.author, comment.created_at]
}
# Comment Load (0.9ms) SELECT "comments".* FROM "comments" ORDER BY "comments"."author" ASC LIMIT 3
#=> [["DHH", Thu, 11 Dec 2014 00:00:00 UTC +00:00],
# ["DHH", Sun, 14 Dec 2014 00:00:00 UTC +00:00],
# ["DHH", Tue, 16 Dec 2014 00:00:00 UTC +00:00]]
# the chaining of these calls basically builds up a query
# and the SQL is generated and executed upon something like
# one of the following methods being called on the object:
#
# .first
# .last
# .all
# .each
#
# which is why our `.map` above works as we'd expect it to
For more resources on ActiveRecord
models, validations, associations, and more: