aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/inheritance.rb
Commit message (Collapse)AuthorAgeFilesLines
* Enable `Layout/EmptyLinesAroundAccessModifier` copRyuta Kamizono2019-06-131-3/+0
| | | | | | | | | | | We sometimes say "✂️ newline after `private`" in a code review (e.g. https://github.com/rails/rails/pull/18546#discussion_r23188776, https://github.com/rails/rails/pull/34832#discussion_r244847195). Now `Layout/EmptyLinesAroundAccessModifier` cop have new enforced style `EnforcedStyle: only_before` (https://github.com/rubocop-hq/rubocop/pull/7059). That cop and enforced style will reduce the our code review cost.
* Use placeholder for `type_condition` predicateRyuta Kamizono2019-02-181-1/+1
| | | | | | | | | | | | | | Before: ``` SELECT "comments".* FROM "comments" WHERE "comments"."type" IN ('VerySpecialComment') AND "comments"."post_id" = ? LIMIT ? [["post_id", 4], ["LIMIT", 1]] ``` After: ``` SELECT "comments".* FROM "comments" WHERE "comments"."type" = ? AND "comments"."post_id" = ? LIMIT ? [["type", "VerySpecialComment"], ["post_id", 4], ["LIMIT", 1]] ```
* Add `Style/RedundantFreeze` to remove redudant `.freeze`Yasuo Honda2018-09-291-1/+1
| | | | | | | | | | | | | | | | | | | | | Since Rails 6.0 will support Ruby 2.4.1 or higher `# frozen_string_literal: true` magic comment is enough to make string object frozen. This magic comment is enabled by `Style/FrozenStringLiteralComment` cop. * Exclude these files not to auto correct false positive `Regexp#freeze` - 'actionpack/lib/action_dispatch/journey/router/utils.rb' - 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb' It has been fixed by https://github.com/rubocop-hq/rubocop/pull/6333 Once the newer version of RuboCop released and available at Code Climate these exclude entries should be removed. * Replace `String#freeze` with `String#-@` manually if explicit frozen string objects are required - 'actionpack/test/controller/test_case_test.rb' - 'activemodel/test/cases/type/string_test.rb' - 'activesupport/lib/active_support/core_ext/string/strip.rb' - 'activesupport/test/core_ext/string_ext_test.rb' - 'railties/test/generators/actions_test.rb'
* Refactor object creation from relation to avoid pushing scope attributesRyuta Kamizono2018-09-111-0/+4
| | | | | | Pushing scope attributes was added at d4007d5 for fixing inheritance object creation. But it was not a better fix, since we could just pull that on demand in `Inheritance` module.
* Add AR::Base.base_class? predicateBogdan Gusiev2018-04-021-1/+7
|
* Extract all `base_class.name` as `polymorphic_name`Ryuta Kamizono2018-03-041-0/+4
| | | | | | | This is an alternative of #29722, and follow up of #32048. This does not change the current behavior, but makes it easier to modify all polymorphic names consistently.
* Expand AR::Base.abstract_class documentationSam Bostock2018-02-201-10/+36
| | | | | | | | | | | | The previous documentation is somewhat unclear about the use case for an abstract ActiveRecord class. This clears it up by highlighting the following points: - table_name is not derived from the abstract class' name - type is not derived on direct descendants of the abstract class - validations, not abstract_class, should be used to specify whether the parent model can be instantiated or not
* Fix inheritance object creation from relationRyuta Kamizono2017-12-131-4/+3
| | | | | | | | | | 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.
* Update links to use https instead of http [ci skip]Yoshiyuki Hirano2017-08-221-1/+1
|
* Use frozen-string-literal in ActiveRecordKir Shatrov2017-07-191-0/+2
|
* Improve the performance of writing attributesEugene Kenny2017-06-181-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Using a similar approach to 08576b94ad4f19dfc368619d7751e211d23dcad8, this change adds a new internal `_write_attribute` method which bypasses the code that checks for attribute aliases and custom primary keys. We can use this method instead of `write_attribute` when we know that we have the name of the actual column to be updated and not an alias. This makes writing an attribute with `attribute=` about 18% faster. Benchmark: ``` begin require "bundler/inline" rescue LoadError => e $stderr.puts "Bundler version 1.10 or later is required. Please update your Bundler" raise e end gemfile(true) do source "https://rubygems.org" gem "rails", github: "rails/rails" gem "arel", github: "rails/arel" gem "sqlite3" gem "benchmark-ips" end require "active_record" ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:") ActiveRecord::Schema.define do create_table :posts, force: true do |t| end end class Post < ActiveRecord::Base end post = Post.new(id: 1) Benchmark.ips do |x| x.report("attribute=") { post.id = post.id + 1 } end ``` Before: Warming up -------------------------------------- attribute= 25.889k i/100ms Calculating ------------------------------------- attribute= 290.946k (± 3.1%) i/s - 1.476M in 5.077036s After: Warming up -------------------------------------- attribute= 30.056k i/100ms Calculating ------------------------------------- attribute= 345.088k (± 4.8%) i/s - 1.743M in 5.064264s
* Add option for class_attribute default (#29270)David Heinemeier Hansson2017-05-291-2/+1
| | | | | | | | | | | | * Allow a default value to be declared for class_attribute * Convert to using class_attribute default rather than explicit setter * Removed instance_accessor option by mistake * False is a valid default value * Documentation
* Performance optimization for ActiveRecord#subclass_from_attributesMichael Lovitt2017-05-241-1/+1
| | | | | This change addresses slowness in ActiveRecord initialization introduced starting in Rails 5.0.
* Cache results of computing model typeKonstantin Lazarev2017-01-031-2/+15
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 ```
* Fix broken comments indentation caused by rubocop auto-correct [ci skip]Ryuta Kamizono2016-09-141-12/+12
| | | | | | All indentation was normalized by rubocop auto-correct at 80e66cc4d90bf8c15d1a5f6e3152e90147f00772. But comments was still kept absolute position. This commit aligns comments with method definitions for consistency.
* normalizes indentation and whitespace across the projectXavier Noria2016-08-061-66/+66
|
* applies new string literal convention in activerecord/libXavier Noria2016-08-061-1/+1
| | | | | The current code base is not uniform. After some discussion, we have chosen to go with double quotes by default.
* [ci skip] Update Documentation on ActiveRecord::InheritanceAlex Kitchens2016-06-231-1/+2
|
* Defer Arel attribute lookup to the model classMatthew Draper2016-02-041-1/+1
| | | | | This still isn't as separated as I'd like, but it at least moves most of the burden of alias mapping in one place.
* Do not use default attributes for STI when instantiating a subclassSean Griffin2016-01-271-1/+5
| | | | | | | | | | 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.
* run `type` column through attribtues API type casting.Yves Senn2016-01-191-0/+1
| | | | | | | Closes #21986. This makes it possible to write custom types that define a different mapping for STI columns.
* Remove old comment about AC::Parameters>subclassesclaudiob2015-12-021-2/+0
| | | | | | | | | | | | [ci skip] Q: What happens if you initialize an AR model by passing Parameters that have not been whitelisted with `permit`? A: An `ActiveModel::ForbiddenAttributesError` is raised. I think this behavior is correct, and it's better than what used to happen, with unpermitted parameter being simply ignored.
* don't rely on the columns hash to get defaults. follow-up to #17169.Yves Senn2015-12-021-7/+1
| | | | | | This will also get the defaults from attribute definitions like: attribute :type, :string, default: "SomethingElse"
* add `ActiveRecord::Base.has_attribute?`Yves Senn2015-12-021-2/+2
| | | | `has_attribute?` method to check wether a given attribute has been defined.
* Merge pull request #17169 from kuldeepaggarwal/fix-STI-default-typeYves Senn2015-12-021-9/+13
|\ | | | | | | STI cast new instances to `default type` on initialize.
| * STI cast new instances to `default type` on initialize.Kuldeep Aggarwal2015-12-021-0/+12
|/ | | | fixes #17121
* Update and fix forbidden attributes testsThomas Walpole2015-11-031-1/+2
| | | | Add AC::Parameters tests for WhereChain#not
* Fix a stylistic nitpick in #19501Sean Griffin2015-10-291-3/+3
| | | | | | | We don't need to use `String#+` or create all the intermediate strings to break a string into multiple lines. We can just write a c-style multiline string literal. This is by no means a hotpath, but this is clearer to me anyway.
* Fix test failures caused by #19501Sean Griffin2015-10-291-1/+1
| | | | | | | | | | | | | | | | | | | | | The first one is quite straightforward. We want to give the proper error message in the case where a top level constant exists, but we're looking for a nested one. We just need to port over the change to use `subclass.name` into these changes. The second set of failures, which are only present in the mysql adapter tests, are stranger to me. The failure occurs because we were previously comparing `subclass.name == self.name` instead of `subclass == self`. However, I don't think that we need to support creating anonymous classes which share a table with a class that uses STI, overrides `name` to return the same name as athe class that we have no other relationship with, when not assigned to a constant so it could never be used anyway... The commits around why that exist give no context, and I think they're just poorly written tests (WTF does `test_schema` mean anyway, and why does calling `.first` on some anonymous class test it?). We'll just disable STI on that class.
* Fix merge conflicts from #19501Sean Griffin2015-10-291-20/+18
|\ | | | | | | | | | | | | | | I'm making this commit separately because this has failing tests and style nitpicks that I'd like to make as individual commits, to make the changes I'm making explicit. We still want a single merge commit at the end, however.
| * DRY up STI subclass logicCody Cutrer2015-03-241-19/+19
| | | | | | | | | | | | | | | | | | | | | | the newer method used for discriminating new records did not use the older and more robust method used for instantiating existing records, but did have a better post-check to ensure the sublass was in the hierarchy. so move the descendants check to find_sti_class, and then simply call find_sti_class from subclass_from_attributes now with fixed specs
* | Replace AR with ActiveRecord to make it more readable [ci skip]arvind2015-09-081-1/+1
| |
* | invalid sti error message contains the full class name.Yves Senn2015-05-131-1/+1
| | | | | | | | | | | | | | This can resolve confusing situation when a top level constant exists but a namespaced version is identified. Related to #19531.
* | allow setting of a demodulized class name when using STIAlex Robbin2015-05-111-6/+8
|/ | | | | | | | | | | | | | | | | | | | | 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.
* Revert "Merge pull request #19500 from ccutrer/dry_sti_subclass_finding"Rafael Mendonça França2015-03-241-19/+19
| | | | | | | This reverts commit 5cfa6a8ab997089c3012a82052c8c317b2e095f5, reversing changes made to bfd5bf8313e6ea0bb2eccb68ee5076bb63f0b2db. Reason: This broken travis build.
* DRY up STI subclass logicCody Cutrer2015-03-241-19/+19
| | | | | | | | | the newer method used for discriminating new records did not use the older and more robust method used for instantiating existing records, but did have a better post-check to ensure the sublass was in the hierarchy. so move the descendants check to find_sti_class, and then simply call find_sti_class from subclass_from_attributes
* Attribute assignment and type casting has nothing to do with columnsSean Griffin2015-01-311-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | It's finally finished!!!!!!! The reason the Attributes API was kept private in 4.2 was due to some publicly visible implementation details. It was previously implemented by overloading `columns` and `columns_hash`, to make them return column objects which were modified with the attribute information. This meant that those methods LIED! We didn't change the database schema. We changed the attribute information on the class. That is wrong! It should be the other way around, where schema loading just calls the attributes API for you. And now it does! Yes, this means that there is nothing that happens in automatic schema loading that you couldn't manually do yourself. (There's still some funky cases where we hit the connection adapter that I need to handle, before we can turn off automatic schema detection entirely.) There were a few weird test failures caused by this that had to be fixed. The main source came from the fact that the attribute methods are now defined in terms of `attribute_names`, which has a clause like `return [] unless table_exists?`. I don't *think* this is an issue, since the only place this caused failures were in a fake adapter which didn't override `table_exists?`. Additionally, there were a few cases where tests were failing because a migration was run, but the model was not reloaded. I'm not sure why these started failing from this change, I might need to clear an additional cache in `reload_schema_from_cache`. Again, since this is not normal usage, and it's expected that `reset_column_information` will be called after the table is modified, I don't think it's a problem. Still, test failures that were unrelated to the change are worrying, and I need to dig into them further. Finally, I spent a lot of time debugging issues with the mutex used in `define_attribute_methods`. I think we can just remove that method entirely, and define the attribute methods *manually* in the call to `define_attribute`, which would simplify the code *tremendously*. Ok. now to make this damn thing public, and work on moving it up to Active Model.
* Remove deprecated `symbolized_base_class` and `symbolized_sti_name`Rafael Mendonça França2015-01-041-10/+0
|
* Remove all cases of manuallly wrapping `Arel::Nodes::Quoted`Sean Griffin2014-12-291-1/+0
| | | | | | | | | | 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.
* We don't need to perform type casting on the STI conditionSean Griffin2014-12-261-0/+1
| | | | | | | We will always have the correct type for this query, so no casting is needed. We inform Arel that we already have the right type by wrapping it in an `Arel::Nodes::Quoted` (which we will no longer need to do in Rails 5.1)
* Pass symbol as an argument instead of a blockErik Michaels-Ober2014-11-291-1/+1
|
* Revert "Improve performance of AR object instantiation"Sean Griffin2014-11-141-8/+4
| | | | | | | | | | This reverts commit 8fee923888192a658d8823b31e77ed0683dfd665. Conflicts: activerecord/lib/active_record/attribute_set/builder.rb This solution sucks, and is hard to actually apply across the board. Going to try other solutions
* Improve performance of AR object instantiationSean Griffin2014-11-051-4/+8
| | | | | | | We introduced a performance hit by adding an additional iteration through a model's attributes on creation. We don't actually need the values from `Result` to be a hash, we can separate the columns and values and zip them up ourself during the iteration that we have to do.
* edit pass over all warningsXavier Noria2014-10-281-2/+2
| | | | | | | | | | | | | | | This patch uniformizes warning messages. I used the most common style already present in the code base: * Capitalize the first word. * End the message with a full stop. * "Rails 5" instead of "Rails 5.0". * Backticks for method names and inline code. Also, converted a few long strings into the new heredoc convention.
* Merge pull request #15762 from arthurnn/better_error_on_bad_alias_methodMatthew Draper2014-07-181-8/+2
|\ | | | | | | Dont swallow errors when bad alias_method
| * Dont swallow errors when bad alias_methodArthur Neves2014-06-241-8/+2
| |
* | Tiny follow-up to #15987 and 088b4c3e [ci skip]Robin Dupret2014-07-021-4/+4
| |
* | Move STI docs off of the main Base document, leaving a noteSean Griffin2014-06-301-0/+31
|/
* Move changed_attributes into dirty.rbKeenan Brock2014-01-221-0/+10
| | | Move serialization dirty into serialization.rb
* Don't try to get the subclass if the inheritance column doesn't existUjjwal Thaakar2014-01-141-7/+15
| | | | | | | 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.