aboutsummaryrefslogtreecommitdiffstats
path: root/guides/source/active_record_querying.md
diff options
context:
space:
mode:
Diffstat (limited to 'guides/source/active_record_querying.md')
-rw-r--r--guides/source/active_record_querying.md66
1 files changed, 43 insertions, 23 deletions
diff --git a/guides/source/active_record_querying.md b/guides/source/active_record_querying.md
index 57e8e080f4..4725e2c8a2 100644
--- a/guides/source/active_record_querying.md
+++ b/guides/source/active_record_querying.md
@@ -436,7 +436,7 @@ to this code:
Client.where("orders_count = #{params[:orders]}")
```
-because of argument safety. Putting the variable directly into the conditions string will pass the variable to the database **as-is**. This means that it will be an unescaped variable directly from a user who may have malicious intent. If you do this, you put your entire database at risk because once a user finds out he or she can exploit your database they can do just about anything to it. Never ever put your arguments directly inside the conditions string.
+because of argument safety. Putting the variable directly into the conditions string will pass the variable to the database **as-is**. This means that it will be an unescaped variable directly from a user who may have malicious intent. If you do this, you put your entire database at risk because once a user finds out they can exploit your database they can do just about anything to it. Never ever put your arguments directly inside the conditions string.
TIP: For more information on the dangers of SQL injection, see the [Ruby on Rails Security Guide](security.html#sql-injection).
@@ -473,7 +473,7 @@ In the case of a belongs_to relationship, an association key can be used to spec
```ruby
Post.where(author: author)
-Author.joins(:posts).where(posts: {author: author})
+Author.joins(:posts).where(posts: { author: author })
```
NOTE: The values cannot be symbols. For example, you cannot do `Client.where(status: :active)`.
@@ -685,9 +685,9 @@ This will return single order objects for each day, but only those that are orde
Overriding Conditions
---------------------
-### `except`
+### `unscope`
-You can specify certain conditions to be excepted by using the `except` method. For example:
+You can specify certain conditions to be removed using the `unscope` method. For example:
```ruby
Post.where('id > 10').limit(20).order('id asc').except(:order)
@@ -698,30 +698,24 @@ The SQL that would be executed:
```sql
SELECT * FROM posts WHERE id > 10 LIMIT 20
-# Original query without `except`
+# Original query without `unscope`
SELECT * FROM posts WHERE id > 10 ORDER BY id asc LIMIT 20
```
-### `unscope`
-
-The `except` method does not work when the relation is merged. For example:
-
-```ruby
-Post.comments.except(:order)
-```
-
-will still have an order if the order comes from a default scope on Comment. In order to remove all ordering, even from relations which are merged in, use unscope as follows:
+You can additionally unscope specific where clauses. For example:
```ruby
-Post.order('id DESC').limit(20).unscope(:order) = Post.limit(20)
-Post.order('id DESC').limit(20).unscope(:order, :limit) = Post.all
+Post.where(id: 10, trashed: false).unscope(where: :id)
+# => SELECT "posts".* FROM "posts" WHERE trashed = 0
```
-You can additionally unscope specific where clauses. For example:
+A relation which has used `unscope` will affect any relation it is
+merged in to:
```ruby
-Post.where(id: 10).limit(1).unscope({ where: :id }, :limit).order('id DESC') = Post.order('id DESC')
+Post.order('id asc').merge(Post.unscope(:order))
+# => SELECT "posts".* FROM "posts"
```
### `only`
@@ -796,6 +790,32 @@ SELECT * FROM clients WHERE orders_count > 10 ORDER BY clients.id DESC
This method accepts **no** arguments.
+### `rewhere`
+
+The `rewhere` method overrides an existing, named where condition. For example:
+
+```ruby
+Post.where(trashed: true).rewhere(trashed: false)
+```
+
+The SQL that would be executed:
+
+```sql
+SELECT * FROM posts WHERE `trashed` = 0
+```
+
+In case the `rewhere` clause is not used,
+
+```ruby
+Post.where(trashed: true).where(trashed: false)
+```
+
+the SQL executed would be:
+
+```sql
+SELECT * FROM posts WHERE `trashed` = 1 AND `trashed` = 0
+```
+
Null Relation
-------------
@@ -1022,7 +1042,7 @@ Or, in English: "return all posts that have a comment made by a guest."
#### Joining Nested Associations (Multiple Level)
```ruby
-Category.joins(posts: [{comments: :guest}, :tags])
+Category.joins(posts: [{ comments: :guest }, :tags])
```
This produces:
@@ -1048,7 +1068,7 @@ An alternative and cleaner syntax is to nest the hash conditions:
```ruby
time_range = (Time.now.midnight - 1.day)..Time.now.midnight
-Client.joins(:orders).where(orders: {created_at: time_range})
+Client.joins(:orders).where(orders: { created_at: time_range })
```
This will find all clients who have orders that were created yesterday, again using a `BETWEEN` SQL expression.
@@ -1109,7 +1129,7 @@ This loads all the posts and the associated category and comments for each post.
#### Nested Associations Hash
```ruby
-Category.includes(posts: [{comments: :guest}, :tags]).find(1)
+Category.includes(posts: [{ comments: :guest }, :tags]).find(1)
```
This will find the category with id 1 and eager load all of the associated posts, the associated posts' tags and comments, and every comment's guest association.
@@ -1301,7 +1321,7 @@ especially useful if a `default_scope` is specified in the model and should not
applied for this particular query.
```ruby
-Client.unscoped.all
+Client.unscoped.load
```
This method removes all scoping and will do a normal query on the table.
@@ -1610,7 +1630,7 @@ Client.where(first_name: 'Ryan').count
You can also use various finder methods on a relation for performing complex calculations:
```ruby
-Client.includes("orders").where(first_name: 'Ryan', orders: {status: 'received'}).count
+Client.includes("orders").where(first_name: 'Ryan', orders: { status: 'received' }).count
```
Which will execute: