Commit Graph

91 Commits

Author SHA1 Message Date
Ryuta Kamizono
d4007d5a54 Fix inheritance object creation from relation
We need to pass scope attributes to `klass.new` to detect subclass.
Otherwise `subclass_from_attributes` can't detect subclass which is had
in scope attributes.

Fixes #18062.
Closes #18227.
Closes #30720.
2017-12-13 14:13:52 +09:00
Yukio Mizuta
25cb200cb7 Clarify base_class tests on abstract STI vs concrete STI 2017-08-12 11:04:01 -07:00
Sean Griffin
213796fb49 Refactor Active Record to let Arel manage bind params
A common source of bugs and code bloat within Active Record has been the
need for us to maintain the list of bind values separately from the AST
they're associated with. This makes any sort of AST manipulation
incredibly difficult, as any time we want to potentially insert or
remove an AST node, we need to traverse the entire tree to find where
the associated bind parameters are.

With this change, the bind parameters now live on the AST directly.
Active Record does not need to know or care about them until the final
AST traversal for SQL construction. Rather than returning just the SQL,
the Arel collector will now return both the SQL and the bind parameters.
At this point the connection adapter will have all the values that it
had before.

A bit of this code is janky and something I'd like to refactor later. In
particular, I don't like how we're handling associations in the
predicate builder, the special casing of `StatementCache::Substitute` in
`QueryAttribute`, or generally how we're handling bind value replacement
in the statement cache when prepared statements are disabled.

This also mostly reverts #26378, as it moved all the code into a
location that I wanted to delete.

/cc @metaskills @yahonda, this change will affect the adapters

Fixes #29766.
Fixes #29804.
Fixes #26541.
Close #28539.
Close #24769.
Close #26468.
Close #26202.

There are probably other issues/PRs that can be closed because of this
commit, but that's all I could find on the first few pages.
2017-07-24 09:07:24 -04:00
Rafael França
15ef55efb5 Merge pull request #29732 from kirs/frozen-activerecord
Use frozen-string-literal in ActiveRecord
2017-07-21 14:36:30 -04:00
Sean Griffin
93c9a95e01 Revert "Extract bind_param and bind_attribute into ActiveRecord::TestCase"
This reverts commit b6ad4052d18e4b29b8a092526c2beef013e2bf4f.

This is not something that the majority of Active Record should be
testing or care about. We should look at having fewer places rely on
these details, not make it easier to rely on them.
2017-07-21 14:01:08 -04:00
Kir Shatrov
831be98f9a Use frozen-string-literal in ActiveRecord 2017-07-19 22:27:07 +03:00
Ryuta Kamizono
452a814cf0 Make preload query to preparable
Currently preload query cannot be prepared statements even if
`prepared_statements: true` due to array handler in predicate builder
doesn't support making bind params. This makes preload query to
preparable by don't passing array value if possible.
2017-07-07 23:22:21 +09:00
Matthew Draper
87b3e226d6 Revert "Merge pull request #29540 from kirs/rubocop-frozen-string"
This reverts commit 3420a14590c0e6915d8b6c242887f74adb4120f9, reversing
changes made to afb66a5a598ce4ac74ad84b125a5abf046dcf5aa.
2017-07-02 02:15:17 +09:30
Kir Shatrov
cfade1ec7e Enforce frozen string in Rubocop 2017-07-01 02:11:03 +03:00
Ryuta Kamizono
c11109da93 Fix default_scoped with defined default_scope on STI model
This regression is caused by d1249c1.

If STI model is defined `default_scope`, `base_rel` is not respected.
I fixed to merge `base_rel` in that case.
2017-05-31 17:51:38 +09:00
bogdanvlviv
40bdbce191
Define path with __dir__
".. with __dir__ we can restore order in the Universe." - by @fxn

