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.
- 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
|