Module: MappedRecord::ClassMethods

Defined in:
lib/mapped-record.rb

Instance Method Summary collapse

Instance Method Details

#attr_mapped(*map_attrs) ⇒ Object

Assigns a mapping for the current ActiveRecord class.

class Person < ActiveRecord::Base
  attr_mapped 'PBName', 'PBAddress', 'PBEmail', { :namespace => 'Email' }
end

Given a list of strings, those keys will be mapped automatically to downcase and underscored attributes. (Specify these first).

Configuration options:

:id

The key to map to the primary key.

attr_mapped { :id => 'Key' }
:serialize

Any keys to serialize after mapping.

attr_mapped 'Array', 'Blob', { :serialize => ['Array', 'Blob'] }
:filter

Specify a hash of keys and procs to call before assigning to attributes.

attr_mapped 'Date', { :after => { 'Date' => Proc.new { ... } } }
:namespace

A prefix string to remove before automatically mapping.

attr_mapped 'PBOne', 'PBTwo', { :namespace => 'PB' }
'key' => :attribute, 'key2' => :attribute2, ...

As many manual mappings as needed.



79
80
81
# File 'lib/mapped-record.rb', line 79

def attr_mapped(*map_attrs)
  attr_mapped_named(class_name, *map_attrs)
end

#attr_mapped_named(named_mapping = nil, *map_attrs) ⇒ Object

Assigns mappings to a name.

class Person < ActiveRecord::Base
  attr_mapped_named :public, 'PBName', 'PBAddress', 'PBEmail', { :namespace => 'Email' }
end

The mapping can then be used with dynamic create and update methods. From the example above:

p = Person.create_with_public({ 'PBName' => 'Mr. Name' })
p.update_with_public({ 'PBName' => 'Full Name' })

Raises:



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/mapped-record.rb', line 93

def attr_mapped_named(named_mapping = nil, *map_attrs)
  unless self.respond_to?(:attr_mapped_serialized)
    class_inheritable_accessor :attr_mapped_serialized
    write_inheritable_attribute :attr_mapped_serialized, HashWithIndifferentAccess.new
  end

  unless self.respond_to?(:attr_hashed_id)
    class_inheritable_accessor :attr_hashed_id
    write_inheritable_attribute :attr_hashed_id, ''
  end

  raise NameError.new(named_mapping) if named_mapping.nil?
  raise NameError.new(named_mapping) unless named_mapping.to_s[/[a-zA-Z_]?[a-zA-Z_0-9]+/] == named_mapping.to_s
  raise MappingError, "No options given." if map_attrs.blank?

  options = map_attrs.extract_options!

  serialize_mappings = []

  options.each_pair do |key, value|
    case key
    when :id
      self.attr_hashed_id = value.to_s
    when :serialize
      case value
      when String, Symbol, Array
      else
        raise TargetError.new(named_mapping, key, value, [String, Symbol, Array])
      end
      
      value = [value] unless value.kind_of?(Array)
      keys = value.collect { |v| v.to_s }
      serialize_mappings |= keys
    end
  end
  options.delete(:id)
  options.delete(:serialize)

  map_attrs << options
  Mapping.create named_mapping, *map_attrs

  if Mapping.has?(named_mapping)
    # create dynamic methods
    self.class.send(:define_method, :"create_with_#{named_mapping}") do |hash|
      create_with(hash, :"#{named_mapping}")
    end
    self.send(:define_method, :"update_with_#{named_mapping}") do |hash|
      update_with(hash, :"#{named_mapping}")
    end

    self.attr_mapped_serialized[named_mapping] ||= HashWithIndifferentAccess.new
    self.attr_mapped_serialized[named_mapping] = update_serialized(named_mapping)
  end

  serialize_mappings.each do |attr|
    raise MappingError, "Serializing :id not allowed." if !self.attr_hashed_id.blank? && attr == self.attr_hashed_id        
    to_serialize = Mapping[named_mapping][attr][:to].to_sym

    # need to know serialized attributes to 'watch'
    self.attr_mapped_serialized[named_mapping][attr] = to_serialize

    self.instance_eval { serialize to_serialize }
  end
end

#create_with(hash = {}, named_mapping = nil) ⇒ Object

Accepts a hash to map and creates the Active Record object with its values.



159
160
161
162
163
164
165
166
# File 'lib/mapped-record.rb', line 159

def create_with(hash = {}, named_mapping = nil)
  named_mapping = self.class_name unless named_mapping

  self.create(with_attributes(named_mapping, hash)) do |r|
    id = hash[self.attr_hashed_id]
    r.id = id if id
  end
end

#with_attributes(named_mapping, hash) ⇒ Object

Maps the values in hash with named_mapping for use in Active Record.



169
170
171
172
173
# File 'lib/mapped-record.rb', line 169

def with_attributes(named_mapping, hash)
  attrs = hash.map_with(named_mapping)
  attrs.delete(:id) if attrs[:id]
  attrs
end