Commit Graph

49374 Commits

Author SHA1 Message Date
Yves Senn
d28e5b94a7 introduce ActiveSupport::Testing::FileFixtures.
It's a thin layer to provide easy access to sample files throughout
test-cases. This adds the directory `test/fixtures/files` to newly
generated applications.
2015-01-28 12:29:34 +01:00
Yves Senn
71a84206ab Merge pull request #18709 from ianks/atomic-write
Return value of yielded block in File.atomic_write
2015-01-28 08:58:16 +01:00
Ian Ker-Seymer
b3c23f1176 Return value of yielded block in File.atomic_write
Staying true to Ruby convention, we now return the value of the yielded
block from `File.atomic_write {...}`. This mimics the behavior of MRI's
`File.open {...}`.
2015-01-28 00:40:25 -07:00
Guillermo Iguaran
36082a6204 Merge pull request #18666 from cheunghy/auth_check_nil
Fixed undefined method error when doing http basic authentication.
2015-01-28 00:00:17 -05:00
Aaron Patterson
1fb9e6eff7 improve performance of integration tests.
I found delegate to be a bottleneck during integration tests.  Here is
the test case:

```ruby
require 'test_helper'

class DocumentsIntegrationTest < ActionDispatch::IntegrationTest
  test "index" do
    get '/documents'
    assert_equal 200, response.status
  end
end

Minitest.run_one_method(DocumentsIntegrationTest, 'test_index')
StackProf.run(mode: :wall, out: 'stackprof.dump') do
  3000.times do
    Minitest.run_one_method(DocumentsIntegrationTest, 'test_index')
  end
end
```

Top of the stack:

```
[aaron@TC integration_performance_test (master)]$ stackprof stackprof.dump
==================================
  Mode: wall(1000)
  Samples: 23694 (7.26% miss rate)
  GC: 1584 (6.69%)
==================================
     TOTAL    (pct)     SAMPLES    (pct)     FRAME
      7058  (29.8%)        6178  (26.1%)     block in Module#delegate
       680   (2.9%)         680   (2.9%)     ActiveSupport::PerThreadRegistry#instance
       405   (1.7%)         405   (1.7%)     ThreadSafe::NonConcurrentCacheBackend#[]
       383   (1.6%)         383   (1.6%)     Set#include?
       317   (1.3%)         317   (1.3%)     ActiveRecord::Base.logger
       281   (1.2%)         281   (1.2%)     Rack::Utils::HeaderHash#[]=
       269   (1.1%)         269   (1.1%)     ActiveSupport::Notifications::Fanout::Subscribers::Evented#subscribed_to?
       262   (1.1%)         262   (1.1%)     block (4 levels) in Class#class_attribute
       384   (1.6%)         246   (1.0%)     block (2 levels) in Class#class_attribute
```

According to @eileencodes's tests, this speeds up integration tests so
that they are only 1.4x slower than functional tests:

Before:

  INDEX: Integration Test:      153.2 i/s - 2.43x slower

After:

  INDEX: Integration Test:      275.1 i/s - 1.41x slower
2015-01-27 16:29:18 -08:00
Sean Griffin
b06f64c348 Remove Relation#bind_params
`bound_attributes` is now used universally across the board, removing
the need for the conversion layer. These changes are mostly mechanical,
with the exception of the log subscriber. Additional, we had to
implement `hash` on the attribute objects, so they could be used as a
key for query caching.
2015-01-27 16:10:03 -07:00
Rafael Mendonça França
d66ffb656e Merge pull request #18588 from thegcat/patch-1
[ci skip] fix typo still -> will
2015-01-27 20:19:29 -02:00
Felix Schäfer
31dd1ca59f fix typo still cause -> still causes 2015-01-27 21:18:15 +01:00
Sean Griffin
3a551b9777 All subclasses of Attribute should be private constants 2015-01-27 13:08:07 -07:00
Sean Griffin
6c235dd958 Use an Attribute object to represent a bind value
The column is primarily used for type casting, which we're trying to
separate from the idea of a column. Since what we really need is the
combination of a name, type, and value, let's use the object that we
already have to represent that concept, rather than this tuple. No
consumers of the bind values have been changed, only the producers
(outside of tests which care too much about internals). This is
*finally* possible since the bind values are now produced from a
reasonable number of lcoations.
2015-01-27 12:07:06 -07:00
Sean Griffin
102a5272c5 Don't rely on the internal representation of join values
I'm going to be extracting this logic into a clause class, things need
to go through a method and not access the values hash directly.
2015-01-27 11:04:56 -07:00
Sean Griffin
ae299dd45d Minor refactorings on Relation#build_joins
Attempting to grok this code by refactoring it as I go through it.
2015-01-27 10:56:31 -07:00
Sean Griffin
d26dd00854 WhereClause#predicates does not need to be public
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.
2015-01-27 10:30:38 -07:00
Sean Griffin
c2c95cd279 Use the WhereClause ast building logic for having 2015-01-27 10:03:25 -07:00
Sean Griffin
a5fcdae0a0 Move where grouping into WhereClause 2015-01-27 09:41:25 -07:00
Sean Griffin
16ce2eecd3 Unify access to bind values on Relation
The bind values can come from four places. `having`, `where`, `joins`,
and `from` when selecting from a subquery that contains binds. These
need to be kept in a specific order, since the clauses will always
appear in that order. Up until recently, they were not.