Related to 5b8738c2df003a96f0e490c43559747618d10f5f
2017-05-23 00:53:51 +03:00
Ryuta Kamizono
b201474756 Should escape meta characters in regexp 2017-05-07 04:10:00 +09:00
Konstantin Lazarev
cdf8a2b493 Cache results of computing model type
We faced a significant performance decrease when we started using STI
without storing full namespaced class name in type column (because of PostgreSQL
length limit for ENUM types).
We realized that the cause of it is the slow STI model instantiation. Problematic
method appears to be `ActiveRecord::Base.compute_type`, which is used to find
the right class for STI model on every instantiation.
It builds an array of candidate types and then iterates through it calling
`safe_constantize` on every type until it finds appropriate constant. So if
desired type isn't the first element in this array there will be at least one
unsuccessful call to `safe_constantize`, which is very expensive, since it's
defined in terms of `begin; rescue; end`.

This commit is an attempt to speed up `compute_type` method simply by caching
results of previous calls.

```ruby
class MyCompany::MyApp::Business::Accounts::Base < ApplicationRecord
  self.table_name = 'accounts'
  self.store_full_sti_class = false
end

class MyCompany::MyApp::Business::Accounts::Free < Base
end

class MyCompany::MyApp::Business::Accounts::Standard < Base
  # patch .compute_type there
end

puts '======================= .compute_type ======================='
Benchmark.ips do |x|
  x.report("original method") do
    MyCompany::MyApp::Business::Accounts::Free.send :compute_type, 'Free'
  end
  x.report("with types cached") do
    MyCompany::MyApp::Business::Accounts::Standard.send :compute_type, 'Standard'
  end
  x.compare!
end
```

```
======================= .compute_type =======================
  with types cached:  1529019.4 i/s
    original method:     2850.2 i/s - 536.46x  slower
```

```ruby
5_000.times do |i|
  MyCompany::MyApp::Business::Accounts::Standard.create!(name: "standard_#{i}")
end

5_000.times do |i|
  MyCompany::MyApp::Business::Accounts::Free.create!(name: "free_#{i}")
end

puts '====================== .limit(100).to_a ======================='
Benchmark.ips do |x|
  x.report("without .compute_type patch") do
    MyCompany::MyApp::Business::Accounts::Free.limit(100).to_a
  end
  x.report("with .compute_type patch") do
    MyCompany::MyApp::Business::Accounts::Standard.limit(100).to_a
  end
  x.compare!
end
```

```
====================== .limit(100).to_a =======================
     with .compute_type patch:      360.5 i/s
  without .compute_type patch:       24.7 i/s - 14.59x  slower
```
2017-01-03 19:02:38 +05:00
Rafael Mendonça França
55f9b8129a
Add three new rubocop rules
Style/SpaceBeforeBlockBraces
Style/SpaceInsideBlockBraces
Style/SpaceInsideHashLiteralBraces

Fix all violations in the repository.
2016-08-16 04:30:11 -03:00
Xavier Noria
b326e82dc0 applies remaining conventions across the project 2016-08-06 20:20:22 +02:00
Xavier Noria
d22e522179 modernizes hash syntax in activerecord 2016-08-06 19:37:57 +02:00
Xavier Noria
9617db2078 applies new string literal convention in activerecord/test
The current code base is not uniform. After some discussion,
we have chosen to go with double quotes by default.
2016-08-06 18:26:53 +02:00
Aaron Ang
798dc5a925 Remove log-related stuff from ActiveSupport::Dependencies
In this patch, all log-related stuff in `ActiveSupport::Dependencies`
is removed because the logging is no longer useful.
2016-03-15 00:54:48 +01:00
Sean Griffin
77383fc1e4 Do not use default attributes for STI when instantiating a subclass
The commit which originally added this behavior did not consider that
doing `Subclass.new` does not actually populate the `type` field in the
attributes (though perhaps it should). We simply need to not use the
defaults for STI related things unless we are instantiating the base
class.

Fixes #23285.
2016-01-27 13:26:20 -05:00
Prathamesh Sonpatki
e55ba530c1 Fix test failure on PostgreSQL by sorting the result before comparison 2016-01-19 22:45:25 +05:30
Yves Senn
3ea4476942 run type column through attribtues API type casting.
Closes #21986.

This makes it possible to write custom types that define a different
mapping for STI columns.
2016-01-19 17:31:16 +01:00
Yves Senn
72b92e8172 don't rely on the columns hash to get defaults. follow-up to #17169.
This will also get the defaults from attribute definitions like:

     attribute :type, :string, default: "SomethingElse"
