Commit Graph

49 Commits

Author SHA1 Message Date
Tsutomu Kuroda
c1d9934447 Handle aliased attributes in AR::Relation#select, #order, etc.
With this we can write `Model#select(:aliased)`, `Model#order(:aliased)`,
`Model#reoder(aliased: :desc)`, etc.

Supplementary work to 54122067acaad39b277a5363c6d11d6804c7bf6b.
2014-01-29 09:16:46 +09:00
Kuldeep Aggarwal
a2985e2067 raise ArgumentError exception if Model.where.not is called with nil argument 2013-12-30 01:53:02 +05:30
Lauro Caetano
d4ee09cda1 Create a blacklist to disallow mutator methods to be delegated to Array.
This change was necessary because the whitelist wouldn't work.
It would be painful for users trying to update their applications.

This blacklist intent to prevent odd bugs and confusion in code that call mutator
methods directely on the `Relation`.
2013-12-17 13:43:10 -02:00
Martin Emde
8062a30794 Better support for where() conditions that use an association name.
Using the name of an association in `where` previously worked only
if the value was a single `ActiveRecrd::Base` object. e.g.

    Post.where(author: Author.first)

Any other values, including `nil`, would cause invalid SQL to be
generated. This change supports arguments in the `where` query
conditions where the key is a `belongs_to` association name and the
value is `nil`, an `Array` of `ActiveRecord::Base` objects, or an
`ActiveRecord::Relation` object.

    # Given the Post model
    class Post < ActiveRecord::Base
      belongs_to :author
    end

    # nil value finds records where the association is not set
    Post.where(author: nil)
    # SELECT "posts".* FROM "posts" WHERE "posts"."author_id" IS NULL

    # Array values find records where the association foreign key
    # matches the ids of the passed ActiveRecord models, resulting
    # in the same query as Post.where(author_id: [1,2])
    authors_array = [Author.find(1), Author.find(2)]
    Post.where(author: authors_array)

    # ActiveRecord::Relation values find records using the same
    # query as Post.where(author_id: Author.where(last_name: "Emde"))
    Post.where(author: Author.where(last_name: "Emde"))

Polymorphic `belongs_to` associations will continue to be handled
appropriately, with the polymorphic `association_type` field added
to the query to match the base class of the value. This feature
previously only worked when the value was a single `ActveRecord::Base`.

    class Post < ActiveRecord::Base
      belongs_to :author, polymorphic: true
    end

    Post.where(author: Author.where(last_name: "Emde"))
    # Generates a query similar to:
    Post.where(author_id: Author.where(last_name: "Emde"), author_type: "Author")
2013-12-16 14:16:15 -08:00
Jeremy Kemper
0b142a6f84 Add a bunch of Relation -> Array delegate methods to the whitelist. This won't last - aim to switch back to a blacklist for mutator methods. 2013-12-12 21:10:03 -07:00
Lauro Caetano
1244aa7c5f Use public_send instead of just use send. 2013-12-12 20:19:04 -02:00
Lauro Caetano
aa85bdba68 Use a whitelist to delegate methods to array 2013-12-12 19:34:47 -02:00
Yves Senn
7ccb482181 Merge pull request #13029 from akshay-vishnoi/documentation
`delgated` => `delegated`
2013-11-25 00:47:59 -08:00
Akshay Vishnoi
5a406ff42e delgated => delegated 2013-11-25 14:09:44 +05:30
Jon Leighton
64b9e93bb5 Fix ActiveRecord::Relation#unscope
I'm pretty confused about the addition of this method. The documentation
says that it was intended to allow the removal of values from the
default scope (in contrast to #except). However it behaves exactly the
same as except: https://gist.github.com/jonleighton/7537008 (other than
having a slightly enhanced syntax).

The removal of the default scope is allowed by
94924dc32baf78f13e289172534c2e71c9c8cade, which was not a change we
could make until 4.1 due to the need to deprecate things. However after
that change #unscope still gives us nothing that #except doesn't already
give us.

However there *is* a desire to be able to unscope stuff in a way that
persists across merges, which would allow associations to be defined
which unscope stuff from the default scope of the associated model. E.g.

  has_many :comments, -> { unscope where: :trashed }

