rest_model 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/Gemfile +2 -0
- data/Guardfile +7 -0
- data/README.md +237 -0
- data/Rakefile +2 -0
- data/examples/all.rb +12 -0
- data/examples/embeds_many/invisible.rb +16 -0
- data/examples/embeds_many/simple.rb +13 -0
- data/examples/embeds_many/with_array.rb +10 -0
- data/examples/embeds_many/with_class_name.rb +13 -0
- data/examples/embeds_many/with_fields.rb +9 -0
- data/examples/embeds_many/with_if.rb +16 -0
- data/examples/embeds_many/with_nil_value.rb +12 -0
- data/examples/embeds_many/with_start_key.rb +13 -0
- data/examples/embeds_one/flattened.rb +12 -0
- data/examples/embeds_one/simple.rb +12 -0
- data/examples/embeds_one/with_class_name.rb +12 -0
- data/examples/embeds_one/with_if.rb +16 -0
- data/examples/embeds_one/with_start_key.rb +12 -0
- data/examples/has_many/simple.rb +28 -0
- data/examples/helper.rb +9 -0
- data/examples/initialize/embeds_many.rb +25 -0
- data/examples/initialize/embeds_many_array.rb +9 -0
- data/examples/initialize/embeds_one.rb +19 -0
- data/examples/initialize/simple.rb +8 -0
- data/examples/properties/array_serialization.rb +8 -0
- data/examples/properties/collections.rb +11 -0
- data/examples/properties/simple.rb +8 -0
- data/examples/properties/with_field.rb +8 -0
- data/examples/properties/with_field_path.rb +8 -0
- data/examples/properties/with_id.rb +8 -0
- data/examples/properties/with_if.rb +21 -0
- data/examples/properties/with_key_converter.rb +18 -0
- data/examples/properties/with_two_key_converters.rb +27 -0
- data/examples/properties/with_values.rb +10 -0
- data/examples/summarization/simple.rb +21 -0
- data/examples/to_input/embeds_many.rb +25 -0
- data/examples/to_input/embeds_many_without_key.rb +31 -0
- data/examples/to_input/embeds_one.rb +13 -0
- data/examples/to_input/embeds_one_without_key.rb +23 -0
- data/examples/to_input/flattened.rb +12 -0
- data/examples/to_input/serializables.rb +19 -0
- data/examples/to_input/simple.rb +8 -0
- data/examples/to_input/with_field.rb +8 -0
- data/examples/to_input/with_field_path.rb +8 -0
- data/examples/to_input/with_fields.rb +8 -0
- data/examples/to_input/without_key.rb +11 -0
- data/examples/to_input/without_nil.rb +11 -0
- data/lib/rest_model/configuration.rb +45 -0
- data/lib/rest_model/key/association.rb +42 -0
- data/lib/rest_model/key/builder.rb +30 -0
- data/lib/rest_model/key/embeddable/builder.rb +19 -0
- data/lib/rest_model/key/embeddable/response.rb +25 -0
- data/lib/rest_model/key/embeddable/retriever.rb +20 -0
- data/lib/rest_model/key/embeddable/sender.rb +41 -0
- data/lib/rest_model/key/embeddable.rb +29 -0
- data/lib/rest_model/key/href/response.rb +10 -0
- data/lib/rest_model/key/href.rb +10 -0
- data/lib/rest_model/key/property/builder.rb +27 -0
- data/lib/rest_model/key/property/response.rb +9 -0
- data/lib/rest_model/key/property/retriever.rb +24 -0
- data/lib/rest_model/key/property/sender.rb +41 -0
- data/lib/rest_model/key/property.rb +22 -0
- data/lib/rest_model/key/relation/builder.rb +24 -0
- data/lib/rest_model/key/relation/response.rb +38 -0
- data/lib/rest_model/key/relation.rb +23 -0
- data/lib/rest_model/key.rb +44 -0
- data/lib/rest_model/response.rb +42 -0
- data/lib/rest_model/serialization/boolean.rb +48 -0
- data/lib/rest_model/serialization/date.rb +19 -0
- data/lib/rest_model/serialization/enumerable.rb +15 -0
- data/lib/rest_model/serialization/float.rb +17 -0
- data/lib/rest_model/serialization/integer.rb +17 -0
- data/lib/rest_model/serialization/string.rb +13 -0
- data/lib/rest_model/source/path.rb +25 -0
- data/lib/rest_model/source/retriever.rb +48 -0
- data/lib/rest_model/source/sender.rb +38 -0
- data/lib/rest_model/version.rb +3 -0
- data/lib/rest_model.rb +101 -0
- data/rest_model.gemspec +26 -0
- data/spec/.DS_Store +0 -0
- data/spec/integration/embeds_many_spec.rb +57 -0
- data/spec/integration/embeds_one_spec.rb +41 -0
- data/spec/integration/has_many_spec.rb +27 -0
- data/spec/integration/property_spec.rb +69 -0
- data/spec/integration/summarization_spec.rb +12 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/support/examples.rb +29 -0
- data/spec/support/out.rb +17 -0
- data/spec/support/shared_examples.rb +20 -0
- data/spec/unit/configuration_spec.rb +24 -0
- data/spec/unit/key/association_spec.rb +69 -0
- data/spec/unit/key/embeddable/builder_spec.rb +26 -0
- data/spec/unit/key/embeddable/response_spec.rb +55 -0
- data/spec/unit/key/embeddable/retriever_spec.rb +38 -0
- data/spec/unit/key/embeddable_spec.rb +7 -0
- data/spec/unit/key/property/builder_spec.rb +154 -0
- data/spec/unit/key/property/response_spec.rb +22 -0
- data/spec/unit/key/property/retriever_spec.rb +31 -0
- data/spec/unit/key/property_spec.rb +39 -0
- data/spec/unit/key/relation/builder_spec.rb +53 -0
- data/spec/unit/key/relation/response_spec.rb +105 -0
- data/spec/unit/key/relation_spec.rb +71 -0
- data/spec/unit/key_spec.rb +101 -0
- data/spec/unit/response_spec.rb +44 -0
- data/spec/unit/rest_model_spec.rb +46 -0
- data/spec/unit/serialization/boolean_spec.rb +25 -0
- data/spec/unit/serialization/date_spec.rb +13 -0
- data/spec/unit/serialization/float_spec.rb +13 -0
- data/spec/unit/serialization/integer_spec.rb +13 -0
- data/spec/unit/serialization/string_spec.rb +11 -0
- data/spec/unit/source/path_spec.rb +62 -0
- data/spec/unit/source/retriever_spec.rb +85 -0
- 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,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,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,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,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
|