aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test/cases/relation_test.rb
Commit message (Collapse)AuthorAgeFilesLines
* Green version of moving the handling of supported arguments to `where`yui-knk2015-10-181-7/+4
| | | | | | | | This commit follow up of 4d8f62d. The difference from 4d8f62d are below: * Change `WhereClauseFactory` to accept `Arel::Nodes::Node` * Change test cases of `relation_test.rb`
* Skip the test added in 9cc324a on buggy versions of SQliteSean Griffin2015-09-211-7/+22
| | | | See 7dcfc25e7c52682a4343c2ba7188a69e7c06c936 for more details
* Skip test that fails from outdated sqlite3 on travisSean Griffin2015-06-021-7/+9
|
* Ensure symbols passed to `select` are always quotedSean Griffin2015-05-301-0/+22
| | | | | | | | | | | | | | | | | Our general contract in Active Record is that strings are assumed to be SQL literals, and symbols are assumed to reference a column. If a from clause is given, we shouldn't include the table name, but we should still quote the value as if it were a column. Upon fixing this, the tests were still failing on SQLite. This was because the column name being returned by the query was `"\"join\""` instead of `"join"`. This is actually a bug in SQLite that was fixed a long time ago, but I was using the version of SQLite included by OS X which has this bug. Since I'm guessing this will be a common case for contributors, I also added an explicit check with a more helpful error message. Fixes #20360
* `type_cast_for_database` -> `serialize`Sean Griffin2015-02-171-1/+1
|
* `Type#type_cast_from_database` -> `Type#deserialize`Sean Griffin2015-02-171-1/+1
|
* Raise ArgumentError when passing nil to Relation#mergeRafael Mendonça França2015-02-061-0/+16
| | | | | | nil or false should not be valid argument to the merge method. Closes #12264
* `WhereClause#predicates` does not need to be publicSean Griffin2015-01-271-2/+2
| | | | | | | | | | | The only place it was accessed was in tests. Many of them have another way that they can test their behavior, that doesn't involve reaching into internals as far as they did. `AssociationScopeTest` is testing a situation where the where clause would have one bind param per predicate, so it can just ignore the predicates entirely. The where chain test was primarly duplicating the logic tested on `WhereClause` directly, so I instead just make sure it calls the appropriate method which is fully tested in isolation.
* Remove all references to `where_values` in testsSean Griffin2015-01-251-4/+4
|
* Introduce `Relation::WhereClause`Sean Griffin2015-01-251-8/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The way that bind values are currently stored on Relation is a mess. They can come from `having`, `where`, or `join`. I'm almost certain that `having` is actually broken, and calling `where` followed by `having` followed by `where` will completely scramble the binds. Joins don't actually add the bind parameters to the relation itself, but instead add it onto an accessor on the arel AST which is undocumented, and unused in Arel itself. This means that the bind values must always be accessed as `relation.arel.bind_values + relation.bind_values`. Anything that doesn't is likely broken (and tons of bugs have come up for exactly that reason) The result is that everything dealing with `Relation` instances has to know far too much about the internals. The binds are split, combined, and re-stored in non-obvious ways that makes it difficult to change anything about the internal representation of `bind_values`, and is extremely prone to bugs. So the goal is to move a lot of logic off of `Relation`, and into separate objects. This is not the same as what is currently done with `JoinDependency`, as `Relation` knows far too much about its internals, and vice versa. Instead these objects need to be black boxes that can have their implementations swapped easily. The end result will be two classes, `WhereClause` and `JoinClause` (`having` will just re-use `WhereClause`), and there will be a single method to access the bind values of a `Relation` which will be implemented as ``` join_clause.binds + where_clause.binds + having_clause.binds ``` This is the first step towards that refactoring, with the internal representation of where changed, and an intermediate representation of `where_values` and `bind_values` to let the refactoring take small steps. These will be removed shortly.
* Remove all cases of manuallly wrapping `Arel::Nodes::Quoted`Sean Griffin2014-12-291-6/+6
| | | | | | | | | | This is no longer required now that we are injecting a type caster object into the Arel table, with the exception of uniqueness validations. Since it calls `ConnectionAdapter#type_cast`, the value has already been cast for the database. We don't want Arel to attempt to cast it further, so we need to continue wrapping it in a quoted node. This can potentially go away when this validator is refactored to make better use of `where` or the predicate builder.
* Inform Arel that we don't need type casting in testsSean Griffin2014-12-261-6/+9
| | | | | | | Part of the larger refactoring to remove type casting from Arel. We can inform it that we already have the right type by wrapping the value in an `Arel::Nodes::Quoted`. This commit can be reverted when we have removed type casting from Arel in Rail 5.1
* Inject the `PredicateBuilder` into the `Relation` instanceSean Griffin2014-12-261-25/+25
| | | | | | | Construction of relations can be a hotspot, we don't want to create one of these in the constructor. This also allows us to do more expensive things in the predicate builder's constructor, since it's created once per AR::Base subclass
* Consolidate testing of update_all type castingSean Griffin2014-06-261-0/+28
| | | | | | | | | | | | | | We have several test cases on "tricky" types that are essentially testing that `update_all` goes through the same type casting behavior as a normal assignment + save. We recently had another case to add this test for another type in https://github.com/rails/rails/pull/12742. Rather than testing this separately for every type which is "tricky" when round tripping, let's instead have a fairly exhaustive test that ensures we're getting the correct values at every step for `update_all`. Given the structure of the code now, we can be confident that if the type is correct, and `update_all` is type casting correctly, we're going to get the right behavior for all types.
* Merge pull request #12829 from iantropov/issue_insert_via_hmt_scope_3548Rafael Mendonça França2014-04-101-0/+4
|\ | | | | | | | | | | | | Fix insertion of records for hmt association with scope Conflicts: activerecord/CHANGELOG.md
| * Fix insertion of records for hmt association with scope, fix #3548Ivan Antropov2013-11-171-0/+4
| |
* | Improve tests to use only public APIRafael Mendonça França2013-12-311-3/+2
| |
* | Make outer joins on proper parentWashington Luiz2013-12-311-1/+11
|/ | | | | Outer joins were being built on the root relation klass rather than the one specified in the join dependency root
* Merge pull request #12129 from Empact/deprecate-array-bang-delegationRafael Mendonça França2013-09-121-144/+0
|\ | | | | | | | | | | | | | | Deprecate the delegation of Array bang methods in ActiveRecord::Delegation Conflicts: activerecord/CHANGELOG.md activerecord/test/cases/relation_test.rb
| * Pull the RelationMutationTests from cases/relation_test to ↵Ben Woosley2013-09-031-135/+0
| | | | | | | | cases/relation/mutation_test.
* | Relation#merge should not lose readonly(false) flag.thedarkone2013-09-111-0/+8
| | | | | | | | The original code ignores the `false` value because `false.blank? # => true`.
* | Merge pull request #11958 from jetthoughts/extract_pre_process_orders_argsYves Senn2013-09-041-0/+9
|\ \ | |/ |/| Re-use order arguments pre-processing for reorder
| * Extracted from `order` processing of arguments, and use it for `reorder` to ↵Paul Nikitochkin2013-09-041-0/+9
| | | | | | | | be consistent.
* | move the cache to the AR models and populate it on inheritedAaron Patterson2013-08-301-4/+19
|/
* stop relying on side effects of const_missingAaron Patterson2013-07-231-0/+6
|
* reorder bind parameters when merging relationsAaron Patterson2013-07-151-1/+8
|
* use arel rather than slapping together SQL stringsAaron Patterson2013-07-151-3/+6
|
* Blacklist->whitelist for reference scans in order!Ernie Miller2013-07-141-0/+7
| | | | | | Stop special-casing Arel::Nodes as exempt from reference scanning in order. Instead, only scan order values that are strings for a table reference.
* flatten merged join_values before building the joinsNeeraj Singh2013-06-221-1/+8
| | | | | | | | fixes #10669 While joining_values special treatment is given to string values. By flattening the array it ensures that string values are detected as strings and not arrays.
* Merge pull request #10495 from senny/postgres_test_cleanupRafael Mendonça França2013-05-281-1/+1
|\ | | | | PostgreSQL specific test cleanup
| * cleanup, assert on warning from postgres adapterYves Senn2013-05-081-1/+1
| |
* | include bind values from the default scopeAaron Patterson2013-05-171-4/+1
|/
* if singletons belong to the contract, test themXavier Noria2013-04-201-1/+4
| | | | | | Object#respond_to? returns singletons and thus we inherit that contract. The implementation of the predicate is good, but the test is only checking boolean semantics, which in this case is not enough.
* fix respond_to? for non selected columnNeeraj Singh2013-04-191-0/+5
| | | | | | | | | | | | | | | | | | | | | | | fixes #4208 If a query selects only a few columns and gives custom names to those columns then respond_to? was returning true for the non selected columns. However calling those non selected columns raises exception. post = Post.select("'title' as post_title").first In the above case when `post.body` is invoked then an exception is raised since `body` attribute is not selected. Howevere `respond_to?` did not behave correctly. pos.respond_to?(:body) #=> true Reason was that Active Record calls `super` to pass the call to Active Model and all the columns are defined on Active Model. Fix is to actually check if the data returned from the db contains the data for column in question.
* Address ORA-00979: not a GROUP BY expression errorYasuo Honda2013-04-111-1/+1
|
* While merging relations preserve context for joinsJared Armstrong and Neeraj Singh2013-04-101-1/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Fixes #3002. Also see #5494. ``` class Comment < ActiveRecord::Base belongs_to :post end class Author < ActiveRecord::Base has_many :posts end class Post < ActiveRecord::Base belongs_to :author has_many :comments end ``` `Comment.joins(:post).merge(Post.joins(:author).merge(Author.where(:name => "Joe Blogs"))).all` would fail with `ActiveRecord::ConfigurationError: Association named 'author' was not found on Comment`. It is failing because `all` is being called on relation which looks like this after all the merging: `{:joins=>[:post, :author], :where=>[#<Arel::Nodes::Equality: ....}`. In this relation all the context that `Post` was joined with `Author` is lost and hence the error that `author` was not found on `Comment`. Ths solution is to build JoinAssociation when two relations with join information are being merged. And later while building the arel use the previously built `JoinAssociation` record in `JoinDependency#graft` to build the right from clause. Thanks to Jared Armstrong (https://github.com/armstrjare) for most of the work. I ported it to make it compatible with new code base.
* rename `Relation#uniq` to `Relation#distinct`. `#uniq` still works.Yves Senn2013-03-151-0/+12
| | | | | | | | The similarity of `Relation#uniq` to `Array#uniq` is confusing. Since our Relation API is close to SQL terms I renamed `#uniq` to `#distinct`. There is no deprecation. `#uniq` and `#uniq!` are aliases and will continue to work. I also updated the documentation to promote the use of `#distinct`.
* Expand order(:symbol) to "table".symbol to prevent broken queries on PG.Yves Senn2013-02-251-2/+15
| | | | | | | | | | Fixes #9275. When `#order` is called with a Symbol this patch will prepend the quoted_table_name. Before the postgresql adapter failed to build queries containg a join and an order with a symbol. This expansion happens for all adapters.
* Use separate Relation subclasses for each AR classJon Leighton2012-11-301-21/+24
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | At present, ActiveRecord::Delegation compiles delegation methods on a global basis. The compiled methods apply to all subsequent Relation instances. This creates several problems: 1) After Post.all.recent has been called, User.all.respond_to?(:recent) will be true, even if User.all.recent will actually raise an error due to no User.recent method existing. (See #8080.) 2) Depending on the AR class, the delegation should do different things. For example, if a Post.zip method exists, then Post.all.zip should call it. But this will then result in User.zip being called by a subsequent User.all.zip, even if User.zip does not exist, when in fact User.all.zip should call User.all.to_a.zip. (There are various variants of this problem.) We are creating these compiled delegations in order to avoid method missing and to avoid repeating logic on each invocation. One way of handling these issues is to add additional checks in various places to ensure we're doing the "right thing". However, this makes the compiled methods signficantly slower. In which case, there's almost no point in avoiding method_missing at all. (See #8127 for a proposed solution which takes this approach.) This is an alternative approach which involves creating a subclass of ActiveRecord::Relation for each AR class represented. So, with this patch, Post.all.class != User.all.class. This means that the delegations are compiled for and only apply to a single AR class. A compiled method for Post.all will not be invoked from User.all. This solves the above issues without incurring significant performance penalties. It's designed to be relatively seamless, however the downside is a bit of complexity and potentially confusion for a user who thinks that Post.all and User.all should be instances of the same class. Benchmark --------- require 'active_record' require 'benchmark/ips' class Post < ActiveRecord::Base establish_connection adapter: 'sqlite3', database: ':memory:' connection.create_table :posts def self.omg :omg end end relation = Post.all Benchmark.ips do |r| r.report('delegation') { relation.omg } r.report('constructing') { Post.all } end Before ------ Calculating ------------------------------------- delegation 4392 i/100ms constructing 4780 i/100ms ------------------------------------------------- delegation 144235.9 (±27.7%) i/s - 663192 in 5.038075s constructing 182015.5 (±21.2%) i/s - 850840 in 5.005364s After ----- Calculating ------------------------------------- delegation 6677 i/100ms constructing 6260 i/100ms ------------------------------------------------- delegation 166828.2 (±34.2%) i/s - 754501 in 5.001430s constructing 116575.5 (±18.6%) i/s - 563400 in 5.036690s Comments -------- Bear in mind that the standard deviations in the above are huge, so we can't compare the numbers too directly. However, we can conclude that Relation construction has become a little slower (as we'd expect), but not by a huge huge amount, and we can still construct a large number of Relations quite quickly.
* ActiveRecord::Relation#none! method.Juanjo Bazán2012-10-281-0/+6
|
* Merge pull request #6606 from amatsuda/ar_relation_model_methodRafael Mendonça França2012-08-211-0/+5
|\ | | | | AR::Relation#model would be a better API than AR::Relation#klass
| * AR::Relation#model would be a better API than AR::Relation#klassAkira Matsuda2012-06-031-0/+5
| |
* | Allow Relation#merge to take a proc.Jon Leighton2012-08-031-0/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This was requested by DHH to allow creating of one's own custom association macros. For example: module Commentable def has_many_comments(extra) has_many :comments, -> { where(:foo).merge(extra) } end end class Post < ActiveRecord::Base extend Commentable has_many_comments -> { where(:bar) } end
* | fix association :extend optionJon Leighton2012-07-131-2/+5
|/
* Relation#from to accept other Relation objectsRadoslav Stankov2012-05-171-1/+6
| | | | Record.from("(#{sub_query.to_sql})") -> Record.from(sub_query) Record.from("(#{sub_query.to_sql}) a") -> Record.from(sub_query, :a)
* fix interpolation for hash mergingJon Leighton2012-04-251-4/+13
|
* allow merging a single where valueJon Leighton2012-04-251-0/+6
|
* fix testsJon Leighton2012-04-131-6/+0
|
* now we can just manipulate the values hash in #only and #exceptJon Leighton2012-04-131-0/+13
|
* use a hash to store relation valuesJon Leighton2012-04-131-7/+7
|