Additionally, `joins` actually did keep its bind values in a separate
location (presumably because it's the only case that people noticed was
broken). However, this meant that anything accessing just `bind_values`
was broken (which most places were). This is no longer possible, there
is only a single way to access the bind values, and it includes joins in
the proper location. The setter was removed yesterday, so breaking `+=`
cases is not possible.

I'm still not happy that `joins` is putting it's bind values on the
Arel AST, and I'm planning on refactoring it further, but this removes a
ton of bug cases.
2015-01-27 09:18:30 -07:00
Rafael Mendonça França
ad20b41cb9 Merge pull request #18701 from andreynering/fix-typo-guide-name
Fix typo on guide name
2015-01-27 13:18:36 -02:00
Andrey Nering
d5d9e0af3f Fix typo on guide name [ci skip] 2015-01-27 13:16:46 -02:00
Rafael Mendonça França
1bc30b18b7 Restore useful documentation removed at
3729103e17e00494c8eae76e8a4ee1ac990d3450

[ci skip]
2015-01-27 11:21:42 -02:00
Abdelkader Boudih
75a1ab5f62 Merge pull request #18622 from take/patch-1
Update ActiveRecord::ModelSchema#table_name= 's doc
2015-01-27 08:12:09 +00:00
Takehiro Adachi
3729103e17 Update model_schema.rb [ci skip]
Overriding these methods may cause unexpected results since
"table_name=" does more then just setting the "@table_name".

ref: https://github.com/rails/rails/pull/18622#issuecomment-70874358
2015-01-27 16:01:34 +09:00
Sean Griffin
bdc5141652 Move the from bind logic to a FromClause class
Contrary to my previous commit message, it wasn't overkill, and led to
much cleaner code.

[Sean Griffin & anthonynavarre]
2015-01-26 16:36:14 -07:00
Sean Griffin
8436e2c2bd Remove Relation#bind_values=
The last place that was assigning it was when `from` is called with a
relation to use as a subquery. The implementation was actually
completely broken, and would break if you called `from` more than once,
or if you called it on a relation, which also had its own join clause,
as the bind values would get completely scrambled. The simplest solution
was to just move it into its own array, since creating a `FromClause`
class for this would be overkill.
2015-01-26 16:20:58 -07:00
Sean Griffin
765a3123c8 Remove unused bind and bind! methods from Relation 2015-01-26 16:12:59 -07:00
Sean Griffin
76661dc64f Remove Relation#build_where
All of its uses have been moved to better places
2015-01-26 15:55:22 -07:00
Sean Griffin
6a7ac40dab Go through normal where logic in AssociationScope
This removes the need to duplicate much of the logic in `WhereClause`
and `PredicateBuilder`, simplifies the code, removes the need for the
connection adapter to be continuously passed around, and removes one
place that cares about the internal representation of `bind_values`

Part of the larger refactoring to change how binds are represented
internally

[Sean Griffin & anthonynavarre]
2015-01-26 15:49:29 -07:00
Sean Griffin
9d4d2e7fc6 Ensure the type caster object given to Arel is always marshallable
The Relation will ultimately end up holding a reference to the arel
table object, and its associated type caster. If this is a
`TypeCaster::Connection`, that means it'll hold a reference to the
connection adapter, which cannot be marshalled. We can work around this
by just holding onto the class object instead. It's ugly, but I'm hoping
to remove the need for the connection adapter type caster in the future
anyway.

[Sean Griffin & anthonynavarre]
2015-01-26 15:47:43 -07:00
Sean Griffin
a384c002af Generate a query that makes sense when testing having clauses
PG expects us to not give it nonsenes

[Sean Griffin & anthonynavarre]
2015-01-26 15:01:28 -07:00
Sean Griffin
39f2c3b3ea Change having_values to use the WhereClause class
This fixed an issue where `having` can only be called after the last
call to `where`, because it messes with the same `bind_values` array.
With this change, the two can be called as many times as needed, in any
order, and the final query will be correct. However, once something
assigns `bind_values`, that stops. This is because we have to move all
of the bind values from the having clause over to the where clause since
we can't differentiate the two, and assignment was likely in the form
of:

`relation.bind_values += other.bind_values`

This will go away once we remove all places that are assigning
`bind_values`, which is next on the list.

