aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/attribute_set
Commit message (Collapse)AuthorAgeFilesLines
* [Active Record] require => require_relativeAkira Matsuda2017-07-011-1/+1
|
* Describe what we are protectingAkira Matsuda2016-12-232-0/+4
|
* normalizes indentation and whitespace across the projectXavier Noria2016-08-062-20/+20
|
* applies new string literal convention in activerecord/libXavier Noria2016-08-062-5/+5
| | | | | The current code base is not uniform. After some discussion, we have chosen to go with double quotes by default.
* Correct the behavior of virtual attributes on models loaded from the dbSean Griffin2016-07-251-7/+21
| | | | | | | | | | | | | | | | | | | | | | | | | | | Previously we had primarily tested the behavior of these attributes by calling `.new`, allowing this to slip through the cracks. There were a few ways in which they were behaving incorrectly. The biggest issue was that attempting to read the attribute would through a `MissingAttribute` error. We've corrected this by returning the default value when the attribute isn't backed by a database column. This is super special cased, but I don't see a way to avoid this conditional. I had considered handling this higher up in `define_default_attribute`, but we don't have the relevant information there as users can provide new defaults for database columns as well. Once I corrected this, I had noticed that the attributes were always being marked as changed. This is because the behavior of `define_default_attribute` was treating them as assigned from `Attribute::Null`. Finally, with our new implementation, `LazyAttributeHash` could no longer be marshalled, as it holds onto a proc. This has been corrected as well. I've not handled YAML in that class, as we do additional work higher up to avoid YAML dumping it at all. Fixes #25787 Close #25841
* nodoc `ActiveRecord::AttributeSet::YAMLEncoder`Jon Moss2016-06-241-1/+1
| | | | | | | | | As mentioned in 7b86ea6715ee987e61a7f3bd8e72b1bbfcfbbbe7, this is an internal class. [ci skip] r? @sgrif
* Revert "[ci skip] better docs for ↵Jon Moss2016-06-241-17/+0
| | | | | | | | ActiveRecord::AttributeSet::YAMLEncoder#decode" This reverts commit 7ea502ae141fc26b736c7a73bdf7a676b1f9fc87, per internal discussion with @sgrif -- this is documenting the implementation of a class that isn't intended to be public API.
* [ci skip] better docs for ActiveRecord::AttributeSet::YAMLEncoder#decodeDavid Elliott2016-06-211-0/+17
|
* Make Active Record emit significantly smaller YAMLSean Griffin2016-05-312-1/+40
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This reduces the size of a YAML encoded Active Record object by ~80% depending on the number of columns. There were a number of wasteful things that occurred when we encoded the objects before that have resulted in numerous wins - We were emitting the result of `attributes_before_type_cast` as a hack to work around some laziness issues - The name of an attribute was emitted multiple times, since the attribute objects were in a hash keyed by the name. We now store them in an array instead, and reconstruct the hash using the name - The types were included for every attribute. This would use backrefs if multiple objects were encoded, but really we don't need to include it at all unless it differs from the type at the class level. (The only time that will occur is if the field is the result of a custom select clause) - `original_attribute:` was included over and over and over again since the ivar is almost always `nil`. We've added a custom implementation of `encode_with` on the attribute objects to ensure we don't write the key when the field is `nil`. This isn't without a cost though. Since we're no longer including the types, an object can find itself in an invalid state if the type changes on the class after serialization. This is the same as 4.1 and earlier, but I think it's worth noting. I was worried that I'd introduce some new state bugs as a result of doing this, so I've added an additional test that asserts mutation not being lost as the result of YAML round tripping. Fixes #25145
* Implement equality comparison on `AttributeSet` and friendsSean Griffin2015-10-061-11/+19
| | | | | | | Any gems or libraries which do work with serialization or YAML will ultimately need to compare these objects (albeit indirectly) to ensure correctness. These will likely never get used internally (as they're slow), but we should still expose them for others.
* Separate `dup` from `deep_dup` in the attributes hashSean Griffin2015-09-281-1/+7
| | | | | | | | | | | I'm looking to move towards a tree-like structure for dirty checking that involves an attribute holding onto the attribute that it was created from. This means that `changed?` can be fully encapsulated on that object. Since the objects are immutable, in `changes_applied`, we can simply perform a shallow dup, instead of a deep one. I'm not sure if that will actually end up in a performance boost, but I'd like to semantically separate these concepts regardless
* Explicitly require AR/attribute where using itAkira Matsuda2015-09-101-0/+2
| | | | | autoloading this could possibly cause some weird race condition when calling an AR::Attribute's singleton method on a threaded server.
* Maintain a consistent order in `ActiveRecord::Base#attributes`Sean Griffin2015-02-101-1/+11
| | | | Fixes #18871
* Remove `AttributeSet#initialized_keys`Sean Griffin2015-01-311-5/+1
| | | | | | | | | This method doesn't need to be lazy, as it is never called from reads. The only time it is called are in write cases, where we're about to loop through the results of it, and build the attribute objects anyway. So we don't gain anything by dodging the instantiation here. This is the only method that coupled `AttributeSet` to `LazyAttributeHash`, so removing it puts us back in a place where we can use a normal hash instead.
* Don't error when `attributes` is called on a frozen AR modelSean Griffin2014-12-081-1/+3
| | | | | | | | | | | | | | | | | | `freeze` will ultimately end up freezing the `AttributeSet`, which in turn freezes its `@attributes` hash. However, we actually insert a special object to lazily instantiate the values of the hash on demand. When it does need to actually instantiate all of them for iteration (the only case is `ActiveRecord::Base#attributes`, which calls `AttributeSet#to_h`), it will set an instance variable as a performance optimization Since it's just an optimization for subsequent calls, and that method being called at all is a very uncommon case, we can just leave the ivar alone if we're frozen, as opposed to coming up with some overly complicated mechanism for freezing which allows us to continue to modify ourselves. Fixes #17960
* Remove needless call to `key?` when building attributesSean Griffin2014-11-181-2/+4
| | | | This appears to be a performance hotspot, see #17655.
* LazyAttributeHash is privateSean Griffin2014-11-181-1/+1
|
* Remove call to `key?` in `LazyAttributeHash#[]`Sean Griffin2014-11-181-5/+1
| | | | Performance improvement, as well as improved code clarity
* Remove pointless `private`Sean Griffin2014-11-171-2/+0
| | | | This class no longer has any private methods
* Don't freeze the same hash we use for memoizationSean Griffin2014-11-141-6/+7
|
* Allow `LazyAttributeHash` to be marshalledSean Griffin2014-11-141-13/+17
| | | | | | | | `default_proc` makes a hash unmarshallable, and adds unneccessary overhead. Since we control all access to the hash, let's just handle it in that method. This has the side effect of improving performance on initialization (but not neccessarily on access). We'll need to profile further once the tests are passing.
* Correctly determine if an attribute is uninitializedSean Griffin2014-11-141-1/+1
| | | | | | | In real usage, we give the builder a types hash with a default value of `Type::Value.new`. This means we need to explicitly check for the key, rather than the truthiness of the type to determine if it's a known but uninitialized attribute
* Reduce the amount of work performed when instantiating AR modelsSean Griffin2014-11-141-15/+63
| | | | | | | | | | 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.
* Revert "Improve performance of AR object instantiation"Sean Griffin2014-11-141-18/+3
| | | | | | | | | | 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
* Remove unneccesary default parametersSean Griffin2014-11-051-1/+1
|
* Improve performance of AR object instantiationSean Griffin2014-11-051-3/+18
| | | | | | | 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.
* some object allocation reduction for new AR objectsAaron Patterson2014-09-271-2/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | Benchmark: ```ruby require 'objspace' require 'active_record' 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 ObjectSpace::AllocationTracer.trace do N.times { Article.find a.id } end ObjectSpace::AllocationTracer.allocated_count_table table.sort_by { |_,x| x }.each do |k,v| p k => (v / N) end ```
* `Attribute` should know about its nameSean Griffin2014-06-261-4/+3
| | | | | This allows using polymorphism for the uninitialized attributes raising an exception behavior.
* Encapsulate the creation of `Attribute` objectsSean Griffin2014-06-261-1/+1
| | | | | | | | 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
* Move behavior of `read_attribute` to `AttributeSet`Sean Griffin2014-06-251-0/+33
Moved `Builder` to its own file, as it started looking very weird once I added private methods to the `AttributeSet` class and the `Builder` class started to grow. Would like to refactor `fetch_value` to change to ```ruby self[name].value(&block) ``` But that requires the attributes to know about their name, which they currently do not.