aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/core.rb
Commit message (Collapse)AuthorAgeFilesLines
* Remove support for the protected attributes gemCarlos Antonio da Silva2015-01-091-10/+2
| | | | Related to #10690.
* Define attribute methods before attempting to populate recordsSean Griffin2015-01-051-1/+1
| | | | | | | | `initialize_internals_callback` will attempt to assign attributes from the current scope, which will fail if something defined the method and calls super (meaning it won't hit `method_missing`). Fixes #18339
* Remove deprecated `ActiveRecord::Base.disable_implicit_join_references=`Rafael Mendonça França2015-01-041-7/+0
|
* Pass a type caster when aliasing tables for joinsSean Griffin2014-12-291-4/+4
|
* Extract an explicit type caster classSean Griffin2014-12-291-7/+5
|
* Rely on the injectable type caster for `arel_table`Sean Griffin2014-12-291-1/+7
| | | | | | | This API will require much less consuming code to change to accomodate the removal of automatic type casting from Arel. As long as the predicates are constructed using the `arel_table` off of an AR subclass, there will be no changes that need to happen.
* Remove `klass` and `arel_table` as a dependency of `PredicateBuilder`Sean Griffin2014-12-261-2/+6
| | | | | | | | | | | | | | | This class cares far too much about the internals of other parts of Active Record. This is an attempt to break out a meaningful object which represents the needs of the predicate builder. I'm not fully satisfied with the name, but the general concept is an object which represents a table, the associations to/from that table, and the types associated with it. Many of these exist at the `ActiveRecord::Base` class level, not as properties of the table itself, hence the need for another object. Currently it provides these by holding a reference to the class, but that will likely change in the future. This allows the predicate builder to remain wholy concerned with building predicates. /cc @mrgilman
* Inject the `PredicateBuilder` into the `Relation` instanceSean Griffin2014-12-261-1/+5
| | | | | | | 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
* Don't perform statement caching for `find` when called from a scopeSean Griffin2014-12-221-0/+1
| | | | | | | | If there is a method defined such as `find_and_do_stuff(id)`, which then gets called on an association, we will perform statement caching and the parent ID will not change on subsequent calls. Fixes #18117
* docs, bring back `ActiveRecord::Core` methods in the API. [ci skip]Yves Senn2014-12-041-1/+0
| | | | | | | | | | | | This `# :nodoc:` had the effect of hiding every method that follows. This meant that the API page for `ActiveRecord::Core` only contained `configurations` and none of the following methods. Furthermore this `# :nodoc:` had no effect on `maintain_test_schema`. Those `mattr_accessor` inside the `included` block are not picked up by rdoc. /cc @zzak
* Stop using `Arel::Table.engine`Sean Griffin2014-11-291-1/+1
| | | | | | | | | | | | | We never actually make use of it on the table, since we're constructing the select manager manually. It looks like if we ever actually were grabbing it from the table, we're grossly misusing it since it's meant to vary by AR class. Its existence on `Arel::Table` appears to be purely for convenience methods that are never used outside of tests. However, in production code it just complicates construction of the tables on the rails side, and the plan is to remove it from `Arel::Table` entirely. I'm not convinced it needs to live on `SelectManager`, etc either.
* Reduce the amount of work performed when instantiating AR modelsSean Griffin2014-11-141-2/+0
| | | | | | | | | | We don't know which attributes will or won't be used, and we don't want to create massive bottlenecks at instantiation. Rather than doing *any* iteration over types and values, we can lazily instantiate the object. The lazy attribute hash should not fully implement hash, or subclass hash at any point in the future. It is not meant to be a replacement, but instead implement its own interface which happens to overlap.
* Treat strings greater than int max value as out of rangeSean Griffin2014-10-311-0/+4
| | | | | | | | | | | Sufficiently large integers cause `find` and `find_by` to raise `StatementInvalid` instead of `RecordNotFound` or just returning `nil`. Given that we can't cast to `nil` for `Integer` like we would with junk data for other types, we raise a `RangeError` instead, and rescue in places where it would be highly unexpected to get an exception from casting. Fixes #17380
* Rename `default_attributes` to `_default_attributes`Sean Griffin2014-10-311-1/+1
| | | | | It is internal use only. This is to avoid conflicting with users' method names. Fixes #17458
* let's warn with heredocsXavier Noria2014-10-281-5/+10
| | | | | | | | | | | | The current style for warning messages without newlines uses concatenation of string literals with manual trailing spaces where needed. Heredocs have better readability, and with `squish` we can still produce a single line. This is a similar use case to the one that motivated defining `strip_heredoc`, heredocs are super clean.
* Prefix internal method with _Rafael Mendonça França2014-10-251-4/+4
| | | | This will avoid naming clash with user defined methods
* Reduce allocations when running AR callbacks.Pete Higgins2014-09-281-4/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Inspired by @tenderlove's work in c363fff29f060e6a2effe1e4bb2c4dd4cd805d6e, this reduces the number of strings allocated when running callbacks for ActiveRecord instances. I measured that using this script: ``` require 'objspace' require 'active_record' require 'allocation_tracer' ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:" ActiveRecord::Base.connection.instance_eval do create_table(:articles) { |t| t.string :name } end class Article < ActiveRecord::Base; end a = Article.create name: "foo" a = Article.find a.id N = 10 result = ObjectSpace::AllocationTracer.trace do N.times { Article.find a.id } end result.sort.each do |k,v| p k => v end puts "total: #{result.values.map(&:first).inject(:+)}" ``` When I run this against master and this branch I get this output: ``` pete@balloon:~/projects/rails/activerecord$ git checkout master M Gemfile Switched to branch 'master' pete@balloon:~/projects/rails/activerecord$ bundle exec ruby benchmark_allocation_with_callback_send.rb > allocations_before pete@balloon:~/projects/rails/activerecord$ git checkout remove-dynamic-send-on-built-in-callbacks M Gemfile Switched to branch 'remove-dynamic-send-on-built-in-callbacks' pete@balloon:~/projects/rails/activerecord$ bundle exec ruby benchmark_allocation_with_callback_send.rb > allocations_after pete@balloon:~/projects/rails/activerecord$ diff allocations_before allocations_after 39d38 < {["/home/pete/projects/rails/activesupport/lib/active_support/callbacks.rb", 81]=>[40, 0, 0, 0, 0, 0]} 42c41 < total: 630 --- > total: 590 ``` In addition to this, there are two micro-optimizations present: * Using `block.call if block` vs `yield if block_given?` when the block was being captured already. ``` pete@balloon:~/projects$ cat benchmark_block_call_vs_yield.rb require 'benchmark/ips' def block_capture_with_yield &block yield if block_given? end def block_capture_with_call &block block.call if block end def no_block_capture yield if block_given? end Benchmark.ips do |b| b.report("block_capture_with_yield") { block_capture_with_yield } b.report("block_capture_with_call") { block_capture_with_call } b.report("no_block_capture") { no_block_capture } end pete@balloon:~/projects$ ruby benchmark_block_call_vs_yield.rb Calculating ------------------------------------- block_capture_with_yield 124979 i/100ms block_capture_with_call 138340 i/100ms no_block_capture 136827 i/100ms ------------------------------------------------- block_capture_with_yield 5703108.9 (±2.4%) i/s - 28495212 in 4.999368s block_capture_with_call 6840730.5 (±3.6%) i/s - 34169980 in 5.002649s no_block_capture 5821141.4 (±2.8%) i/s - 29144151 in 5.010580s ``` * Defining and calling methods instead of using send. ``` pete@balloon:~/projects$ cat benchmark_method_call_vs_send.rb require 'benchmark/ips' class Foo def tacos nil end end my_foo = Foo.new Benchmark.ips do |b| b.report('send') { my_foo.send('tacos') } b.report('call') { my_foo.tacos } end pete@balloon:~/projects$ ruby benchmark_method_call_vs_send.rb Calculating ------------------------------------- send 97736 i/100ms call 151142 i/100ms ------------------------------------------------- send 2683730.3 (±2.8%) i/s - 13487568 in 5.029763s call 8005963.9 (±2.7%) i/s - 40052630 in 5.006604s ``` The result of this is making typical ActiveRecord operations slightly faster: https://gist.github.com/phiggins/e46e51dcc7edb45b5f98
* Fix find_by with associations not working with adequate recordGodfrey Chan2014-09-201-0/+3
| | | | | | | | | For now, we will just skip the cache when a non-column key is used in the hash. If the future, we can probably move some of the logic in PredicateBuilder.expand up the chain to make caching possible for association queries. Closes #16903 Fixes #16884
* Quick fix to address the borken build caused by #15791Godfrey Chan2014-09-201-1/+1
| | | | | | This is pretty lame though, so feel free to send a PR with a better fix! ;) cc @zev @tenderlove
* Backwards compat for activerecord-deprecated_findersstopdropandrew2014-09-161-0/+2
| | | | | | | Maintain compatibility for: * ActiveRecord::Base#find(:all) * ActiveRecord::Base#find(:first) * ActiveRecord::Base#find(:last)
* Allow included modules to override association methods.Yves Senn2014-09-091-2/+0
| | | | | | | | | | Closes #16684. This is achieved by always generating `GeneratedAssociationMethods` when `ActiveRecord::Base` is subclassed. When some of the included modules of `ActiveRecord::Base` were reordered this behavior was broken as `Core#initialize_generated_modules` was no longer called. Meaning that the module was generated on first access.
* Skip StatementCache for eager loaded associations (Fixes #16761)Sammy Larbi2014-09-041-0/+1
| | | | | | Eagerly loaded collection and singular associations are ignored by the StatementCache, which causes errors when the queries they generate reference columns that were not eagerly loaded. This commit skips the creation of the StatementCache as a fix for these scenarios.
* Override #find_by! in core to enable AST cachingGodfrey Chan2014-08-251-0/+4
|
* Fixed find_by("sql fragment without bindings") on masterGodfrey Chan2014-08-251-1/+1
| | | | | | | | | | | * Also duplicated find_by tests from relations_test.rb to finder_test.rb now that we have a completely different implementation on the class (in core.rb with AST caching stuff). * Also removed a (failing) test that used mocks. Now that we have tests for the behavior, there's no point having another test that tests the implementation (that it delegates). Further, what the test was implying is nolonger true with the current implementation, because Class.find_by is a real method now.
* Merge pull request #15718 from chancancode/regression_from_15694Godfrey Chan2014-07-161-0/+5
|\ | | | | Fixed a regression introduced in 84cf156
| * Fixed a regression introduced in 84cf156Godfrey Chan2014-06-141-0/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 84cf156 (PR #15694) introduced a subtle regression. There are actually three distinct entry points to creating an AR object – via .new (i.e. #initialize), via #init_with (e.g. from YAML or database queries) and via .allocate. With the patch in 84cf156, attribute methods and respond_to? will not work correctly when objects are allocated directly, without going through either The reason this test case didn't catch the regression was that the `Topic` class is shared between test cases, so by the time this test case is ran the attribute methods are very likely to be defined. Switching to use a fresh anonymous class in the test to ensure we surface this problem in the future.
* | Merge pull request #16015 from sgrif/sg-ensure-initializedRafael Mendonça França2014-07-021-4/+1
|\ \ | | | | | | | | | | | | | | | | | | Move pk initialization logic onto `AttributeSet` Conflicts: activerecord/lib/active_record/attribute_set.rb
| * | Move pk initialization logic onto `AttributeSet`Sean Griffin2014-07-021-4/+1
| | | | | | | | | | | | Better encapsulates its internals from `ActiveRecord::Base`.
* | | Don't error when `dup`ing a record with no PKSean Griffin2014-07-021-2/+1
|/ /
* | Simplify creation of default attributes on AR instanceSean Griffin2014-06-291-6/+1
| | | | | | | | `AttributeSet#dup` has all the behavior we need.
* | Move writing unknown column exception to null attributeSean Griffin2014-06-261-1/+1
| | | | | | | | | | | | Making this change revealed several subtle bugs related to models with no primary key, and anonymous classes. These have been fixed as well, with regression tests added.
* | Encapsulate the creation of `Attribute` objectsSean Griffin2014-06-261-2/+2
| | | | | | | | | | | | | | | | This will make it less painful to add additional properties, which should persist across writes, such as `name`. Conflicts: activerecord/lib/active_record/attribute_set.rb
* | Remove unneeded `@column_types` instance variableSean Griffin2014-06-221-2/+0
| | | | | | | | This was used more previously, but other uses have been removed.
* | Return a null object from `AttributeSet#[]`Sean Griffin2014-06-201-1/+3
| |
* | docs, configurations method is listed in the docs. [ci skip]Yves Senn2014-06-201-1/+0
| | | | | | | | | | The :singleton-method: directive is printed in the docs. This directive is not necessary as the method is documentable just fine.
* | Introduce an object to aid in creation and management of `@attributes`Sean Griffin2014-06-191-4/+3
|/ | | | | Mostly delegation to start, but we can start moving a lot of behavior in bulk to this object.
* Remove unused column types overrideSean Griffin2014-06-131-3/+0
|
* Merge pull request #15689 from sgrif/sg-attribute-methodsMatthew Draper2014-06-141-0/+1
|\ | | | | Ensure we always define attribute methods
| * Ensure we always define attribute methodsSean Griffin2014-06-131-0/+1
| |
* | Merge pull request #15593 from sgrif/sg-attributeRafael Mendonça França2014-06-131-19/+18
|\ \ | |/ |/| Introduce an Attribute object to handle the type casting dance
| * Introduce an Attribute object to handle the type casting danceSean Griffin2014-06-131-19/+18
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | There's a lot more that can be moved to these, but this felt like a good place to introduce the object. Plans are: - Remove all knowledge of type casting from the columns, beyond a reference to the cast_type - Move type_cast_for_database to these objects - Potentially make them mutable, introduce a state machine, and have dirty checking handled here as well - Move `attribute`, `decorate_attribute`, and anything else that modifies types to mess with this object, not the columns hash - Introduce a collection object to manage these, reduce allocations, and not require serializing the types
* | Defer to super, rather than re-implementing Object#hashSean Griffin2014-06-121-1/+5
| |
* | Fix performance regression on preloading HABTM associationsSean Griffin2014-06-121-1/+1
|/ | | | | | | | | | | We'd spend a lot of time calling `hash` and `eql?` on the join model, which has no primary key. Calling `id` with no primary key is a really slow way to get back `nil`, so we can improve the performance there. However, even with the escape clause, we *still* weren't getting high enough performance, as we were checking the primary key too much. `hash` will always return `nil.hash` for records with no id, and `==` will always return `false`. We can optimize those cases in the HABTM join model.
* Keep the types of virtual columns after yaml serializationSean Griffin2014-06-101-0/+1
| | | | | On MySQL and PostgreSQL, the adapter does not type cast virtual columns for us.
* Move conditionals about freezing closer to the definition of `freeze`Sean Griffin2014-06-071-0/+6
| | | | | | | Reduces the number of places that care about the internals of how we store and type cast attributes. We do not need to go through the dup/freeze dance, as you couldn't have saved a frozen new record anyway, and that is the only time we would end up modifying the frozen hash.
* Bring type casting behavior of hstore/json in line with serializedSean Griffin2014-06-041-3/+6
| | | | | `@raw_attributes` should not contain the type-cast, mutable version of the value.
* Merge pull request #15172 from notEthan/active_record_pretty_printRafael Mendonça França2014-06-031-0/+23
|\ | | | | | | | | | | | | implement ActiveRecord::Base#pretty_print Conflicts: activerecord/CHANGELOG.md
| * implement ActiveRecord::Base#pretty_print + changelogEthan2014-05-291-0/+23
| |
* | Keep column defaults in type cast formSean Griffin2014-06-031-1/+1
| | | | | | | | | | | | | | | | | | | | The contract of `_field_changed?` assumes that the old value is always type cast. That is not the case for the value in `Column#default` as things are today. It appears there are other public methods that assume that `Column#default` is type cast, as well. The reason for this change originally was because the value gets put into `@raw_attributes` in initialize. This reverts to the old behavior on `Column`, and updates `initialize` to make sure that the values are in the right format.
* | Remove unused `initialize_attributes` methodSean Griffin2014-06-021-3/+2
| | | | | | | | | | This was previously a hook for a special case related to `serialize`, which has since been removed.