Module: ActiveRecord::AttributeMethods
Relationships & Source Files | |
Namespace Children | |
Modules:
| |
Classes:
| |
Extension / Inclusion / Inheritance Descendants | |
Included In:
| |
Super Chains via Extension / Inclusion / Inheritance | |
Class Chain:
|
|
Instance Chain:
|
|
Defined in: | activerecord/lib/active_record/attribute_methods.rb, activerecord/lib/active_record.rb, activerecord/lib/active_record/attribute_methods/before_type_cast.rb, activerecord/lib/active_record/attribute_methods/composite_primary_key.rb, activerecord/lib/active_record/attribute_methods/dirty.rb, activerecord/lib/active_record/attribute_methods/primary_key.rb, activerecord/lib/active_record/attribute_methods/query.rb, activerecord/lib/active_record/attribute_methods/read.rb, activerecord/lib/active_record/attribute_methods/serialization.rb, activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb, activerecord/lib/active_record/attribute_methods/write.rb |
Constant Summary
-
RESTRICTED_CLASS_METHODS =
# File 'activerecord/lib/active_record/attribute_methods.rb', line 23%w(private public protected allocate new name superclass)
::ActiveModel::AttributeMethods
- Included
::ActiveModel::AttributeMethods
- Attributes & Methods
- .attribute_aliases rw
- #attribute_aliases readonly
- .attribute_aliases? ⇒ Boolean rw
- #attribute_aliases? ⇒ Boolean readonly
- .attribute_method_patterns rw
- #attribute_method_patterns readonly
- .attribute_method_patterns? ⇒ Boolean rw
- #attribute_method_patterns? ⇒ Boolean readonly
Class Method Summary
- .dangerous_attribute_methods Internal use only
::ActiveSupport::Concern
- Extended
class_methods | Define class methods from given block. |
included | Evaluate given block in context of base class, so that you can write class macros here. |
prepended | Evaluate given block in context of base class, so that you can write class macros here. |
append_features, prepend_features |
::ActiveSupport::Autoload
- Extended
Instance Method Summary
-
#[](attr_name)
Returns the value of the attribute identified by
attr_name
after it has been type cast. -
#[]=(attr_name, value)
Updates the attribute identified by
attr_name
using the specifiedvalue
. -
#accessed_fields
Returns the name of all database fields which have been read from this model.
-
#attribute_for_inspect(attr_name)
Returns an
#inspect
-like string for the value of the attributeattr_name
. -
#attribute_names
Returns an array of names for the attributes available on this object.
-
#attribute_present?(attr_name) ⇒ Boolean
Returns
true
if the specifiedattribute
has been set by the user or by a database load and is neithernil
norempty?
(the latter only applies to objects that respond toempty?
, most notably Strings). -
#attributes
Returns a hash of all the attributes with their names as keys and the values of the attributes as values.
-
#has_attribute?(attr_name) ⇒ Boolean
Returns
true
if the given attribute is in the attributes hash, otherwisefalse
. -
#respond_to?(name, include_private = false) ⇒ Boolean
A Person object with a name attribute can ask
person.respond_to?(:name)
,person.respond_to?(:name=)
, andperson.respond_to?(:name?)
which will all returntrue
. - #attribute_method?(attr_name) ⇒ Boolean private
-
#attributes_for_create(attribute_names)
private
Filters out the virtual columns and also primary keys, from the attribute names, when the primary key is to be generated (e.g.
-
#attributes_for_update(attribute_names)
private
Filters the primary keys, readonly attributes and virtual columns from the attribute names.
- #attributes_with_values(attribute_names) private
- #format_for_inspect(name, value) private
- #method_missing(name) private
- #pk_attribute?(name) ⇒ Boolean private
- #respond_to_missing?(name, include_private = false) ⇒ Boolean private
- #_has_attribute?(attr_name) ⇒ Boolean Internal use only
::ActiveModel::AttributeMethods
- Included
#attribute_missing |
|
#method_missing | Allows access to the object attributes, which are held in the hash returned by #attributes, as though they were first-class methods. |
#respond_to?, | |
#respond_to_without_attributes? | A |
#_read_attribute, #attribute_method?, | |
#matched_attribute_method | Returns a struct representing the matching attribute method. |
#missing_attribute |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(name) (private)
[ GitHub ]# File 'activerecord/lib/active_record/attribute_methods.rb', line 474
def method_missing(name, ...) unless self.class.attribute_methods_generated? if self.class.method_defined?(name) # The method is explicitly defined in the model, but calls a generated # method with super. So we must resume the call chain at the right step. last_method = method(name) last_method = last_method.super_method while last_method.super_method self.class.define_attribute_methods if last_method.super_method return last_method.super_method.call(...) end elsif self.class.define_attribute_methods # Some attribute methods weren't generated yet, we retry the call return public_send(name, ...) end end super end
DSL Calls
included
[ GitHub ]11 12 13 14 15 16 17 18 19 20 21
# File 'activerecord/lib/active_record/attribute_methods.rb', line 11
included do initialize_generated_modules include Read include Write include BeforeTypeCast include Query include PrimaryKey include TimeZoneConversion include Dirty include Serialization end
Class Attribute Details
.attribute_aliases (rw)
[ GitHub ]# File 'activemodel/lib/active_model/attribute_methods.rb', line 71
class_attribute :attribute_aliases, instance_writer: false, default: {}
.attribute_aliases? ⇒ Boolean
(rw)
[ GitHub ]
# File 'activemodel/lib/active_model/attribute_methods.rb', line 71
class_attribute :attribute_aliases, instance_writer: false, default: {}
.attribute_method_patterns (rw)
[ GitHub ]# File 'activemodel/lib/active_model/attribute_methods.rb', line 72
class_attribute :attribute_method_patterns, instance_writer: false, default: [ ClassMethods::AttributeMethodPattern.new ]
.attribute_method_patterns? ⇒ Boolean
(rw)
[ GitHub ]
# File 'activemodel/lib/active_model/attribute_methods.rb', line 72
class_attribute :attribute_method_patterns, instance_writer: false, default: [ ClassMethods::AttributeMethodPattern.new ]
Class Method Details
.dangerous_attribute_methods
# File 'activerecord/lib/active_record/attribute_methods.rb', line 30
def dangerous_attribute_methods # :nodoc: @dangerous_attribute_methods ||= ( Base.instance_methods + Base.private_instance_methods - Base.superclass.instance_methods - Base.superclass.private_instance_methods + %i[__id__ dup freeze frozen? hash class clone] ).map { |m| -m.to_s }.to_set.freeze end
Instance Attribute Details
#attribute_aliases (readonly)
[ GitHub ]# File 'activemodel/lib/active_model/attribute_methods.rb', line 71
class_attribute :attribute_aliases, instance_writer: false, default: {}
#attribute_aliases? ⇒ Boolean
(readonly)
[ GitHub ]
# File 'activemodel/lib/active_model/attribute_methods.rb', line 71
class_attribute :attribute_aliases, instance_writer: false, default: {}
#attribute_method_patterns (readonly)
[ GitHub ]# File 'activemodel/lib/active_model/attribute_methods.rb', line 72
class_attribute :attribute_method_patterns, instance_writer: false, default: [ ClassMethods::AttributeMethodPattern.new ]
#attribute_method_patterns? ⇒ Boolean
(readonly)
[ GitHub ]
# File 'activemodel/lib/active_model/attribute_methods.rb', line 72
class_attribute :attribute_method_patterns, instance_writer: false, default: [ ClassMethods::AttributeMethodPattern.new ]
Instance Method Details
#[](attr_name)
Returns the value of the attribute identified by attr_name
after it has been type cast. (For information about specific type casting behavior, see the types under ::ActiveModel::Type
.)
class Person < ActiveRecord::Base
belongs_to :organization
end
person = Person.new(name: "Francesco", date_of_birth: "2004-12-12")
person[:name] # => "Francesco"
person[:date_of_birth] # => Date.new(2004, 12, 12)
person[:organization_id] # => nil
Raises ::ActiveModel::MissingAttributeError
if the attribute is missing. Note, however, that the id
attribute will never be considered missing.
person = Person.select(:name).first
person[:name] # => "Francesco"
person[:date_of_birth] # => ActiveModel::MissingAttributeError: missing attribute 'date_of_birth' for Person
person[:organization_id] # => ActiveModel::MissingAttributeError: missing attribute 'organization_id' for Person
person[:id] # => nil
# File 'activerecord/lib/active_record/attribute_methods.rb', line 414
def [](attr_name) read_attribute(attr_name) { |n| missing_attribute(n, caller) } end
#[]=(attr_name, value)
Updates the attribute identified by attr_name
using the specified value
. The attribute value will be type cast upon being read.
class Person < ActiveRecord::Base
end
person = Person.new
person[:date_of_birth] = "2004-12-12"
person[:date_of_birth] # => Date.new(2004, 12, 12)
# File 'activerecord/lib/active_record/attribute_methods.rb', line 427
def []=(attr_name, value) write_attribute(attr_name, value) end
#_has_attribute?(attr_name) ⇒ Boolean
# File 'activerecord/lib/active_record/attribute_methods.rb', line 321
def _has_attribute?(attr_name) # :nodoc: @attributes.key?(attr_name) end
#accessed_fields
Returns the name of all database fields which have been read from this model. This can be useful in development mode to determine which fields need to be selected. For performance critical pages, selecting only the required fields can be an easy performance win (assuming you aren’t using all of the fields on the model).
For example:
class PostsController < ActionController::Base
after_action :print_accessed_fields, only: :index
def index
@posts = Post.all
end
private
def print_accessed_fields
p @posts.first.accessed_fields
end
end
Which allows you to quickly change your code to:
class PostsController < ActionController::Base
def index
@posts = Post.select(:id, :title, :, :updated_at)
end
end
# File 'activerecord/lib/active_record/attribute_methods.rb', line 459
def accessed_fields @attributes.accessed end
#attribute_for_inspect(attr_name)
Returns an #inspect
-like string for the value of the attribute attr_name
. ::String
attributes are truncated up to 50 characters. Other attributes return the value of #inspect
without modification.
person = Person.create!(name: 'David Heinemeier Hansson ' * 3)
person.attribute_for_inspect(:name)
# => "\"David Heinemeier Hansson David Heinemeier Hansson ...\""
person.attribute_for_inspect(:created_at)
# => "\"2012-10-22 00:15:07.000000000 +0000\""
person.attribute_for_inspect(:tag_ids)
# => "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]"
# File 'activerecord/lib/active_record/attribute_methods.rb', line 364
def attribute_for_inspect(attr_name) attr_name = attr_name.to_s attr_name = self.class.attribute_aliases[attr_name] || attr_name value = _read_attribute(attr_name) format_for_inspect(attr_name, value) end
#attribute_method?(attr_name) ⇒ Boolean
(private)
# File 'activerecord/lib/active_record/attribute_methods.rb', line 494
def attribute_method?(attr_name) @attributes&.key?(attr_name) end
#attribute_names
Returns an array of names for the attributes available on this object.
class Person < ActiveRecord::Base
end
person = Person.new
person.attribute_names
# => ["id", "created_at", "updated_at", "name", "age"]
# File 'activerecord/lib/active_record/attribute_methods.rb', line 333
def attribute_names @attributes.keys end
#attribute_present?(attr_name) ⇒ Boolean
Returns true
if the specified attribute
has been set by the user or by a database load and is neither nil
nor empty?
(the latter only applies to objects that respond to empty?
, most notably Strings). Otherwise, false
. Note that it always returns true
with boolean attributes.
class Task < ActiveRecord::Base
end
task = Task.new(title: '', is_done: false)
task.attribute_present?(:title) # => false
task.attribute_present?(:is_done) # => true
task.title = 'Buy milk'
task.is_done = true
task.attribute_present?(:title) # => true
task.attribute_present?(:is_done) # => true
# File 'activerecord/lib/active_record/attribute_methods.rb', line 386
def attribute_present?(attr_name) attr_name = attr_name.to_s attr_name = self.class.attribute_aliases[attr_name] || attr_name value = _read_attribute(attr_name) !value.nil? && !(value.respond_to?(:empty?) && value.empty?) end
#attributes
Returns a hash of all the attributes with their names as keys and the values of the attributes as values.
class Person < ActiveRecord::Base
end
person = Person.create(name: 'Francesco', age: 22)
person.attributes
# => {"id"=>3, "created_at"=>Sun, 21 Oct 2012 04:53:04, "updated_at"=>Sun, 21 Oct 2012 04:53:04, "name"=>"Francesco", "age"=>22}
# File 'activerecord/lib/active_record/attribute_methods.rb', line 345
def attributes @attributes.to_hash end
#attributes_for_create(attribute_names) (private)
Filters out the virtual columns and also primary keys, from the attribute names, when the primary key is to be generated (e.g. the id attribute has no value).
# File 'activerecord/lib/active_record/attribute_methods.rb', line 514
def attributes_for_create(attribute_names) attribute_names &= self.class.column_names attribute_names.delete_if do |name| (pk_attribute?(name) && id.nil?) || column_for_attribute(name).virtual? end end
#attributes_for_update(attribute_names) (private)
Filters the primary keys, readonly attributes and virtual columns from the attribute names.
# File 'activerecord/lib/active_record/attribute_methods.rb', line 503
def attributes_for_update(attribute_names) attribute_names &= self.class.column_names attribute_names.delete_if do |name| self.class.readonly_attribute?(name) || self.class.counter_cache_column?(name) || column_for_attribute(name).virtual? end end
#attributes_with_values(attribute_names) (private)
[ GitHub ]# File 'activerecord/lib/active_record/attribute_methods.rb', line 498
def attributes_with_values(attribute_names) attribute_names.index_with { |name| @attributes[name] } end
#format_for_inspect(name, value) (private)
[ GitHub ]# File 'activerecord/lib/active_record/attribute_methods.rb', line 522
def format_for_inspect(name, value) if value.nil? value.inspect else inspected_value = if value.is_a?(String) && value.length > 50 "#{value[0, 50]}...".inspect elsif value.is_a?(Date) || value.is_a?(Time) %("#{value.to_fs(:inspect)}") else value.inspect end inspection_filter.filter_param(name, inspected_value) end end
#has_attribute?(attr_name) ⇒ Boolean
Returns true
if the given attribute is in the attributes hash, otherwise false
.
class Person < ActiveRecord::Base
alias_attribute :new_name, :name
end
person = Person.new
person.has_attribute?(:name) # => true
person.has_attribute?(:new_name) # => true
person.has_attribute?('age') # => true
person.has_attribute?(:nothing) # => false
# File 'activerecord/lib/active_record/attribute_methods.rb', line 315
def has_attribute?(attr_name) attr_name = attr_name.to_s attr_name = self.class.attribute_aliases[attr_name] || attr_name @attributes.key?(attr_name) end
#pk_attribute?(name) ⇒ Boolean
(private)
# File 'activerecord/lib/active_record/attribute_methods.rb', line 538
def pk_attribute?(name) name == @primary_key end
#respond_to?(name, include_private = false) ⇒ Boolean
A Person object with a name attribute can ask person.respond_to?(:name)
, person.respond_to?(:name=)
, and person.respond_to?(:name?)
which will all return true
. It also defines the attribute methods if they have not been generated.
class Person < ActiveRecord::Base
end
person = Person.new
person.respond_to?(:name) # => true
person.respond_to?(:name=) # => true
person.respond_to?(:name?) # => true
person.respond_to?('age') # => true
person.respond_to?('age=') # => true
person.respond_to?('age?') # => true
person.respond_to?(:nothing) # => false
# File 'activerecord/lib/active_record/attribute_methods.rb', line 290
def respond_to?(name, include_private = false) return false unless super # If the result is true then check for the select case. # For queries selecting a subset of columns, return false for unselected columns. if @attributes if name = self.class.symbol_column_to_string(name.to_sym) return _has_attribute?(name) end end true end
#respond_to_missing?(name, include_private = false) ⇒ Boolean
(private)
# File 'activerecord/lib/active_record/attribute_methods.rb', line 464
def respond_to_missing?(name, include_private = false) if self.class.define_attribute_methods # Some methods weren't defined yet. return true if self.class.method_defined?(name) return true if include_private && self.class.private_method_defined?(name) end super end