2015-12-02 17:14:45 +01:00
Yves Senn
3da890f891 Merge pull request #17169 from kuldeepaggarwal/fix-STI-default-type
STI cast new instances to `default type` on initialize.
2015-12-02 13:39:30 +01:00
Kuldeep Aggarwal
6b18bdd00c STI cast new instances to default type on initialize.
fixes #17121
2015-12-02 16:11:24 +05:30
yui-knk
2fe8baf9b2 Move some AR test cases to inheritance_test.rb
These methods are defined in inheritance.rb

* `abstract_class?`
* `descends_from_active_record?`
* `compute_type`
2015-10-31 08:30:18 +09:00
Rafael Mendonça França
8e57ed1a39 Revert "Merge pull request #21994 from mtodd/inherit-scopes"
This reverts commit 60c9701269f5b412849f1a507df61ba4735914d7, reversing
changes made to 6a25202d9ea3b4a7c9f2d6154b97cf8ba58403db.

Reason: Broken build
2015-10-27 01:12:03 -02:00
Matt Todd
3c4aa73ce8 Make inherited scope test fail
This triggers the JoinDependency work to reflect on the associations
and trigger an error as follows:

  ActiveRecord::ConfigurationError: Association named 'account' was
  not found on Company; perhaps you misspelled it?

Fix Company.of_first_firm joins association name

Should be `Company.joins(:accounts)` not `Company.joins(:account)`.

Do the same for Client.of_first_firm
2015-10-26 21:36:43 -04:00
Yves Senn
f7881d3e2b invalid sti error message contains the full class name.
This can resolve confusing situation when a top level constant exists
but a namespaced version is identified.

Related to #19531.
2015-05-13 11:35:34 +02:00
Yves Senn
15354b6fd0 Merge branch 'sti-subclass-from-attributes' of https://github.com/agrobbin/rails into agrobbin-sti-subclass-from-attributes
Conflicts:
	activerecord/CHANGELOG.md
2015-05-13 11:08:10 +02:00
Alex Robbin
cbd66b430b allow setting of a demodulized class name when using STI
If your STI class looks like this:

```ruby
class Company < ActiveRecord::Base
  self.store_full_sti_class = false

  class GoodCo < Company
  end

  class BadCo < Company
  end
end
```

The expectation (which is valid) is that the `type` in the database is saved as
`GoodCo` or `BadCo`. However, another expectation should be that setting `type`
to `GoodCo` would correctly instantiate the object as a `Company::GoodCo`. That
second expectation is what this should fix.
2015-05-11 09:02:48 -04:00
Yves Senn
d27974d3fb tests, extract helpers to modify global state.
Make sure that tests do not hardcode the default value.
For example `test_instantiation_doesnt_try_to_require_corresponding_file`
always restored the configuration to `true` regardless of what it's
original value was.

Extract a helper to make the global modification consistent across tests.
2015-05-07 15:04:49 +02:00
Miklos Fazekas
5f6370a81b Always reset changed attributes in becomes
When ```becomes``` changes @attributes it should also change
@changed_attributes. Otherwise we'll experience a kind of split head situation
where attributes are coming from ```self```, but changed_attributes is coming
from ```klass.new```. This affects the inheritance_colmn as it's changed by new
for example.

Fixes #16881
2015-02-04 15:42:14 +01:00
Sean Griffin
8e3b1a632c Test association was eager loaded, rather than reaching into internals 2015-01-26 11:36:13 -07:00
Sean Griffin
b98668decb Go through normal where logic when preloading associations
This will allow eager type casting to take place as needed. There
doesn't seem to be any particular reason that the `in` statement was
forced for single values, and the commit message where it was introduced
gives no context.

See
d90b4e2615
2014-12-26 16:12:56 -07:00
Sean Griffin
08576b94ad Improve the performance of reading attributes
We added a comparison to "id", and call to `self.class.primary_key` a
*lot*. We also have performance hits from `&block` all over the place.
We skip the check in a new method, in order to avoid breaking the
behavior of `read_attribute`
2014-11-18 15:20:19 -08:00
Sean Griffin
8df8334327 Remove dead test code for unsupported adapters 2014-05-17 13:24:25 -06:00
Guo Xiang Tan
3baace687c Use teardown helper method.
Follow-Up to https://github.com/rails/rails/pull/14348