So that's what this change implements. I've also corrected the
documentation. I removed the guide references to #except as I think
unscope really supercedes #except now.

While we're here, there's also a potential desire to be able to write
this:

  has_many :comments, -> { unscoped }

However, it doesn't make sense and would not be straightforward to
implement. While with #unscope we're specifying exactly what we want to
be removed from the relation, with "unscoped" we're just saying that we
want it to not have some things which were added earlier on by the
default scope. However in the case of an association, we surely don't
want *all* conditions to be removed, otherwise the above would just
become "SELECT * FROM comments" with no foreign key constraint.

To make the above work, we'd have to somehow tag the relation values
which get added when evaluating the default scope in order to
differentiate them from other relation values. Which is way too much
complexity and therefore not worth it when most use cases can be
satisfied with unscope.

Closes #10643, #11061.
2013-11-20 22:23:16 +00:00
Yves Senn
f83c9b10b4 use arel nodes to represent non-string order_values.
This fixes a bug when merging relations of different classes.

```
Given:
  Post.joins(:author).merge(Author.order(name: :desc)).to_sql

Before:
 SELECT "posts".* FROM "posts"
   INNER JOIN "authors" ON "authors"."id" = "posts"."author_id"
   ORDER BY "posts"."name" DESC

After:
 SELECT "posts".* FROM "posts"
   INNER JOIN "authors" ON "authors"."id" = "posts"."author_id"
   ORDER BY "authors"."name" DESC
```
2013-11-19 17:40:21 +01:00
Yasuo Honda
8e3474bede Address test_merging_where_relations failure by adding order("posts.id") 2013-11-18 02:10:56 +09:00
Yves Senn
c994e10862 fix weird Emacs auto indentation. [ci skip] 2013-11-13 17:56:44 +01:00
Yves Senn
f081edb1fe tests for merging Relations of different classes. 2013-11-13 17:41:26 +01:00
Yves Senn
742adce211 move Relation#merge tests into separate file. 2013-11-13 17:41:20 +01:00
Akira Matsuda
3ce9e43bc3 Avoid sorting an Array including objects from different Classes
addresses "ArgumentError: comparison of VerySpecialComment with SpecialComment failed" in ActiveRecord::DelegationRelationTest#test_#sort!_delegation_is_deprecated
2013-11-11 19:53:54 +09:00
Akira Matsuda
48b10134a5 Load test fixtures where data are needed
Without this, some tests here were not actually testing anything.
2013-11-11 19:53:54 +09:00
Akira Matsuda
9222928dfb A tiny grammatical fix
[ci skip]
2013-11-11 19:14:42 +09:00
David Heinemeier Hansson
661637e5b6 Delegate #rewhere to all on the class like all other relation methods 2013-11-02 19:45:03 -07:00
David Heinemeier Hansson
f950b2699f Added ActiveRecord::QueryMethods#rewhere which will overwrite an existing, named where condition. 2013-11-02 17:36:45 -07:00
Federico Ravasio
0aeb11e575 Allow methods arity below -1 in assert_responds.
Every method from MRI's core classes is written in C. This means
Method#arity always returns -1 for methods with a variable number of
arguments. This is not the case with Rubinius, where, for example
Array#slice! is implemented in Ruby and has arity -2, since is
defined as def slice!(start, length = undefined)
2013-10-08 00:15:11 +02:00
Rafael Mendonça França
defdeed2fc Merge pull request #12129 from Empact/deprecate-array-bang-delegation
Deprecate the delegation of Array bang methods in ActiveRecord::Delegation

Conflicts:
	activerecord/CHANGELOG.md
	activerecord/test/cases/relation_test.rb
2013-09-12 21:36:00 -03:00
Ben Woosley
1a40be0211 Deprecate the delegation of Array bang methods in ActiveRecord::Delegation
The primary means of returning results for Array bang methods is to modify
the array in-place. When you call these methods on a relation, that
array is created, modified, and then thrown away. Only the secondary
return value is exposed to the caller.

