Module: ActiveRecord::AttributeMethods
- Defined in:
- lib/active_record/attribute_methods.rb
Overview
:nodoc:
Defined Under Namespace
Modules: ClassMethods
Constant Summary collapse
- DEFAULT_SUFFIXES =
%w(= ? _before_type_cast)
- ATTRIBUTE_TYPES_CACHED_BY_DEFAULT =
[:datetime, :timestamp, :time, :date]
Class Method Summary collapse
Instance Method Summary collapse
-
#method_missing(method_id, *args, &block) ⇒ Object
Allows access to the object attributes, which are held in the
@attributes
hash, as though they were first-class methods. - #query_attribute(attr_name) ⇒ Object
-
#read_attribute(attr_name) ⇒ Object
Returns the value of the attribute identified by
attr_name
after it has been typecast (for example, “2004-12-12” in a data column is cast to a date object, like Date.new(2004, 12, 12)). - #read_attribute_before_type_cast(attr_name) ⇒ Object
- #respond_to?(method, include_private_methods = false) ⇒ Boolean
-
#respond_to_without_attributes? ⇒ Object
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
. -
#unserializable_attribute?(attr_name, column) ⇒ Boolean
Returns true if the attribute is of a text column and marked for serialization.
-
#unserialize_attribute(attr_name) ⇒ Object
Returns the unserialized object of the attribute.
-
#write_attribute(attr_name, value) ⇒ Object
Updates the attribute identified by
attr_name
with the specifiedvalue
.
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method_id, *args, &block) ⇒ Object
Allows access to the object attributes, which are held in the @attributes
hash, as though they were first-class methods. So a Person class with a name attribute can use Person#name and Person#name= and never directly use the attributes hash – except for multiple assigns with ActiveRecord#attributes=. A Milestone class can also ask Milestone#completed? to test that the completed attribute is not nil
or 0.
It’s also possible to instantiate related objects, so a Client class belonging to the clients table with a master_id
foreign key can instantiate master through Client#master.
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 |
# File 'lib/active_record/attribute_methods.rb', line 247 def method_missing(method_id, *args, &block) method_name = method_id.to_s if self.class.private_method_defined?(method_name) raise NoMethodError.new("Attempt to call private method", method_name, args) end # If we haven't generated any methods yet, generate them, then # see if we've created the method we're looking for. if !self.class.generated_methods? self.class.define_attribute_methods if self.class.generated_methods.include?(method_name) return self.send(method_id, *args, &block) end end if self.class.primary_key.to_s == method_name id elsif md = self.class.match_attribute_method?(method_name) attribute_name, method_type = md.pre_match, md.to_s if @attributes.include?(attribute_name) __send__("attribute#{method_type}", attribute_name, *args, &block) else super end elsif @attributes.include?(method_name) read_attribute(method_name) else super end end |
Class Method Details
.included(base) ⇒ Object
6 7 8 9 10 11 12 13 14 15 |
# File 'lib/active_record/attribute_methods.rb', line 6 def self.included(base) base.extend ClassMethods base.attribute_method_suffix(*DEFAULT_SUFFIXES) base.cattr_accessor :attribute_types_cached_by_default, :instance_writer => false base.attribute_types_cached_by_default = ATTRIBUTE_TYPES_CACHED_BY_DEFAULT base.cattr_accessor :time_zone_aware_attributes, :instance_writer => false base.time_zone_aware_attributes = false base.class_inheritable_accessor :skip_time_zone_conversion_for_attributes, :instance_writer => false base.skip_time_zone_conversion_for_attributes = [] end |
Instance Method Details
#query_attribute(attr_name) ⇒ Object
333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 |
# File 'lib/active_record/attribute_methods.rb', line 333 def query_attribute(attr_name) unless value = read_attribute(attr_name) false else column = self.class.columns_hash[attr_name] if column.nil? if Numeric === value || value !~ /[^0-9]/ !value.to_i.zero? else return false if ActiveRecord::ConnectionAdapters::Column::FALSE_VALUES.include?(value) !value.blank? end elsif column.number? !value.zero? else !value.blank? end end end |
#read_attribute(attr_name) ⇒ Object
Returns the value of the attribute identified by attr_name
after it has been typecast (for example, “2004-12-12” in a data column is cast to a date object, like Date.new(2004, 12, 12)).
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 |
# File 'lib/active_record/attribute_methods.rb', line 281 def read_attribute(attr_name) attr_name = attr_name.to_s if !(value = @attributes[attr_name]).nil? if column = column_for_attribute(attr_name) if unserializable_attribute?(attr_name, column) unserialize_attribute(attr_name) else column.type_cast(value) end else value end else nil end end |
#read_attribute_before_type_cast(attr_name) ⇒ Object
298 299 300 |
# File 'lib/active_record/attribute_methods.rb', line 298 def read_attribute_before_type_cast(attr_name) @attributes[attr_name] end |
#respond_to?(method, include_private_methods = false) ⇒ Boolean
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 |
# File 'lib/active_record/attribute_methods.rb', line 357 def respond_to?(method, include_private_methods = false) method_name = method.to_s if super return true elsif !include_private_methods && super(method, true) # If we're here than we haven't found among non-private methods # but found among all methods. Which means that given method is private. return false elsif !self.class.generated_methods? self.class.define_attribute_methods if self.class.generated_methods.include?(method_name) return true end end if @attributes.nil? return super elsif @attributes.include?(method_name) return true elsif md = self.class.match_attribute_method?(method_name) return true if @attributes.include?(md.pre_match) end super end |
#respond_to_without_attributes? ⇒ Object
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
.
356 |
# File 'lib/active_record/attribute_methods.rb', line 356 alias :respond_to_without_attributes? :respond_to? |
#unserializable_attribute?(attr_name, column) ⇒ Boolean
Returns true if the attribute is of a text column and marked for serialization.
303 304 305 |
# File 'lib/active_record/attribute_methods.rb', line 303 def unserializable_attribute?(attr_name, column) column.text? && self.class.serialized_attributes[attr_name] end |
#unserialize_attribute(attr_name) ⇒ Object
Returns the unserialized object of the attribute.
308 309 310 311 312 313 314 315 316 317 |
# File 'lib/active_record/attribute_methods.rb', line 308 def unserialize_attribute(attr_name) unserialized_object = object_from_yaml(@attributes[attr_name]) if unserialized_object.is_a?(self.class.serialized_attributes[attr_name]) || unserialized_object.nil? @attributes.frozen? ? unserialized_object : @attributes[attr_name] = unserialized_object else raise SerializationTypeMismatch, "#{attr_name} was supposed to be a #{self.class.serialized_attributes[attr_name]}, but was a #{unserialized_object.class.to_s}" end end |
#write_attribute(attr_name, value) ⇒ Object
Updates the attribute identified by attr_name
with the specified value
. Empty strings for fixnum and float columns are turned into nil
.
322 323 324 325 326 327 328 329 330 |
# File 'lib/active_record/attribute_methods.rb', line 322 def write_attribute(attr_name, value) attr_name = attr_name.to_s @attributes_cache.delete(attr_name) if (column = column_for_attribute(attr_name)) && column.number? @attributes[attr_name] = convert_number_column_value(value) else @attributes[attr_name] = value end end |