Module: CouchRest::Mixins::Properties

Defined in:
lib/couchrest/mixins/properties.rb

Defined Under Namespace

Modules: ClassMethods Classes: IncludeError

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object



29
30
31
32
33
34
35
36
# File 'lib/couchrest/mixins/properties.rb', line 29

def self.included(base)
  base.class_eval <<-EOS, __FILE__, __LINE__ + 1
      extlib_inheritable_accessor(:properties) unless self.respond_to?(:properties)
      self.properties ||= []
  EOS
  base.extend(ClassMethods)
  raise CouchRest::Mixins::Properties::IncludeError, "You can only mixin Properties in a class responding to [] and []=, if you tried to mixin CastedModel, make sure your class inherits from Hash or responds to the proper methods" unless (base.new.respond_to?(:[]) && base.new.respond_to?(:[]=))
end

Instance Method Details

#apply_defaultsObject



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/couchrest/mixins/properties.rb', line 38

def apply_defaults
  return if self.respond_to?(:new?) && (new? == false)
  return unless self.class.respond_to?(:properties) 
  return if self.class.properties.empty?
  # TODO: cache the default object
  self.class.properties.each do |property|
    key = property.name.to_s
    # let's make sure we have a default
    unless property.default.nil?
        if property.default.class == Proc
          self[key] = property.default.call
        else
          self[key] = Marshal.load(Marshal.dump(property.default))
        end
      end
  end
end

#associate_casted_to_parent(casted, assigned) ⇒ Object



94
95
96
97
# File 'lib/couchrest/mixins/properties.rb', line 94

def associate_casted_to_parent(casted, assigned)
  casted.casted_by = self if casted.respond_to?(:casted_by)
  casted.document_saved = true if !assigned && casted.respond_to?(:document_saved)
end

#cast_float(value) ⇒ Object



121
122
123
124
125
126
127
# File 'lib/couchrest/mixins/properties.rb', line 121

def cast_float(value)
  begin 
    Float(value)
  rescue
    value
  end
end

#cast_keysObject



56
57
58
59
60
61
# File 'lib/couchrest/mixins/properties.rb', line 56

def cast_keys
  return unless self.class.properties
  self.class.properties.each do |property|
    cast_property(property)
  end
end

#cast_property(property, assigned = false) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/couchrest/mixins/properties.rb', line 63

def cast_property(property, assigned=false)
  return unless property.casted
  key = self.has_key?(property.name) ? property.name : property.name.to_sym
  # Don't cast the property unless it has a value
  return unless self[key]
  if property.type.is_a?(Array)
    klass = ::CouchRest.constantize(property.type[0])
    arr = self[key].dup.collect do |value|
      unless value.instance_of?(klass)
        value = convert_property_value(property, klass, value)
      end
      associate_casted_to_parent(value, assigned)
      value
    end
    self[key] = klass != String ? CastedArray.new(arr) : arr
    self[key].casted_by = self if self[key].respond_to?(:casted_by)
  else
    if property.type == 'boolean'
      klass = TrueClass
    else
      klass = ::CouchRest.constantize(property.type)
    end
    
    unless self[key].instance_of?(klass)
      self[key] = convert_property_value(property, klass, self[property.name])
    end
    associate_casted_to_parent(self[property.name], assigned)
  end
  
end

#cast_property_by_name(property_name) ⇒ Object



114
115
116
117
118
119
# File 'lib/couchrest/mixins/properties.rb', line 114

def cast_property_by_name(property_name)
  return unless self.class.properties
  property = self.class.properties.detect{|property| property.name == property_name}
  return unless property
  cast_property(property, true)
end

#convert_property_value(property, klass, value) ⇒ Object



99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/couchrest/mixins/properties.rb', line 99

def convert_property_value(property, klass, value)
  if ((property.init_method == 'new') && klass == Time)
    # Using custom time parsing method because Ruby's default method is toooo slow
    value.is_a?(String) ? Time.mktime_with_offset(value.dup) : value
  # Float instances don't get initialized with #new
  elsif ((property.init_method == 'new') && klass == Float)
    cast_float(value)
    # 'boolean' type is simply used to generate a property? accessor method
  elsif ((property.init_method == 'new') && klass == TrueClass)
    value
  else
    klass.send(property.init_method, value.dup)
  end
end