While this fixes a bug that was present in at least 4.2 (more likely
present going back as far as 3.0, becoming more likely in 4.1 and later
as we switched to prepared statements in more cases), I don't think this
can be easily backported. The internal changes to `Relation` are
non-trivial, anything that involves modifying the `bind_values` array
would need to change, and I'm not confident that we have sufficient test
coverage of all of those locations (when `having` was called with a hash
that could generate bind values).

[Sean Griffin & anthonynavarre]
2015-01-26 14:44:05 -07:00
Sean Griffin
1152219fa2 Improve consistency of counter caches updating in memory
When we made sure that the counter gets updated in memory, we only did
it on the has many side. The has many side only does the update if the
belongs to cannot. The belongs to side was updated to update the counter
cache (if it is able). This means that we need to check if the
belongs_to is able to update in memory on the has_many side.

We also found an inconsistency where the reflection names were used to
grab the association which should update the counter cache. Since
reflection names are now strings, this means it was using a different
instance than the one which would have the inverse instance set.

Fixes #18689

[Sean Griffin & anthonynavarre]
2015-01-26 12:37:29 -07:00
Sean Griffin
8e3b1a632c Test association was eager loaded, rather than reaching into internals 2015-01-26 11:36:13 -07:00
Sean Griffin
025187d980 Move flattening records added to an association farther out
There are many ways that things end up getting passed to `concat`. Not
all of those entry points called `flatten` on their input. It seems that
just about every method that is meant to take a single record, or that
splats its input, is meant to also take an array. `concat` is the
earliest point that is common to all of the methods which add records to
the association. Partially fixes #18689
2015-01-26 11:36:13 -07:00
Carlos Antonio da Silva
71003d63b6 Move method to private section
It's under private in Active Model as well.
2015-01-26 08:17:53 -02:00
Sean Griffin
c414fc60ac Remove where_values and where_values=
We've now removed all uses of them across the board. All logic lives on
`WhereClause`.
2015-01-25 17:50:24 -07:00
Sean Griffin
fcb95d6744 Correct the implementation for unscope(:where)
The code assumes that non-single-value methods mean multi value methods.
That is not the case. We need to change the accessor name, and only
assign an array for multi value methods
2015-01-25 17:50:24 -07:00
Sean Griffin
4b71ab089c Move where_values_hash over to WhereClause 2015-01-25 17:50:24 -07:00
Sean Griffin
17b1b5d773 Remove all references to where_values in tests 2015-01-25 17:50:19 -07:00
Sean Griffin
d6110799c2 Move where_unscoping logic over to WhereClause 2015-01-25 17:30:42 -07:00
Sean Griffin
7227e4fba1 Remove most references to where_values in QueryMethods
We're still using it in `where_unscoping`, which will require moving
additional logic.
2015-01-25 17:20:04 -07:00
Sean Griffin
b6a9c620aa Relation#Merger can merge all clause methods
This will make it easy to add `having_clause` and `join_clause` later.
2015-01-25 17:16:30 -07:00
Sean Griffin
924127e21f Rename WhereClause#parts to WhereClause#predicates 2015-01-25 17:09:14 -07:00
Sean Griffin
2ae49dd073 Move where.not logic into WhereClause 2015-01-25 17:06:13 -07:00
Sean Griffin
2da8f2154b Move the construction of WhereClause objects out of Relation
Yes, I know, I called it a factory so I'm basically the worst person
ever who loves Java and worships the Gang of Four.
2015-01-25 16:53:46 -07:00
Sean Griffin
320600c773 Remove all references to where_values in association code 2015-01-25 16:46:54 -07:00
Sean Griffin
87726b93d4 Remove references to :bind in except
Bind values are no longer a thing, so this is unnecessary.
2015-01-25 16:40:23 -07:00
Sean Griffin
def2879d7d Move where merging logic over to WhereClause
This object being a black box, it knows the details of how to merge
itself with another where clause. This removes all references to where
values or bind values in `Relation::Merger`
2015-01-25 16:31:21 -07:00
Sean Griffin
2c46d6db4f Introduce Relation::WhereClause
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.
2015-01-25 16:23:01 -07:00
Sean Griffin
79f71d35e9 Don't access the where values hash directly in through associations
See 4d7a62293e148604045a5f78a9d4312e79e90d13 for the reasoning
2015-01-25 16:13:27 -07:00
Sean Griffin
4d7a62293e Don't rely as much on the structure of the values hash in associations
The structure of `values[:where]` is going to change, with an
intermediate definition of `where_values` to aid the refactoring.
Accessing `values[:where]` directly messes with that, signficantly.

The array wrapping is no longer necessary, since `where_values` will
always return an array.
2015-01-25 16:11:07 -07:00
Zachary Scott
ffd495cf21 Merge pull request #18683 from cllns/fix-typo-in-migration-generator-comment
Fix typos in migration generator comment
2015-01-25 13:32:54 -08:00