Removing this delegation is a straight-forward way to reduce user error
by forcing callers to first explicitly call #to_a in order to expose
the array to be acted on by the bang method.
2013-09-04 01:32:27 -07:00
Ben Woosley
5e41cb4a1e Pull the RelationMutationTests from cases/relation_test to cases/relation/mutation_test. 2013-09-03 21:03:26 -07:00
Mikhail Dieterle
c2e084ac48 check class hierarchy with is_a? in PredicateBuilder.expand
add changelog entry for #11945
2013-08-27 15:47:21 +03:00
Yasuo Honda
d613034a11 Change test_registering_new_handlers and test_count_on_invalid_columns_raises
tesetcases assertion to case insensitive because Oracle database adapter
handles table name in uppercase.
2013-08-02 05:55:31 +09:00
sgrif
92a603387c Add ability to specify how a class is converted to Arel predicate
This adds the ability for rails apps or gems to have granular control
over how a domain object is converted to sql. One simple use case would
be to add support for Regexp. Another simple case would be something
like the following:

    class DateRange < Struct.new(:start, :end)
      def include?(date)
        (start..end).cover?(date)
      end
    end

    class DateRangePredicate
      def call(attribute, range)
        attribute.in(range.start..range.end)
      end
    end

    ActiveRecord::PredicateBuilder.register_handler(DateRange,
      DateRangePredicate.new)

More complex cases might include taking a currency object and converting
it from EUR to USD before performing the query.

By moving the existing handlers to this format, we were also able to
nicely refactor a rather nasty method in PredicateBuilder.
2013-07-28 13:12:20 -06:00
Godfrey Chan
54122067ac Handle aliased attributes in ActiveRecord::Relation.
When using symbol keys, ActiveRecord will now translate aliased attribute names to the actual column name used in the database:

With the model

  class Topic
    alias_attribute :heading, :title
  end

The call

  Topic.where(heading: 'The First Topic')

should yield the same result as

  Topic.where(title: 'The First Topic')

This also applies to ActiveRecord::Relation::Calculations calls such as `Model.sum(:aliased)` and `Model.pluck(:aliased)`.

This will not work with SQL fragment strings like `Model.sum('DISTINCT aliased')`.

Github #7839

*Godfrey Chan*
2013-05-01 16:36:01 -07:00
Aaron Patterson
5dc2e3531b stop calling to_sym when building arel nodes [CVE-2013-1854] 2013-03-15 17:45:10 -07:00
Steve Klabnik
afd4a14332 Revert "Merge pull request #9207 from dylanahsmith/mysql-quote-numeric"
This reverts commit 408227d9c5ed7de26310d72a1a99c1ee02311c63, reversing
changes made to dca0b57d03deffc933763482e615c3cf0b9a1d97.
2013-02-27 08:46:40 -08:00
Guillermo Iguaran
29f3a036e7 Reverting e170014113 (Change behaviour with empty hash in where clause) 2013-02-08 16:53:49 -05:00
Guillermo Iguaran
fa987cb8ec Reverting 16f6f25 (Change behaviour with empty array in where clause) 2013-02-08 14:22:10 -05:00
robertomiranda
16f6f2592e Change behaviour with empty array in where clause 2013-02-08 06:37:30 -05:00
robertomiranda
e170014113 Change behaviour with empty hash in where clause 2013-02-08 01:04:32 -05:00
Dylan Smith
a712e08ebe active_record: Quote numeric values compared to string columns. 2013-02-07 04:59:33 -05:00
Aaron Patterson
170fb5c80c reduce the number of queries on IN clauses, fix relation queries in where 2013-01-24 14:29:03 -08:00
Carlos Antonio da Silva
507d23c421 Fix syntax error and remove duplicated test 2013-01-08 20:00:51 -02:00
Aaron Patterson
8e577fe560 * Strip nils from collections on JSON and XML posts. [CVE-2013-0155] * dealing with empty hashes. Thanks Damien Mathieu
Conflicts:
	actionpack/CHANGELOG.md
	actionpack/lib/action_dispatch/http/request.rb
	actionpack/lib/action_dispatch/middleware/params_parser.rb
	activerecord/CHANGELOG.md
	activerecord/lib/active_record/relation/predicate_builder.rb
	activerecord/test/cases/relation/where_test.rb
