Class: Shale::Mapper

Inherits:
Type::Complex show all
Defined in:
lib/shale/mapper.rb

Overview

Base class used for mapping

Examples:

class Address < Shale::Mapper
  attribute :city, :string
  attribute :street, :string
  attribute :state, :string
  attribute :zip, :string
end

class Person < Shale::Mapper
  attribute :first_name, :string
  attribute :last_name, :string
  attribute :age, :integer
  attribute :address, Address
end

person = Person.from_json(%{
  {
    "first_name": "John",
    "last_name": "Doe",
    "age": 55,
    "address": {
      "city": "London",
      "street": "Oxford Street",
      "state": "London",
      "zip": "E1 6AN"
    }
  }
})

person.to_json

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Type::Complex

as_xml, from_csv, from_json, from_toml, from_xml, from_yaml, of_xml, to_csv, #to_csv, #to_hash, #to_json, to_json, to_toml, #to_toml, to_xml, #to_xml, to_yaml, #to_yaml

Methods inherited from Type::Value

as_csv, as_hash, as_json, as_toml, as_xml, as_xml_value, as_yaml, cast, of_csv, of_hash, of_json, of_toml, of_xml, of_yaml

Constructor Details

#initialize(**props) ⇒ Mapper

Initialize instance with properties

Examples:

Person.new(
  first_name: 'John',
  last_name: 'Doe',
  address: Address.new(city: 'London')
)
# => #<Person:0x00007f82768a2370
        @first_name="John",
        @last_name="Doe"
        @address=#<Address:0x00007fe9cf0f57d8 @city="London">>

Parameters:

  • props (Hash)

    Properties

Raises:



369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
# File 'lib/shale/mapper.rb', line 369

def initialize(**props)
  super()

  unless props.empty?
    unknown_attributes = props.keys - self.class.attributes.keys

    unless unknown_attributes.empty?
      raise UnknownAttributeError.new(self.class.to_s, unknown_attributes[0].to_s)
    end
  end

  self.class.attributes.each do |name, attribute|
    if props.key?(name)
      value = props[name]
    elsif attribute.default
      value = attribute.default.call
    end

    send(attribute.setter, value)
  end
end

Class Attribute Details

.attributesHash<Symbol, Shale::Attribute> (readonly)

Return attributes Hash

Returns:



62
63
64
# File 'lib/shale/mapper.rb', line 62

def attributes
  @attributes
end

.csv_mappingShale::Mapping::Dict (readonly)

Return CSV mapping object



97
98
99
# File 'lib/shale/mapper.rb', line 97

def csv_mapping
  @csv_mapping
end

.hash_mappingShale::Mapping::Dict (readonly)

Return Hash mapping object



69
70
71
# File 'lib/shale/mapper.rb', line 69

def hash_mapping
  @hash_mapping
end

.json_mappingShale::Mapping::Dict (readonly)

Return JSON mapping object



76
77
78
# File 'lib/shale/mapper.rb', line 76

def json_mapping
  @json_mapping
end

.toml_mappingShale::Mapping::Dict (readonly)

Return TOML mapping object



90
91
92
# File 'lib/shale/mapper.rb', line 90

def toml_mapping
  @toml_mapping
end

.xml_mappingShale::Mapping::XML (readonly)

Return XML mapping object

Returns:

  • (Shale::Mapping::XML)


104
105
106
# File 'lib/shale/mapper.rb', line 104

def xml_mapping
  @xml_mapping
end

.yaml_mappingShale::Mapping::Dict (readonly)

Return YAML mapping object



83
84
85
# File 'lib/shale/mapper.rb', line 83

def yaml_mapping
  @yaml_mapping
end

Class Method Details

.attribute(name, type, collection: false, default: nil) ⇒ Object

Define attribute on class

Examples:

class Person < Shale::Mapper
  attribute :first_name, :string
  attribute :last_name, :string
  attribute :age, :integer, default: -> { 1 }
  attribute :hobbies, :string, collection: true
end

person = Person.new

person.first_name # => nil
person.first_name = 'John'
person.first_name # => 'John'

person.age # => 1

person.hobbies << 'Dancing'
person.hobbies # => ['Dancing']

Parameters:

  • name (Symbol)

    Name of the attribute

  • type (Symbol, Class<Shale::Type::Value>)

    Type of the attribute

  • collection (Boolean) (defaults to: false)

    Is the attribute a collection

  • default (Proc) (defaults to: nil)

    Default value for the attribute

Raises:



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/shale/mapper.rb', line 175

def attribute(name, type, collection: false, default: nil)
  name = name.to_sym

  unless default.nil? || default.respond_to?(:call)
    raise DefaultNotCallableError.new(to_s, name)
  end

  if type.is_a?(Symbol)
    type = Type.lookup(type)
  end

  @attributes[name] = Attribute.new(name, type, collection, default)

  @hash_mapping.map(name.to_s, to: name) unless @hash_mapping.finalized?
  @json_mapping.map(name.to_s, to: name) unless @json_mapping.finalized?
  @yaml_mapping.map(name.to_s, to: name) unless @yaml_mapping.finalized?
  @toml_mapping.map(name.to_s, to: name) unless @toml_mapping.finalized?
  @csv_mapping.map(name.to_s, to: name) unless @csv_mapping.finalized?
  @xml_mapping.map_element(name.to_s, to: name) unless @xml_mapping.finalized?

  @attributes_module.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
    attr_reader :#{name}

    def #{name}=(val)
      @#{name} = #{collection} ? val : #{type}.cast(val)
    end
  RUBY
