rest_model 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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