2013-01-08 12:41:24 -08:00
Jeremy Kemper
c31cc963da Revert "Merge branch 'master-sec'"
This reverts commit 88cc1688d0cb828c17706b41a8bd27870f2a2beb, reversing
changes made to f049016cd348627bf8db0d72382d7580bf802a79.
2013-01-08 12:41:04 -08:00
Aaron Patterson
d99e8c9e16 * Strip nils from collections on JSON and XML posts. [CVE-2013-0155] * dealing with empty hashes. Thanks Damien Mathieu
Conflicts:
	actionpack/CHANGELOG.md
	actionpack/lib/action_dispatch/http/request.rb
	actionpack/lib/action_dispatch/middleware/params_parser.rb
	activerecord/CHANGELOG.md
	activerecord/lib/active_record/relation/predicate_builder.rb
	activerecord/test/cases/relation/where_test.rb
2013-01-07 17:20:12 -08:00
Carlos Antonio da Silva
8d02afeaee Rollback where.like and where.not_like
The real win with these chain methods is where.not, that takes care of
different scenarios in a graceful way, for instance when the given value
is nil.

    where("author.id != ?", author_to_ignore.id)
    where.not("author.id", author_to_ignore.id)

Both where.like and where.not_like compared to the SQL versions doesn't
seem to give us that much:

    Post.where("title LIKE 'ruby on%'")
    Post.where.like(title: 'ruby on%'")
    Post.where("title NOT LIKE 'ruby on%'")
    Post.where.not_like(title: 'ruby on%'")

Thus Rails is adding where.not, but not where.like/not_like and others.
2012-12-07 16:52:55 -02:00
claudiob
bb53c60fd0 Document the types of arguments accepted by AR#not
This commit stems from https://github.com/rails/rails/pull/8332#issuecomment-11127957

Since the formats in which conditions can be passed to `not` differ
from the formats in which conditions can be passed to `like` and `not_like`,
then I think it's worth adding rdoc and tests to show this behavior
2012-12-07 09:05:33 -08:00
Carlos Antonio da Silva
89ab303d8b Fix where.not with in clause
Arel::Nodes::In inherits from Arel::Nodes::Equality, so the case
statement was always using the Equality operator for both scenarios,
resulting in a not equal query instead.
2012-12-07 08:56:49 -02:00
Carlos Antonio da Silva
55dec5a7da Move where with blank conditions test to the correct where tests file
This test does not belong to has many associations test.
2012-12-07 01:08:38 -02:00
Akira Matsuda
de75af7acc Relation.where with no args can be chained with not, like, and not_like
examples:

  Model.where.not field: nil
  #=> "SELECT * FROM models WHERE field IS NOT NULL

  Model.where.like name: 'Jeremy%'
  #=> "SELECT * FROM models WHERE name LIKE 'Jeremy%'

this feature was originally suggested by Jeremy Kemper https://github.com/rails/rails/pull/5950#issuecomment-5591330

Closes #5950
2012-11-30 01:18:18 +09:00
Damien Mathieu
30a576fa14 fix querying with an empty hash
Closes #6960
2012-09-19 15:57:22 +02:00
Jon Leighton
eb4a623d74 Fix nested association references
Previously the reflection would be looked up on the wrong class. However
the test passed because the examples referred back to themselves.
2012-09-12 23:32:50 +01:00
beerlington
3da275c439 Accept belongs_to assoc. keys in ActiveRecord queries
Allows you to specify the model association key in a belongs_to
relationship instead of the foreign key.

The following queries are now equivalent:

Post.where(:author_id => Author.first)
Post.where(:author => Author.first)

PriceEstimate.where(:estimate_of_type => 'Treasure', :estimate_of_id => treasure)
PriceEstimate.where(:estimate_of => treasure)
2012-09-11 14:11:51 -04:00
Aaron Patterson
9340f89849 predicate builder should not recurse for determining where columns.
Thanks to Ben Murphy for reporting this

CVE-2012-2661
2012-05-30 15:09:13 -07:00