rest_model 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. data/.gitignore +5 -0
  2. data/Gemfile +2 -0
  3. data/Guardfile +7 -0
  4. data/README.md +237 -0
  5. data/Rakefile +2 -0
  6. data/examples/all.rb +12 -0
  7. data/examples/embeds_many/invisible.rb +16 -0
  8. data/examples/embeds_many/simple.rb +13 -0
  9. data/examples/embeds_many/with_array.rb +10 -0
  10. data/examples/embeds_many/with_class_name.rb +13 -0
  11. data/examples/embeds_many/with_fields.rb +9 -0
  12. data/examples/embeds_many/with_if.rb +16 -0
  13. data/examples/embeds_many/with_nil_value.rb +12 -0
  14. data/examples/embeds_many/with_start_key.rb +13 -0
  15. data/examples/embeds_one/flattened.rb +12 -0
  16. data/examples/embeds_one/simple.rb +12 -0
  17. data/examples/embeds_one/with_class_name.rb +12 -0
  18. data/examples/embeds_one/with_if.rb +16 -0
  19. data/examples/embeds_one/with_start_key.rb +12 -0
  20. data/examples/has_many/simple.rb +28 -0
  21. data/examples/helper.rb +9 -0
  22. data/examples/initialize/embeds_many.rb +25 -0
  23. data/examples/initialize/embeds_many_array.rb +9 -0
  24. data/examples/initialize/embeds_one.rb +19 -0
  25. data/examples/initialize/simple.rb +8 -0
  26. data/examples/properties/array_serialization.rb +8 -0
  27. data/examples/properties/collections.rb +11 -0
  28. data/examples/properties/simple.rb +8 -0
  29. data/examples/properties/with_field.rb +8 -0
  30. data/examples/properties/with_field_path.rb +8 -0
  31. data/examples/properties/with_id.rb +8 -0
  32. data/examples/properties/with_if.rb +21 -0
  33. data/examples/properties/with_key_converter.rb +18 -0
  34. data/examples/properties/with_two_key_converters.rb +27 -0
  35. data/examples/properties/with_values.rb +10 -0
  36. data/examples/summarization/simple.rb +21 -0
  37. data/examples/to_input/embeds_many.rb +25 -0
  38. data/examples/to_input/embeds_many_without_key.rb +31 -0
  39. data/examples/to_input/embeds_one.rb +13 -0
  40. data/examples/to_input/embeds_one_without_key.rb +23 -0
  41. data/examples/to_input/flattened.rb +12 -0
  42. data/examples/to_input/serializables.rb +19 -0
  43. data/examples/to_input/simple.rb +8 -0
  44. data/examples/to_input/with_field.rb +8 -0
  45. data/examples/to_input/with_field_path.rb +8 -0
  46. data/examples/to_input/with_fields.rb +8 -0
  47. data/examples/to_input/without_key.rb +11 -0
  48. data/examples/to_input/without_nil.rb +11 -0
  49. data/lib/rest_model/configuration.rb +45 -0
  50. data/lib/rest_model/key/association.rb +42 -0
  51. data/lib/rest_model/key/builder.rb +30 -0
  52. data/lib/rest_model/key/embeddable/builder.rb +19 -0
  53. data/lib/rest_model/key/embeddable/response.rb +25 -0
  54. data/lib/rest_model/key/embeddable/retriever.rb +20 -0
  55. data/lib/rest_model/key/embeddable/sender.rb +41 -0
  56. data/lib/rest_model/key/embeddable.rb +29 -0
  57. data/lib/rest_model/key/href/response.rb +10 -0
  58. data/lib/rest_model/key/href.rb +10 -0
  59. data/lib/rest_model/key/property/builder.rb +27 -0
  60. data/lib/rest_model/key/property/response.rb +9 -0
  61. data/lib/rest_model/key/property/retriever.rb +24 -0
  62. data/lib/rest_model/key/property/sender.rb +41 -0
  63. data/lib/rest_model/key/property.rb +22 -0
  64. data/lib/rest_model/key/relation/builder.rb +24 -0
  65. data/lib/rest_model/key/relation/response.rb +38 -0
  66. data/lib/rest_model/key/relation.rb +23 -0
  67. data/lib/rest_model/key.rb +44 -0
  68. data/lib/rest_model/response.rb +42 -0
  69. data/lib/rest_model/serialization/boolean.rb +48 -0
  70. data/lib/rest_model/serialization/date.rb +19 -0
  71. data/lib/rest_model/serialization/enumerable.rb +15 -0
  72. data/lib/rest_model/serialization/float.rb +17 -0
  73. data/lib/rest_model/serialization/integer.rb +17 -0
  74. data/lib/rest_model/serialization/string.rb +13 -0
  75. data/lib/rest_model/source/path.rb +25 -0
  76. data/lib/rest_model/source/retriever.rb +48 -0
  77. data/lib/rest_model/source/sender.rb +38 -0
  78. data/lib/rest_model/version.rb +3 -0
  79. data/lib/rest_model.rb +101 -0
  80. data/rest_model.gemspec +26 -0
  81. data/spec/.DS_Store +0 -0
  82. data/spec/integration/embeds_many_spec.rb +57 -0
  83. data/spec/integration/embeds_one_spec.rb +41 -0
  84. data/spec/integration/has_many_spec.rb +27 -0
  85. data/spec/integration/property_spec.rb +69 -0
  86. data/spec/integration/summarization_spec.rb +12 -0
  87. data/spec/spec_helper.rb +26 -0
  88. data/spec/support/examples.rb +29 -0
  89. data/spec/support/out.rb +17 -0
  90. data/spec/support/shared_examples.rb +20 -0
  91. data/spec/unit/configuration_spec.rb +24 -0
  92. data/spec/unit/key/association_spec.rb +69 -0
  93. data/spec/unit/key/embeddable/builder_spec.rb +26 -0
  94. data/spec/unit/key/embeddable/response_spec.rb +55 -0
  95. data/spec/unit/key/embeddable/retriever_spec.rb +38 -0
  96. data/spec/unit/key/embeddable_spec.rb +7 -0
  97. data/spec/unit/key/property/builder_spec.rb +154 -0
  98. data/spec/unit/key/property/response_spec.rb +22 -0
  99. data/spec/unit/key/property/retriever_spec.rb +31 -0
  100. data/spec/unit/key/property_spec.rb +39 -0
  101. data/spec/unit/key/relation/builder_spec.rb +53 -0
  102. data/spec/unit/key/relation/response_spec.rb +105 -0
  103. data/spec/unit/key/relation_spec.rb +71 -0
  104. data/spec/unit/key_spec.rb +101 -0
  105. data/spec/unit/response_spec.rb +44 -0
  106. data/spec/unit/rest_model_spec.rb +46 -0
  107. data/spec/unit/serialization/boolean_spec.rb +25 -0
  108. data/spec/unit/serialization/date_spec.rb +13 -0
  109. data/spec/unit/serialization/float_spec.rb +13 -0
  110. data/spec/unit/serialization/integer_spec.rb +13 -0
  111. data/spec/unit/serialization/string_spec.rb +11 -0
  112. data/spec/unit/source/path_spec.rb +62 -0
  113. data/spec/unit/source/retriever_spec.rb +85 -0
  114. metadata +260 -0
