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 263 264 265 266 |
# File 'lib/active_record/attribute_methods.rb', line 232 def method_missing(method_id, *args, &block) if method_id == :to_ary || method_id == :to_str raise NoMethodError, "undefined method `#{method_id}' for #{inspect}:#{self.class}" end 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
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 |
# File 'lib/active_record/attribute_methods.rb', line 322 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)).
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 |
# File 'lib/active_record/attribute_methods.rb', line 270 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
287 288 289 |
# File 'lib/active_record/attribute_methods.rb', line 287 def read_attribute_before_type_cast(attr_name) @attributes[attr_name] end |
#respond_to?(method, include_private_methods = false) ⇒ Boolean
346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 |
# File 'lib/active_record/attribute_methods.rb', line 346 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
.
345 |
# File 'lib/active_record/attribute_methods.rb', line 345 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.
292 293 294 |
# File 'lib/active_record/attribute_methods.rb', line 292 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.
297 298 299 300 301 302 303 304 305 306 |
# File 'lib/active_record/attribute_methods.rb', line 297 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
.
311 312 313 314 315 316 317 318 319 |
# File 'lib/active_record/attribute_methods.rb', line 311 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 |