lhs 0.3.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.
- checksums.yaml +7 -0
- data/.gitignore +38 -0
- data/Gemfile +11 -0
- data/README.md +67 -0
- data/Rakefile +26 -0
- data/docs/collections.md +28 -0
- data/docs/data.md +39 -0
- data/docs/examples/claim_no_include.json +16 -0
- data/docs/examples/claim_with_include.json +47 -0
- data/docs/items.md +55 -0
- data/docs/service.jpg +0 -0
- data/docs/service.pdf +649 -3
- data/docs/services.md +191 -0
- data/lhs.gemspec +31 -0
- data/lib/lhs.rb +6 -0
- data/lib/lhs/collection.rb +78 -0
- data/lib/lhs/concerns/data/json.rb +12 -0
- data/lib/lhs/concerns/item/destroy.rb +15 -0
- data/lib/lhs/concerns/item/save.rb +29 -0
- data/lib/lhs/concerns/item/update.rb +24 -0
- data/lib/lhs/concerns/service/all.rb +24 -0
- data/lib/lhs/concerns/service/batch.rb +37 -0
- data/lib/lhs/concerns/service/build.rb +17 -0
- data/lib/lhs/concerns/service/create.rb +26 -0
- data/lib/lhs/concerns/service/endpoints.rb +82 -0
- data/lib/lhs/concerns/service/find.rb +36 -0
- data/lib/lhs/concerns/service/find_by.rb +35 -0
- data/lib/lhs/concerns/service/first.rb +19 -0
- data/lib/lhs/concerns/service/includes.rb +21 -0
- data/lib/lhs/concerns/service/mapping.rb +23 -0
- data/lib/lhs/concerns/service/model.rb +16 -0
- data/lib/lhs/concerns/service/request.rb +96 -0
- data/lib/lhs/concerns/service/where.rb +16 -0
- data/lib/lhs/data.rb +103 -0
- data/lib/lhs/errors.rb +86 -0
- data/lib/lhs/item.rb +83 -0
- data/lib/lhs/proxy.rb +26 -0
- data/lib/lhs/service.rb +20 -0
- data/lib/lhs/version.rb +3 -0
- data/script/ci/build.sh +19 -0
- data/spec/collection/meta_data_spec.rb +54 -0
- data/spec/collection/respond_to_spec.rb +19 -0
- data/spec/collection/without_object_items_spec.rb +26 -0
- data/spec/data/collection_spec.rb +36 -0
- data/spec/data/item_spec.rb +44 -0
- data/spec/data/merge_spec.rb +32 -0
- data/spec/data/raw_spec.rb +39 -0
- data/spec/data/respond_to_spec.rb +26 -0
- data/spec/data/root_spec.rb +25 -0
- data/spec/data/to_json_spec.rb +39 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/images/.keep +0 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/controllers/concerns/.keep +0 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/mailers/.keep +0 -0
- data/spec/dummy/app/models/.keep +0 -0
- data/spec/dummy/app/models/concerns/.keep +0 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +14 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +34 -0
- data/spec/dummy/config/environments/production.rb +75 -0
- data/spec/dummy/config/environments/test.rb +39 -0
- data/spec/dummy/config/initializers/assets.rb +8 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +9 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +56 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/lib/assets/.keep +0 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/item/destroy_spec.rb +39 -0
- data/spec/item/getter_spec.rb +24 -0
- data/spec/item/respond_to_spec.rb +29 -0
- data/spec/item/save_errors_spec.rb +48 -0
- data/spec/item/save_spec.rb +58 -0
- data/spec/item/setter_spec.rb +38 -0
- data/spec/item/update_spec.rb +56 -0
- data/spec/proxy/load_spec.rb +47 -0
- data/spec/rails_helper.rb +9 -0
- data/spec/service/all_spec.rb +31 -0
- data/spec/service/build_spec.rb +25 -0
- data/spec/service/create_spec.rb +81 -0
- data/spec/service/creation_failed_spec.rb +54 -0
- data/spec/service/endpoint_misconfiguration_spec.rb +26 -0
- data/spec/service/endpoint_options_spec.rb +23 -0
- data/spec/service/endpoints_spec.rb +57 -0
- data/spec/service/find_by_spec.rb +49 -0
- data/spec/service/find_each_spec.rb +47 -0
- data/spec/service/find_in_batches_spec.rb +68 -0
- data/spec/service/find_spec.rb +71 -0
- data/spec/service/first_spec.rb +39 -0
- data/spec/service/includes_spec.rb +61 -0
- data/spec/service/mapping_spec.rb +72 -0
- data/spec/service/model_name_spec.rb +17 -0
- data/spec/service/request_spec.rb +22 -0
- data/spec/service/where_spec.rb +33 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/support/cleanup_configuration.rb +17 -0
- data/spec/support/cleanup_services.rb +20 -0
- data/spec/support/fixtures/json/feedback.json +11 -0
- data/spec/support/fixtures/json/feedbacks.json +174 -0
- data/spec/support/fixtures/json/localina_content_ad.json +23 -0
- data/spec/support/load_json.rb +3 -0
- metadata +346 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'active_support'
|
|
2
|
+
|
|
3
|
+
class LHS::Service
|
|
4
|
+
|
|
5
|
+
module Build
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
module ClassMethods
|
|
9
|
+
|
|
10
|
+
def build(data = {})
|
|
11
|
+
data = LHS::Data.new(data, nil, self)
|
|
12
|
+
item = LHS::Item.new(data)
|
|
13
|
+
LHS::Data.new(item, nil, self)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require 'active_support'
|
|
2
|
+
|
|
3
|
+
class LHS::Service
|
|
4
|
+
|
|
5
|
+
module Create
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
module ClassMethods
|
|
9
|
+
|
|
10
|
+
def create(data = {})
|
|
11
|
+
create!(data)
|
|
12
|
+
rescue LHC::Error => e
|
|
13
|
+
json = JSON.parse(data.to_json)
|
|
14
|
+
data = LHS::Data.new(json, nil, self.class, e.response.request)
|
|
15
|
+
item = LHS::Item.new(data)
|
|
16
|
+
item.errors = LHS::Errors.new(e.response)
|
|
17
|
+
LHS::Data.new(item, data)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def create!(data = {})
|
|
21
|
+
url = instance.compute_url!(data)
|
|
22
|
+
instance.request(url: url, method: :post, body: data.to_json, headers: {'Content-Type' => 'application/json'})
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
require 'active_support'
|
|
2
|
+
|
|
3
|
+
class LHS::Service
|
|
4
|
+
|
|
5
|
+
# An endpoint is an url that leads to a backend resource.
|
|
6
|
+
# A service can contain multiple endpoints.
|
|
7
|
+
# The endpoint that is used to request data is choosen
|
|
8
|
+
# based on the provided parameters.
|
|
9
|
+
module Endpoints
|
|
10
|
+
extend ActiveSupport::Concern
|
|
11
|
+
|
|
12
|
+
attr_accessor :endpoints
|
|
13
|
+
|
|
14
|
+
module ClassMethods
|
|
15
|
+
|
|
16
|
+
# Adds the endpoint to the list of endpoints.
|
|
17
|
+
def endpoint(url, options = nil)
|
|
18
|
+
endpoint = LHC::Endpoint.new(url, options)
|
|
19
|
+
instance.sanity_check(endpoint)
|
|
20
|
+
instance.endpoints.push(endpoint)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def initialize
|
|
25
|
+
self.endpoints = []
|
|
26
|
+
super
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Find an endpoint based on the provided parameters.
|
|
30
|
+
# If no parameters are provided it finds the base endpoint
|
|
31
|
+
# otherwise it finds the endpoint that matches the parameters best.
|
|
32
|
+
def find_endpoint(params = {})
|
|
33
|
+
endpoint = find_best_endpoint(params) if params && params.keys.count > 0
|
|
34
|
+
endpoint ||= find_base_endpoint
|
|
35
|
+
endpoint
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Prevent clashing endpoints.
|
|
39
|
+
def sanity_check(endpoint)
|
|
40
|
+
placeholders = endpoint.placeholders
|
|
41
|
+
fail 'Clashing endpoints.' if endpoints.any? { |e| e.placeholders.sort == placeholders.sort }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Computes the url from params
|
|
45
|
+
# by identifiying endpoint and compiles it if necessary.
|
|
46
|
+
# Id in params is threaded in a special way.
|
|
47
|
+
def compute_url!(params)
|
|
48
|
+
endpoint = find_endpoint(params)
|
|
49
|
+
url = endpoint.compile(params)
|
|
50
|
+
url += "/#{params.delete(:id)}" if params && params[:id]
|
|
51
|
+
endpoint.remove_interpolated_params!(params)
|
|
52
|
+
url
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
# Finds the best endpoint.
|
|
58
|
+
# The best endpoint is the one where all placeholders are interpolated.
|
|
59
|
+
def find_best_endpoint(params)
|
|
60
|
+
sorted_endpoints.find do |endpoint|
|
|
61
|
+
endpoint.placeholders.all? { |match| endpoint.find_value(match, params) }
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Sort endpoints by number of placeholders, heighest first
|
|
66
|
+
def sorted_endpoints
|
|
67
|
+
endpoints.sort{|a, b| b.placeholders.count <=> a.placeholders.count }
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Finds the base endpoint.
|
|
71
|
+
# A base endpoint is the one thats has the least amont of placeholers.
|
|
72
|
+
# There cannot be multiple base endpoints.
|
|
73
|
+
def find_base_endpoint
|
|
74
|
+
endpoints = self.endpoints.group_by do |endpoint|
|
|
75
|
+
endpoint.placeholders.length
|
|
76
|
+
end
|
|
77
|
+
bases = endpoints[endpoints.keys.min]
|
|
78
|
+
fail 'Multiple base endpoints found' if bases.count > 1
|
|
79
|
+
bases.first
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require 'active_support'
|
|
2
|
+
|
|
3
|
+
class LHS::Service
|
|
4
|
+
|
|
5
|
+
module Find
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
module ClassMethods
|
|
9
|
+
|
|
10
|
+
# Find a single uniqe record
|
|
11
|
+
def find(args)
|
|
12
|
+
if args.is_a? Hash
|
|
13
|
+
find_with_parameters(args)
|
|
14
|
+
else
|
|
15
|
+
find_by_id(args)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def find_with_parameters(params)
|
|
22
|
+
data = instance.request(params: params)
|
|
23
|
+
if data._proxy.is_a?(LHS::Collection)
|
|
24
|
+
fail LHC::NotFound.new('Requested unique item. Multiple were found.', data._request.response) if data.count > 1
|
|
25
|
+
data.first || fail(LHC::NotFound.new('No item was found.', data._request.response))
|
|
26
|
+
else
|
|
27
|
+
data
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def find_by_id(id)
|
|
32
|
+
instance.request(params: { id: id })
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require 'active_support'
|
|
2
|
+
|
|
3
|
+
class LHS::Service
|
|
4
|
+
|
|
5
|
+
module FindBy
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
module ClassMethods
|
|
9
|
+
|
|
10
|
+
# Fetch some record by parameters
|
|
11
|
+
def find_by(params = {})
|
|
12
|
+
_find_by(params)
|
|
13
|
+
rescue LHC::NotFound
|
|
14
|
+
nil
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Raise if no record was found
|
|
18
|
+
def find_by!(params = {})
|
|
19
|
+
_find_by(params)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def _find_by(params)
|
|
25
|
+
params = params.dup.merge(limit: 1)
|
|
26
|
+
data = instance.request(params: params)
|
|
27
|
+
if data._proxy.is_a?(LHS::Collection)
|
|
28
|
+
data.first || fail(LHC::NotFound.new('No item was found.', data._request.response))
|
|
29
|
+
else
|
|
30
|
+
data
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'active_support'
|
|
2
|
+
|
|
3
|
+
class LHS::Service
|
|
4
|
+
|
|
5
|
+
module Includes
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
attr_accessor :includes
|
|
9
|
+
|
|
10
|
+
module ClassMethods
|
|
11
|
+
|
|
12
|
+
def includes(args)
|
|
13
|
+
class_clone = clone
|
|
14
|
+
class_clone.instance.endpoints = instance.endpoints
|
|
15
|
+
class_clone.instance.mapping = instance.mapping
|
|
16
|
+
class_clone.instance.includes = args
|
|
17
|
+
class_clone
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require 'active_support'
|
|
2
|
+
|
|
3
|
+
class LHS::Service
|
|
4
|
+
|
|
5
|
+
# Mapping allows to configure some accessors that access data using a provided proc
|
|
6
|
+
module Mapping
|
|
7
|
+
extend ActiveSupport::Concern
|
|
8
|
+
|
|
9
|
+
attr_accessor :mapping
|
|
10
|
+
|
|
11
|
+
module ClassMethods
|
|
12
|
+
|
|
13
|
+
def map(name, block)
|
|
14
|
+
instance.mapping[name] = block
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def initialize
|
|
19
|
+
self.mapping = {}
|
|
20
|
+
super
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
require 'active_support'
|
|
2
|
+
|
|
3
|
+
class LHS::Service
|
|
4
|
+
|
|
5
|
+
module Request
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
def request(options)
|
|
9
|
+
if options.is_a? Array
|
|
10
|
+
multiple_requests(options)
|
|
11
|
+
else
|
|
12
|
+
single_request(options)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def multiple_requests(options)
|
|
19
|
+
options.map { |options| process_options(options) }
|
|
20
|
+
responses = LHC.request(options)
|
|
21
|
+
data = responses.map{ |response| LHS::Data.new(response.body, nil, self.class, response.request) }
|
|
22
|
+
data = LHS::Data.new(data, nil, self.class)
|
|
23
|
+
handle_includes(data) if includes
|
|
24
|
+
data
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def single_request(options)
|
|
28
|
+
response = LHC.request(process_options(options))
|
|
29
|
+
data = LHS::Data.new(response.body, nil, self.class, response.request)
|
|
30
|
+
handle_includes(data) if includes
|
|
31
|
+
data
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Merge explicit params and take configured endpoints options as base
|
|
35
|
+
def process_options(options)
|
|
36
|
+
endpoint = find_endpoint(options[:params])
|
|
37
|
+
options = (endpoint.options || {}).merge(options)
|
|
38
|
+
options[:url] = compute_url!(options[:params]) unless options.key?(:url)
|
|
39
|
+
merge_explicit_params!(options[:params])
|
|
40
|
+
options.delete(:params) if options[:params] && options[:params].empty?
|
|
41
|
+
options
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Merge explicit params nested in 'params' namespace with original hash.
|
|
45
|
+
def merge_explicit_params!(params)
|
|
46
|
+
return true unless params
|
|
47
|
+
explicit_params = params[:params]
|
|
48
|
+
params.delete(:params)
|
|
49
|
+
params.merge!(explicit_params) if explicit_params
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def handle_includes(data)
|
|
53
|
+
if includes.is_a? Hash
|
|
54
|
+
includes.keys.each { |key| handle_include(data, key) }
|
|
55
|
+
else
|
|
56
|
+
handle_include(data, includes)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def handle_include(data, key)
|
|
61
|
+
options = if data._proxy.is_a? LHS::Collection
|
|
62
|
+
include_multiple(data, key)
|
|
63
|
+
else
|
|
64
|
+
include_single(data, key)
|
|
65
|
+
end
|
|
66
|
+
addition = if (further_keys = includes.fetch(key, nil) if includes.is_a? Hash)
|
|
67
|
+
self.class.includes(further_keys).instance.request(options)
|
|
68
|
+
else
|
|
69
|
+
self.class.includes(nil).instance.request(options)
|
|
70
|
+
end
|
|
71
|
+
extend(data, addition, key)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def extend(data, addition, key)
|
|
75
|
+
if data._proxy.is_a? LHS::Collection
|
|
76
|
+
data.each_with_index do |item, i|
|
|
77
|
+
item = item[i] if item.is_a? LHS::Collection
|
|
78
|
+
item._raw[key.to_s].merge!(addition[i]._raw)
|
|
79
|
+
end
|
|
80
|
+
elsif data._proxy.is_a? LHS::Item
|
|
81
|
+
data._raw[key.to_s].merge!(addition._raw)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def include_multiple(data, key)
|
|
86
|
+
data.map do |item|
|
|
87
|
+
include_single(item, key)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def include_single(item, key)
|
|
92
|
+
link = item[key]
|
|
93
|
+
{ url: link.href }
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require 'active_support'
|
|
2
|
+
|
|
3
|
+
class LHS::Service
|
|
4
|
+
|
|
5
|
+
module Where
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
module ClassMethods
|
|
9
|
+
|
|
10
|
+
# Used to query data from the service.
|
|
11
|
+
def where(params = {})
|
|
12
|
+
instance.request(params: params)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
data/lib/lhs/data.rb
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
require File.join(__dir__, 'proxy.rb')
|
|
2
|
+
Dir[File.dirname(__FILE__) + '/concerns/data/*.rb'].each {|file| require file }
|
|
3
|
+
|
|
4
|
+
# Data provides functionalities to accesses information
|
|
5
|
+
class LHS::Data
|
|
6
|
+
include Json
|
|
7
|
+
|
|
8
|
+
# prevent clashing with attributes of underlying data
|
|
9
|
+
attr_accessor :_proxy, :_raw, :_parent, :_service, :_request
|
|
10
|
+
|
|
11
|
+
def initialize(input, parent = nil, service = nil, request = nil)
|
|
12
|
+
self._raw = raw_from_input(input)
|
|
13
|
+
self._proxy = proxy_from_input(input)
|
|
14
|
+
self._service = service
|
|
15
|
+
self._parent = parent
|
|
16
|
+
self._request = request
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# merging data
|
|
20
|
+
# e.g. when loading remote data via link
|
|
21
|
+
def merge!(data)
|
|
22
|
+
return false unless data._raw.is_a?(Hash)
|
|
23
|
+
_raw.merge! data._raw
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def _root
|
|
27
|
+
root = self
|
|
28
|
+
root = root._parent while root && root._parent
|
|
29
|
+
root
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def class
|
|
33
|
+
_root._service
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
protected
|
|
37
|
+
|
|
38
|
+
# Use existing mapping to provide data
|
|
39
|
+
# or forward to proxy
|
|
40
|
+
def method_missing(name, *args, &block)
|
|
41
|
+
if root_item? && mapping = _root._service.instance.mapping[name]
|
|
42
|
+
mapping.call(self)
|
|
43
|
+
else
|
|
44
|
+
_proxy.send(name, *args, &block)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def respond_to_missing?(name, include_all = false)
|
|
49
|
+
(root_item? && _root._service.instance.mapping.keys.map(&:to_s).include?(name.to_s)) ||
|
|
50
|
+
_proxy.respond_to?(name, include_all)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
def collection_proxy?(input)
|
|
56
|
+
(_raw.is_a?(Hash) && _raw['items']) ||
|
|
57
|
+
input.is_a?(Array) || _raw.is_a?(Array)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def root_item
|
|
61
|
+
return if self._proxy.class != LHS::Item
|
|
62
|
+
root = root_item = self
|
|
63
|
+
loop do
|
|
64
|
+
root = root._parent
|
|
65
|
+
root_item = root if root && root._proxy.is_a?(LHS::Item)
|
|
66
|
+
if !(root && root._parent)
|
|
67
|
+
break
|
|
68
|
+
else
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
root_item
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def root_item?
|
|
75
|
+
root_item == self
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def root?
|
|
79
|
+
_root == self
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def proxy_from_input(input)
|
|
83
|
+
if input.is_a? LHS::Proxy
|
|
84
|
+
input
|
|
85
|
+
elsif collection_proxy?(input)
|
|
86
|
+
LHS::Collection.new(self)
|
|
87
|
+
else
|
|
88
|
+
LHS::Item.new(self)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def raw_from_input(input)
|
|
93
|
+
if input.is_a?(String) && input.length > 0
|
|
94
|
+
JSON.parse(input)
|
|
95
|
+
elsif defined?(input._raw)
|
|
96
|
+
input._raw
|
|
97
|
+
elsif defined?(input._data)
|
|
98
|
+
input._data._raw
|
|
99
|
+
else
|
|
100
|
+
input
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|