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.
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 |
# File 'lib/active_record/attribute_methods.rb', line 232 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
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 |
# File 'lib/active_record/attribute_methods.rb', line 318 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 !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)).
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 |
# File 'lib/active_record/attribute_methods.rb', line 266 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
283 284 285 |
# File 'lib/active_record/attribute_methods.rb', line 283 def read_attribute_before_type_cast(attr_name) @attributes[attr_name] end |
#respond_to?(method, include_private_methods = false) ⇒ Boolean
341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 |
# File 'lib/active_record/attribute_methods.rb', line 341 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
.
340 |
# File 'lib/active_record/attribute_methods.rb', line 340 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.
288 289 290 |
# File 'lib/active_record/attribute_methods.rb', line 288 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.
293 294 295 296 297 298 299 300 301 302 |
# File 'lib/active_record/attribute_methods.rb', line 293 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
.
307 308 309 310 311 312 313 314 315 |
# File 'lib/active_record/attribute_methods.rb', line 307 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 |