end

.csv(&block) ⇒ Object

Define CSV mapping

Examples:

class Person < Shale::Mapper
  attribute :first_name, :string
  attribute :last_name, :string
  attribute :age, :integer

  csv do
    map 'first_name', to: :first_name
    map 'last_name', to: :last_name
    map 'age', to: :age
  end
end

Parameters:

  • block (Proc)


318
319
320
321
322
# File 'lib/shale/mapper.rb', line 318

def csv(&block)
  @csv_mapping = @__csv_mapping_init.dup
  @csv_mapping.finalize!
  @csv_mapping.instance_eval(&block)
end

.hsh(&block) ⇒ Object

Define Hash mapping

Examples:

class Person < Shale::Mapper
  attribute :first_name, :string
  attribute :last_name, :string
  attribute :age, :integer

  hsh do
    map 'firstName', to: :first_name
    map 'lastName', to: :last_name
    map 'age', to: :age
  end
end

Parameters:

  • block (Proc)


222
223
224
225
226
# File 'lib/shale/mapper.rb', line 222

def hsh(&block)
  @hash_mapping = @__hash_mapping_init.dup
  @hash_mapping.finalize!
  @hash_mapping.instance_eval(&block)
end

.inherited(subclass) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



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
# File 'lib/shale/mapper.rb', line 107

def inherited(subclass)
  super

  attributes_module = Module.new
  subclass.instance_variable_set('@attributes_module', attributes_module)
  subclass.include(attributes_module)

  subclass.instance_variable_set('@model', subclass)
  subclass.instance_variable_set('@attributes', @attributes.dup)

  subclass.instance_variable_set('@__hash_mapping_init', @hash_mapping.dup)
  subclass.instance_variable_set('@__json_mapping_init', @json_mapping.dup)
  subclass.instance_variable_set('@__yaml_mapping_init', @yaml_mapping.dup)
  subclass.instance_variable_set('@__toml_mapping_init', @toml_mapping.dup)
  subclass.instance_variable_set('@__csv_mapping_init', @csv_mapping.dup)
  subclass.instance_variable_set('@__xml_mapping_init', @xml_mapping.dup)

  subclass.instance_variable_set('@hash_mapping', @hash_mapping.dup)
  subclass.instance_variable_set('@json_mapping', @json_mapping.dup)
  subclass.instance_variable_set('@yaml_mapping', @yaml_mapping.dup)
  subclass.instance_variable_set('@toml_mapping', @toml_mapping.dup)
  subclass.instance_variable_set('@csv_mapping', @csv_mapping.dup)

  xml_mapping = @xml_mapping.dup
  xml_mapping.root(Utils.underscore(subclass.name || ''))

  subclass.instance_variable_set('@xml_mapping', xml_mapping.dup)
end

.json(&block) ⇒ Object

Define JSON mapping

Examples:

class Person < Shale::Mapper
  attribute :first_name, :string
  attribute :last_name, :string
  attribute :age, :integer

  json do
    map 'firstName', to: :first_name
    map 'lastName', to: :last_name
    map 'age', to: :age
  end
end

Parameters:

  • block (Proc)


246
247
248
249
250
# File 'lib/shale/mapper.rb', line 246

def json(&block)
  @json_mapping = @__json_mapping_init.dup
  @json_mapping.finalize!
  @json_mapping.instance_eval(&block)
end

.model(klass = nil) ⇒ Object



136
137
138
139
140
141
142
143
# File 'lib/shale/mapper.rb', line 136

def model(klass = nil)
  if klass
    @model = klass
    xml_mapping.root(Utils.underscore(@model.name))
  else
    @model
  end
end

.toml(&block) ⇒ Object

Define TOML mapping

Examples:

class Person < Shale::Mapper
  attribute :first_name, :string
  attribute :last_name, :string
  attribute :age, :integer

  toml do
    map 'first_name', to: :first_name
    map 'last_name', to: :last_name
    map 'age', to: :age
  end
end

Parameters:

  • block (Proc)


294
295
296
297
298
# File 'lib/shale/mapper.rb', line 294

def toml(&block)
  @toml_mapping = @__toml_mapping_init.dup
  @toml_mapping.finalize!
  @toml_mapping.instance_eval(&block)
end

.xml(&block) ⇒ Object

Define XML mapping

Examples:

class Person < Shale::Mapper
  attribute :first_name, :string
  attribute :last_name, :string
  attribute :age, :integer

  xml do
    root 'Person'
    map_content to: :first_name
    map_element 'LastName', to: :last_name
    map_attribute 'age', to: :age
  end
end

Parameters:

  • block (Proc)


343
344
345
346
347
348
# File 'lib/shale/mapper.rb', line 343

def xml(&block)
  @xml_mapping = @__xml_mapping_init.dup
  @xml_mapping.finalize!
  @xml_mapping.root('')
  @xml_mapping.instance_eval(&block)
end

.yaml(&block) ⇒ Object

Define YAML mapping

Examples:

class Person < Shale::Mapper
  attribute :first_name, :string
  attribute :last_name, :string
  attribute :age, :integer

  yaml do
    map 'first_name', to: :first_name
    map 'last_name', to: :last_name
    map 'age', to: :age
  end
end

Parameters:

  • block (Proc)


270
271
272
273
274
# File 'lib/shale/mapper.rb', line 270

def yaml(&block)
  @yaml_mapping = @__yaml_mapping_init.dup
  @yaml_mapping.finalize!
  @yaml_mapping.instance_eval(&block)
end