aboutsummaryrefslogtreecommitdiffstats
path: root/guides/source/active_record_querying.textile
diff options
context:
space:
mode:
Diffstat (limited to 'guides/source/active_record_querying.textile')
-rw-r--r--guides/source/active_record_querying.textile72
1 files changed, 49 insertions, 23 deletions
diff --git a/guides/source/active_record_querying.textile b/guides/source/active_record_querying.textile
index 8e23a577e2..c5755c8308 100644
--- a/guides/source/active_record_querying.textile
+++ b/guides/source/active_record_querying.textile
@@ -133,6 +133,24 @@ SELECT * FROM clients ORDER BY clients.id DESC LIMIT 1
<tt>Model.last</tt> returns +nil+ if no matching record is found. No exception will be raised.
+h5. +find_by+
+
+<tt>Model.find_by</tt> finds the first record matching some conditions. For example:
+
+<ruby>
+Client.find_by first_name: 'Lifo'
+# => #<Client id: 1, first_name: "Lifo">
+
+Client.find_by first_name: 'Jon'
+# => nil
+</ruby>
+
+It is equivalent to writing:
+
+<ruby>
+Client.where(first_name: 'Lifo').first
+</ruby>
+
h5(#first_1). +first!+
<tt>Model.first!</tt> finds the first record. For example:
@@ -167,6 +185,24 @@ SELECT * FROM clients ORDER BY clients.id DESC LIMIT 1
<tt>Model.last!</tt> raises +RecordNotFound+ if no matching record is found.
+h5(#find_by_1). +find_by!+
+
+<tt>Model.find_by!</tt> finds the first record matching some conditions. It raises +RecordNotFound+ if no matching record is found. For example:
+
+<ruby>
+Client.find_by! first_name: 'Lifo'
+# => #<Client id: 1, first_name: "Lifo">
+
+Client.find_by! first_name: 'Jon'
+# => RecordNotFound
+</ruby>
+
+It is equivalent to writing:
+
+<ruby>
+Client.where(first_name: 'Lifo').first!
+</ruby>
+
h4. Retrieving Multiple Objects
h5. Using Multiple Primary Keys
@@ -659,7 +695,7 @@ Optimistic locking allows multiple users to access the same record for edits, an
<strong>Optimistic locking column</strong>
-In order to use optimistic locking, the table needs to have a column called +lock_version+. Each time the record is updated, Active Record increments the +lock_version+ column. If an update request is made with a lower value in the +lock_version+ field than is currently in the +lock_version+ column in the database, the update request will fail with an +ActiveRecord::StaleObjectError+. Example:
+In order to use optimistic locking, the table needs to have a column called +lock_version+ of type integer. Each time the record is updated, Active Record increments the +lock_version+ column. If an update request is made with a lower value in the +lock_version+ field than is currently in the +lock_version+ column in the database, the update request will fail with an +ActiveRecord::StaleObjectError+. Example:
<ruby>
c1 = Client.find(1)
@@ -943,21 +979,23 @@ If, in the case of this +includes+ query, there were no comments for any posts,
h3. Scopes
-Scoping allows you to specify commonly-used ARel queries which can be referenced as method calls on the association objects or models. With these scopes, you can use every method previously covered such as +where+, +joins+ and +includes+. All scope methods will return an +ActiveRecord::Relation+ object which will allow for further methods (such as other scopes) to be called on it.
+Scoping allows you to specify commonly-used queries which can be referenced as method calls on the association objects or models. With these scopes, you can use every method previously covered such as +where+, +joins+ and +includes+. All scope methods will return an +ActiveRecord::Relation+ object which will allow for further methods (such as other scopes) to be called on it.
-To define a simple scope, we use the +scope+ method inside the class, passing the ARel query that we'd like run when this scope is called:
+To define a simple scope, we use the +scope+ method inside the class, passing the query that we'd like run when this scope is called:
<ruby>
class Post < ActiveRecord::Base
- scope :published, where(:published => true)
+ scope :published, -> { where(published: true) }
end
</ruby>
-Just like before, these methods are also chainable:
+This is exactly the same as defining a class method, and which you use is a matter of personal preference:
<ruby>
class Post < ActiveRecord::Base
- scope :published, where(:published => true).joins(:category)
+ def self.published
+ where(published: true)
+ end
end
</ruby>
@@ -965,8 +1003,8 @@ Scopes are also chainable within scopes:
<ruby>
class Post < ActiveRecord::Base
- scope :published, where(:published => true)
- scope :published_and_commented, published.and(self.arel_table[:comments_count].gt(0))
+ scope :published, -> { where(:published => true) }
+ scope :published_and_commented, -> { published.and(self.arel_table[:comments_count].gt(0)) }
end
</ruby>
@@ -983,25 +1021,13 @@ category = Category.first
category.posts.published # => [published posts belonging to this category]
</ruby>
-h4. Working with times
-
-If you're working with dates or times within scopes, due to how they are evaluated, you will need to use a lambda so that the scope is evaluated every time.
-
-<ruby>
-class Post < ActiveRecord::Base
- scope :created_before_now, lambda { where("created_at < ?", Time.zone.now ) }
-end
-</ruby>
-
-Without the +lambda+, this +Time.zone.now+ will only be called once.
-
h4. Passing in arguments
-When a +lambda+ is used for a +scope+, it can take arguments:
+Your scope can take arguments:
<ruby>
class Post < ActiveRecord::Base
- scope :created_before, lambda { |time| where("created_at < ?", time) }
+ scope :created_before, ->(time) { where("created_at < ?", time) }
end
</ruby>
@@ -1048,7 +1074,7 @@ If we wish for a scope to be applied across all queries to the model we can use
<ruby>
class Client < ActiveRecord::Base
- default_scope where("removed_at IS NULL")
+ default_scope { where("removed_at IS NULL") }
end
</ruby>