Ensure that SQLCounter.clear_log is called after each test.

This is a step to prevent side effects when running tests. This will allow us to run them in random order.
2014-03-14 20:48:59 -07:00
Jason Meller
03855e790d Ensure AR #second, #third, etc. finders work through associations
This commit fixes two regressions introduced in cafe31a078 where
newly created finder methods #second, #third, #forth, and #fifth
caused a NoMethodError error on reload associations and where we
were pulling the wrong element out of cached associations.

Examples:

  some_book.authors.reload.second

  # Before
  # => NoMethodError: undefined method 'first' for nil:NilClass

  # After
  # => #<Author id: 2, name: "Sally Second", ...>

  some_book.first.authors.first
  some_book.first.authors.second

  # Before
  # => #<Author id: 1, name: "Freddy First", ...>
  # => #<Author id: 1, name: "Freddy First", ...>

  # After
  # => #<Author id: 1, name: "Freddy First", ...>
  # => #<Author id: 2, name: "Sally Second", ...>

Fixes #13783.
2014-01-21 19:35:27 -05:00
Ujjwal Thaakar
e8d1d84837
Don't try to get the subclass if the inheritance column doesn't exist
The `subclass_from_attrs` method is called even if the column specified by
the `inheritance_column` setting doesn't exist. This prevents setting associations
via the attributes hash if the association name clashes with the value of the setting,
typically `:type`. This worked previously in Rails 3.2.
2014-01-14 18:53:45 +05:30
Yves Senn
e95031f55d fix bug in becomes! when changing from base to subclass. Closes #13272. 2014-01-13 15:07:14 +01:00
T.J. Schuck
72bb3fc297 Change all "can not"s to the correct "cannot". 2014-01-03 17:02:31 -05:00
Prem Sichanugrist
68421f330b Port test from cf1904f to avoid future regression
Related issue: #11939, #12084
2013-10-03 14:11:12 -04:00
Nate Berkopec
ab157ac6be Fix #new with an STI object with complex inheritance 2013-04-02 09:50:06 -04:00
Takehiro Adachi
4666108c68 move tests out from base_test.rb
These tests should be in inheritance_test.rb since its testing a
feature which is implemented in inheritance.rb
2013-03-18 15:45:39 +09:00
Takehiro Adachi
8b80311e5f add an missing assertion to inheritance_test.rb
assertion for
https://github.com/rails/rails/blob/ad624345e54bd20802de67b2b5c9ef29ecf5
d5f4/activerecord/lib/active_record/inheritance.rb#L32
2013-03-11 20:27:13 +09:00
Dmitry Vorotilin
b04051d4e0 Fix ActiveRecord subclass_from_attrs when eager_load is false.
It cannot find subclass because all classes are loaded automatically
when it needs.
2013-03-06 11:46:07 +04:00
Carlos Antonio da Silva
7ad590d25f User assert_kind_of, invert assert_equal expectations 2012-11-29 09:59:35 -02:00
Jason Rush
89b5b31cc4 Added STI support to init and building associations
Allows you to do BaseClass.new(:type => "SubClass") as well as
parent.children.build(:type => "SubClass") or parent.build_child
to initialize an STI subclass. Ensures that the class name is a
valid class and that it is in the ancestors of the super class
that the association is expecting.
2012-11-29 05:50:34 +00:00
Jon Leighton
9e4c41c903 Remove ActiveRecord::Model
In the end I think the pain of implementing this seamlessly was not
worth the gain provided.

The intention was that it would allow plain ruby objects that might not
live in your main application to be subclassed and have persistence
mixed in. But I've decided that the benefit of doing that is not worth
the amount of complexity that the implementation introduced.
2012-10-26 15:51:02 +01:00
Yves Senn
9f494a9a34 test cleanup, remove ruby_type because it's no longer needed
All tests with a custom inheritance_column use the `Vegtable` model.
The field ruby_type on the Company models is no longer needed
2012-09-03 20:38:14 +02:00