@@ -0,0 +1,27 @@
1
+ $:.push 'examples'; require 'helper'
2
+
3
+ module Upcasing
4
+ def self.call(keys)
5
+ keys.map {|key| key.to_s.upcase}
6
+ end
7
+ end
8
+
9
+ module Camelizing
10
+ def self.call(keys)
11
+ keys.map {|key| key.to_s.camelize}
12
+ end
13
+ end
14
+
15
+ class Customer < RestModel
16
+ convert_input_keys Upcasing
17
+ property :login
18
+ embeds_one :product
19
+ end
20
+
21
+ class Product < RestModel
22
+ convert_input_keys Camelizing
23
+ property :unit_price, type: Float
24
+ end
25
+
26
+ @root = Customer.parse({"LOGIN" => 'jackiechan2010', "PRODUCT" => {"UnitPrice" => 29.9}}).first
27
+ inspect_rest_model(@root)
@@ -0,0 +1,10 @@
1
+ $:.push 'examples'; require 'helper'
2
+
3
+ class Customer < RestModel
4
+ property :periodicity, values: {1 => "c_53", 2 => "c_z1"}
5
+ property :company, values: {"amazon" => "AM", "google" => "GOOG"}
6
+ property :type, values: {simple: "1", complex: "2"}
7
+ end
8
+
9
+ @root = Customer.parse({periodicity: 'c_53', company: "GOOG", type: 2}).first
10
+ inspect_rest_model(@root)
@@ -0,0 +1,21 @@
1
+ $:.push 'examples'; require 'helper'
2
+
3
+ class Customer < RestModel
4
+ convert_input_keys proc {|keys| keys}
5
+
6
+ id
7
+ properties :login, :name, :postal_code, :email, :secondary_email
8
+ summarizes :id, :login
9
+ end
10
+
11
+ input = {
12
+ "id" => 138911938,
13
+ "login" => 'jackiechan2010',
14
+ "name" => 'jackie chan',
15
+ "postal_code" => '05492-092',
16
+ "email" => 'jachan@gmail.com',
17
+ "secondary_email" => 'jackiepeligroso@yahoo.com'
18
+ }
19
+
20
+ @root = Customer.resources Customer.parse(input)
21
+ puts "transcribed: #{@root}"
@@ -0,0 +1,25 @@
1
+ $:.push 'examples'; require 'helper'
2
+
3
+ class Customer < RestModel
4
+ property :login, field: 'hidden.login'
5
+ embeds_many :phones
6
+ end
7
+
8
+ class Phone < RestModel
9
+ properties :number, :extension
10
+ end
11
+
12
+ @root = Customer.new({
13
+ login: 'jackiechan2010',
14
+ phones: [
15
+ {
16
+ number: "123123123",
17
+ extension: "111"
18
+ },
19
+ {
20
+ number: "098098098",
21
+ extension: "999"
22
+ }
23
+ ]})
24
+
25
+ inspect_rest_model(@root)
@@ -0,0 +1,31 @@
1
+ $:.push 'examples'; require 'helper'
2
+
3
+ class Customer < RestModel
4
+ properties :login, :name
5
+ embeds_many :phones
6
+ end
7
+
8
+ class Phone < RestModel
9
+ properties :number, :extension, :description
10
+ end
11
+
12
+ @root = Customer.new({
13
+ login: 'jackiechan2010',
14
+ name: "Jackie Chan",
15
+ phones: [
16
+ {
17
+ number: "897289472",
18
+ extension: "3897",
19
+ description: "abab"
20
+ },
21
+ {
22
+ number: "987198732",
23
+ extension: "1897",
24
+ description: "eheh"
25
+ }
26
+ ]
27
+ })
28
+
29
+ inspect_rest_model(@root)
30
+
31
+ puts "to input without description: #{@root.to_input(phones: {without: :descriptions})}"
@@ -0,0 +1,13 @@
1
+ $:.push 'examples'; require 'helper'
2
+
3
+ class Customer < RestModel
4
+ property :login, field: 'hidden.login'
5
+ embeds_one :address
6
+ end
7
+
8
+ class Address < RestModel
9
+ properties :street, :number
10
+ end
11
+
12
+ @root = Customer.new(login: 'jackiechan2010', address: {street: "Aurora St", number: 666})
13
+ inspect_rest_model(@root)
@@ -0,0 +1,23 @@
1
+ $:.push 'examples'; require 'helper'
2
+
3
+ class Customer < RestModel
4
+ properties :login, :name
5
+ embeds_one :address
6
+ end
7
+
8
+ class Address < RestModel
9
+ properties :street, :number, :hint
10
+ end
11
+
12
+ @root = Customer.new({
13
+ login: 'jackiechan2010',
14
+ name: "Jackie Chan",
15
+ address: {
16
+ street: "Aurora St",
17
+ number: 1833,
18
+ hint: "near gas station"
19
+ }
20
+ })
21
+
22
+ inspect_rest_model(@root)
23
+ puts "root.to_input without hint: #{@root.to_input(address: {without: :hint})}"
@@ -0,0 +1,12 @@
1
+ $:.push 'examples'; require 'helper'
2
+
3
+ class Root < RestModel
4
+ embeds_one :item, start_key: ""
5
+ end
6
+
7
+ class Item < RestModel
8
+ property :id
9
+ end
10
+
11
+ @root = Root.new(item: {id: 2000})
12
+ inspect_rest_model(@root)
@@ -0,0 +1,19 @@
1
+ $:.push 'examples'; require 'helper'
2
+
3
+ RestModel::Configuration.configure do |c|
4
+ c.true_value = "X"
5
+ c.false_value = ""
6
+ c.date_format = "%Y%m%d"
7
+ end
8
+
9
+ class Customer < RestModel
10
+ property :login
11
+ property :age, type: Integer
12
+ property :birth, type: Date
13
+ property :active, type: Boolean
14
+ property :services, type: Enumerable
15
+ property :balance, type: Float
16
+ end
17
+
18
+ @root = Customer.new({login: 'jackiechan2010', age: 22, birth: "1990-07-04", active: true, services: ["Hosting", "Email"], balance: 200.00})
19
+ inspect_rest_model(@root)
@@ -0,0 +1,8 @@
1
+ $:.push 'examples'; require 'helper'
2
+
3
+ class Customer < RestModel
4
+ property :login
5
+ end
6
+
7
+ @root = Customer.new(login: 'jackiechan2010')
8
+ inspect_rest_model(@root)
@@ -0,0 +1,8 @@
1
+ $:.push 'examples'; require 'helper'
2
+
3
+ class Customer < RestModel
4
+ property :login, field: 'customer_login'
5
+ end
6
+
7
+ @root = Customer.new(login: 'jackiechan2010')
8
+ inspect_rest_model(@root)
@@ -0,0 +1,8 @@
1
+ $:.push 'examples'; require 'helper'
2
+
3
+ class Customer < RestModel
4
+ property :login, field: 'hidden.login'
5
+ end
6
+
7
+ @root = Customer.new(login: 'jackiechan2010')
8
+ inspect_rest_model(@root)
@@ -0,0 +1,8 @@
1
+ $:.push 'examples'; require 'helper'
2
+
3
+ class Root < RestModel
4
+ embeds_many :items, fields: [:item1, :item2, :item3, :item4]
5
+ end
6
+
7
+ @root = Root.new(items: %w(i1 i2 i3))
8
+ inspect_rest_model(@root)
@@ -0,0 +1,11 @@
1
+ $:.push 'examples'; require 'helper'
2
+
3
+ class Customer < RestModel
4
+ property :login
5
+ property :name
6
+ end
7
+
8
+ @root = Customer.new(login: 'jackiechan2010', name: "Jackie Chan")
9
+
10
+ puts "root.to_input: #{@root.to_input(without: :name)}"
11
+ inspect_rest_model(@root)
@@ -0,0 +1,11 @@
1
+ $:.push 'examples'; require 'helper'
2
+
3
+ class Customer < RestModel
4
+ property :login
5
+ property :name
6
+ end
7
+
8
+ @root = Customer.new(login: 'jackiechan2010')
9
+ inspect_rest_model(@root)
10
+ puts "root.to_input without nil: #{@root.to_input(without_nil: true)}"
11
+
@@ -0,0 +1,45 @@
1
+ class RestModel
2
+ module Configuration
3
+ extend self
4
+
5
+ attr_accessor :host
6
+
7
+ DefaultHandler = proc {|keys| keys}
8
+
9
+ def convert_input_keys
10
+ @convert_input_keys || DefaultHandler
11
+ end
12
+
13
+ def convert_input_keys=(converter)
14
+ @convert_input_keys = converter
15
+ end
16
+
17
+ def true_value
18
+ @true || true
19
+ end
20
+
21
+ def true_value=(value)
22
+ @true = value
23
+ end
24
+
25
+ def false_value
26
+ @false || false
27
+ end
28
+
29
+ def false_value=(value)
30
+ @false = value
31
+ end
32
+
33
+ def date_format
34
+ @date_format
35
+ end
36
+
37
+ def date_format=(format)
38
+ @date_format = format
39
+ end
40
+
41
+ def configure
42
+ yield self if block_given?
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,42 @@
1
+ class RestModel
2
+ class Association < Key
3
+ attr_reader :many
4
+
5
+ def initialize(name, options = {})
6
+ super
7
+ @many = options.fetch(:many, false)
8
+ @class_name = options.fetch(:class_name, default_class_name).to_s.camelize
9
+ end
10
+
11
+ def one?
12
+ !many?
13
+ end
14
+
15
+ def many?
16
+ @many
17
+ end
18
+
19
+ def default_class_name
20
+ one? ? name : name.to_s.singularize
21
+ end
22
+
23
+ def resource_class
24
+ @class_name.to_s.camelize.constantize
25
+ end
26
+
27
+ def from_hash(attrs, resource = nil)
28
+ return nil if attrs.nil? or attrs.empty?
29
+ resource ? update_from_hash(resource, attrs) : create_from_hash(attrs)
30
+ end
31
+
32
+ def create_from_hash(attrs)
33
+ one? ? resource_class.new(attrs)
34
+ : Array(attrs).map {|item| resource_class.new(item)}
35
+ end
36
+
37
+ def update_from_hash(resource, attrs)
38
+ one? ? resource.update_attributes(attrs)
39
+ : resource.map {|item| item.update_attributes(item)}
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,30 @@
1
+ class RestModel
2
+ class Key
3
+ module Builder
4
+ include Relation::Builder
5
+ include Embeddable::Builder
6
+ include Property::Builder
7
+
8
+ def key(key)
9
+ fail "you can't define a key with name '#{key.name}'" if not_allowed?(key)
10
+ key.model = self
11
+ attr_accessor key.name
12
+ self.keys << key
13
+ self.id_key = key if key.options[:id]
14
+ end
15
+
16
+ def summarizes(*args)
17
+ args.each do |name|
18
+ key = keys.find {|key| key.name == name}
19
+ summarized_keys << key if key
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def not_allowed?(key)
26
+ RestModel.not_allowed_names.include?(key.name.to_s)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,19 @@
1
+ class RestModel
2
+ class Embeddable
3
+ module Builder
4
+ def embeds(name, options = {})
5
+ key Embeddable.new(name, options)
6
+ end
7
+
8
+ def embeds_one(name, options = {})
9
+ options.merge!(many: false)
10
+ embeds(name, options)
11
+ end
12
+
13
+ def embeds_many(name, options = {})
14
+ options.merge!(many: true)
15
+ embeds(name, options)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,25 @@
1
+ class RestModel
2
+ class Embeddable
3
+ module Response
4
+ def to_resource(parent)
5
+ return {} unless visible?(parent)
6
+
7
+ resource = nil
8
+
9
+ if embedded = parent.__send__(name)
10
+ resource = raw? ? embedded : resourcify(embedded)
11
+ elsif many?
12
+ resource = []
13
+ end
14
+
15
+ {name => resource}
16
+ end
17
+
18
+ private
19
+
20
+ def resourcify(embedded)
21
+ one? ? embedded.resource : embedded.map(&:resource)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,20 @@
1
+ class RestModel
2
+ class Embeddable
3
+ module Retriever
4
+ def from_source(item, resource = nil)
5
+ return handle_fields(item) if fields
6
+ value = digg(item)
7
+ parsed_value = raw? ? value : resource_class.from_source(value)
8
+ one? ? parsed_value.first : parsed_value
9
+ end
10
+
11
+ def handle_fields(item)
12
+ convert_input_keys.call(fields).map {|field| item[field]}
13
+ end
14
+
15
+ def digg(input)
16
+ source_path.inject(input) {|buffer, key| buffer = buffer[key]}
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,41 @@
1
+ class RestModel
2
+ class Embeddable
3
+ module Sender
4
+ def to_source!(value, resource, options = {})
5
+ return {} if value.nil?
6
+ fields ? to_multiple_source(value, options)
7
+ : to_single_source(value, options)
8
+ end
9
+
10
+ private
11
+
12
+ def to_single_source(value, options)
13
+ source = {}
14
+ path = source_path
15
+
16
+ if path.any?
17
+ last = path.pop
18
+ key_source = path.inject(source) {|buffer, key| buffer[key] = {}; buffer[key]}
19
+ key_source[last] = raw? ? value
20
+ : one? ? value.to_source(options)
21
+ : value.map {|item| item.to_source(options)}
22
+ else
23
+ source.merge!(value.to_source(options))
24
+ end
25
+
26
+ source
27
+ end
28
+
29
+ def to_multiple_source(value, options)
30
+ input = {}
31
+ mapped_fields = convert_input_keys.call(fields)
32
+
33
+ value.each_with_index do |item, index|
34
+ input[mapped_fields[index]] = item
35
+ end
36
+
37
+ input
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,29 @@
1
+ class RestModel
2
+ class Embeddable < Association
3
+ autoload :Sender, "rest_model/key/embeddable/sender"
4
+ autoload :Retriever, "rest_model/key/embeddable/retriever"
5
+ autoload :Response, "rest_model/key/embeddable/response"
6
+ include Sender
7
+ include Retriever
8
+ include Response
9
+
10
+ attr_accessor :fields
11
+
12
+ def initialize(name, options = {})
13
+ super
14
+
15
+ if fields = options[:fields]
16
+ @class_name = :array
17
+ @fields = fields
18
+ end
19
+ end
20
+
21
+ def raw?
22
+ [Hash, Array].include?(resource_class)
23
+ end
24
+
25
+ def from_hash(attrs, resource = nil)
26
+ raw? ? attrs : super
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,10 @@
1
+ class RestModel
2
+ class Href
3
+ module Response
4
+ def to_resource(parent)
5
+ id_key = parent.class.id_key.name
6
+ {name => "#{RestModel::Configuration.host}/#{parent.class.resource_name}/#{parent.send(id_key)}"}
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ class RestModel
2
+ class Href < Key
3
+ autoload :Response, "rest_model/key/href/response"
4
+ include Response
5
+
6
+ def initialize
7
+ super(:href)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,27 @@
1
+ class RestModel
2
+ class Property
3
+ module Builder
4
+ def property(name, options = {})
5
+ key Property.new(name, options)
6
+ end
7
+
8
+ def properties(*args)
9
+ options = options(args)
10
+ names = args
11
+ names.each {|name| property(name, options)}
12
+ end
13
+
14
+ def id(*args)
15
+ options = options(args)
16
+ name = args.fetch(0, :id)
17
+ property(name, options.merge(id: true))
18
+ end
19
+
20
+ private
21
+
22
+ def options(args)
23
+ args.last.kind_of?(Hash) ? args.pop : {}
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,9 @@
1
+ class RestModel
2
+ class Property
3
+ module Response
4
+ def to_resource(parent)
5
+ visible?(parent) ? {name => parent.__send__(name)} : {}
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,24 @@
1
+ class RestModel
2
+ class Property
3
+ module Retriever
4
+ def from_source(item, resource = nil)
5
+ value = digg(item)
6
+ translate_from_source(serializer.serialize(value), resource)
7
+ end
8
+
9
+ def digg(input)
10
+ source_path.inject(input) {|buffer, key| buffer = buffer[key]}
11
+ end
12
+
13
+ def translate_from_source(value, resource)
14
+ case translations
15
+ when nil then value
16
+ when Proc then resource.instance_eval(&translations)
17
+ when Hash
18
+ fail "from input error" unless translations.has_value?(value)
19
+ translations.key(value)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,41 @@
1
+ class RestModel
2
+ class Property
3
+ module Sender
4
+ def to_source!(value, resource, options = {})
5
+ source_value = nil
6
+
7
+ begin
8
+ if translations
9
+ source_value = translate_to_source(value, resource)
10
+ else
11
+ source_value = serializer.desserialize(value)
12
+ end
13
+ rescue => exception
14
+ raise exception if options[:fail]
15
+ end
16
+
17
+ source = {}
18
+ path = source_path
19
+
20
+ if path.any?
21
+ last = path.pop
22
+ key_source = path.inject(source) {|buffer, key| buffer[key] = {}; buffer[key]}
23
+ key_source[last] = source_value
24
+ else
25
+ source.merge!(source_value)
26
+ end
27
+
28
+ source
29
+ end
30
+
31
+ def translate_to_source(value, resource)
32
+ case translations
33
+ when Proc then resource.instance_eval(&translations)
34
+ when Hash
35
+ fail "to input error" unless translations.has_key?(value)
36
+ translations[value]
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,22 @@
1
+ class RestModel
2
+ class Property < Key
3
+ autoload :Sender, "rest_model/key/property/sender"
4
+ autoload :Retriever, "rest_model/key/property/retriever"
5
+ autoload :Response, "rest_model/key/property/response"
6
+ include Sender
7
+ include Retriever
8
+ include Response
9
+
10
+ attr_accessor :serializer, :translations
11
+
12
+ def initialize(name, options = {})
13
+ super
14
+ @serializer = options.fetch(:type, Serialization::String)
15
+ @translations = options[:values]
16
+ end
17
+
18
+ def from_hash(value, resource = nil)
19
+ value
20
+ end
21
+ end
22
+ end