ncore 1.0.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 +19 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +36 -0
- data/Rakefile +1 -0
- data/example/lib/my_api.rb +12 -0
- data/example/lib/my_api/api_config.rb +33 -0
- data/example/lib/my_api/customer.rb +8 -0
- data/example/lib/my_api/rails/log_subscriber.rb +10 -0
- data/example/lib/my_api/rails/railtie.rb +13 -0
- data/example/lib/my_api/version.rb +3 -0
- data/lib/ncore.rb +14 -0
- data/lib/ncore/associations.rb +81 -0
- data/lib/ncore/attributes.rb +157 -0
- data/lib/ncore/base.rb +35 -0
- data/lib/ncore/builder.rb +34 -0
- data/lib/ncore/client.rb +301 -0
- data/lib/ncore/collection.rb +11 -0
- data/lib/ncore/configuration.rb +56 -0
- data/lib/ncore/exceptions.rb +45 -0
- data/lib/ncore/identity.rb +26 -0
- data/lib/ncore/lifecycle.rb +36 -0
- data/lib/ncore/methods/all.rb +30 -0
- data/lib/ncore/methods/build.rb +16 -0
- data/lib/ncore/methods/count.rb +13 -0
- data/lib/ncore/methods/create.rb +33 -0
- data/lib/ncore/methods/delete.rb +19 -0
- data/lib/ncore/methods/delete_single.rb +19 -0
- data/lib/ncore/methods/find.rb +26 -0
- data/lib/ncore/methods/find_single.rb +34 -0
- data/lib/ncore/methods/update.rb +29 -0
- data/lib/ncore/rails/active_model.rb +44 -0
- data/lib/ncore/rails/log_subscriber.rb +116 -0
- data/lib/ncore/singleton_base.rb +33 -0
- data/lib/ncore/ssl/ca-certificates.crt +4027 -0
- data/lib/ncore/util.rb +61 -0
- data/lib/ncore/version.rb +3 -0
- data/ncore.gemspec +27 -0
- metadata +158 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
module NCore
|
2
|
+
module Identity
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
def class_name
|
7
|
+
self.name.split('::')[-1]
|
8
|
+
end
|
9
|
+
|
10
|
+
def module_name
|
11
|
+
self.name.split('::')[0..-2].join('::')
|
12
|
+
end
|
13
|
+
|
14
|
+
def attrib_name
|
15
|
+
class_name.underscore
|
16
|
+
end
|
17
|
+
alias :json_root :attrib_name
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
def json_root
|
22
|
+
self.class.json_root
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module NCore
|
2
|
+
module Lifecycle
|
3
|
+
|
4
|
+
def errors?
|
5
|
+
@errors.any?
|
6
|
+
end
|
7
|
+
|
8
|
+
def valid?
|
9
|
+
@errors.none?
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
def save(update_params={})
|
14
|
+
if id.present?
|
15
|
+
if respond_to? :update, true
|
16
|
+
update(update_params)
|
17
|
+
else
|
18
|
+
raise self.class.parent::Error, "Updating #{self.class.name} objects is not supported."
|
19
|
+
end
|
20
|
+
else
|
21
|
+
if respond_to? :create, true
|
22
|
+
create(update_params)
|
23
|
+
else
|
24
|
+
raise self.class.parent::Error, "Creating #{self.class.name} objects is not supported."
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
alias :update_attributes :save
|
29
|
+
|
30
|
+
def save!(update_params={})
|
31
|
+
save(update_params) || raise(self.class.parent::RecordInvalid, self)
|
32
|
+
end
|
33
|
+
alias :update_attributes! :save!
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module NCore
|
2
|
+
module All
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
def all(params={}, api_creds=nil)
|
7
|
+
parsed, creds = request(:get, url, api_creds, params)
|
8
|
+
if parsed[:errors].any?
|
9
|
+
raise parent::QueryError, parsed[:errors]
|
10
|
+
end
|
11
|
+
Collection.new.tap do |coll|
|
12
|
+
coll.metadata = parsed[:metadata]
|
13
|
+
parsed[:data].each do |hash|
|
14
|
+
if key = hash[:object]
|
15
|
+
coll << discover_class(key, self).new(hash.merge(metadata: parsed[:metadata]), creds)
|
16
|
+
else
|
17
|
+
coll << new(hash.merge(metadata: parsed[:metadata]), creds)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def first(params={}, api_creds=nil)
|
24
|
+
params = params.with_indifferent_access.merge(max_results: 1)
|
25
|
+
all(params, api_creds).first
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module NCore
|
2
|
+
module Build
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
def build(params={}, api_creds=nil)
|
7
|
+
parsed, creds = request(:get, url+'/new', api_creds, params)
|
8
|
+
if parsed[:errors].any?
|
9
|
+
raise parent::QueryError, parsed[:errors]
|
10
|
+
end
|
11
|
+
new(parsed, creds)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module NCore
|
2
|
+
module Create
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
def create!(attribs={}, api_creds=nil)
|
7
|
+
obj = create(attribs, api_creds)
|
8
|
+
if obj.errors.any?
|
9
|
+
raise parent::RecordInvalid, obj
|
10
|
+
end
|
11
|
+
obj
|
12
|
+
end
|
13
|
+
|
14
|
+
# always returns a new object; check .errors? or .valid? to see how it went
|
15
|
+
def create(attribs={}, api_creds=nil)
|
16
|
+
params = {json_root => attribs}
|
17
|
+
parsed, creds = request(:post, url, api_creds, params)
|
18
|
+
new(attribs, creds).send(:load, parsed)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def create(attribs={})
|
25
|
+
params = {json_root => attribs}
|
26
|
+
parsed, @api_creds = request(:post, self.class.url, api_creds, params)
|
27
|
+
load(data: attribs) if parsed[:errors].any?
|
28
|
+
load(parsed)
|
29
|
+
errors.empty? ? self : false
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module NCore
|
2
|
+
module Delete
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
def delete(id, params={}, api_creds=nil)
|
7
|
+
obj = new({id: id}, api_creds)
|
8
|
+
obj.delete(params) || raise(parent::RecordInvalid, obj)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def delete(params={})
|
13
|
+
parsed, @api_creds = request(:delete, url, api_creds, params)
|
14
|
+
load(parsed)
|
15
|
+
errors.empty? ? self : false
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module NCore
|
2
|
+
module DeleteSingle
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
def delete(params={}, api_creds=nil)
|
7
|
+
obj = new({}, api_creds)
|
8
|
+
obj.delete(params) || raise(parent::RecordInvalid, obj)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def delete(params={})
|
13
|
+
parsed, @api_creds = request(:delete, url, api_creds, params)
|
14
|
+
load(parsed)
|
15
|
+
errors.empty? ? self : false
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module NCore
|
2
|
+
module Find
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
def find(id, params={}, api_creds=nil)
|
7
|
+
o = new({id: id}, api_creds)
|
8
|
+
o.reload(params)
|
9
|
+
end
|
10
|
+
|
11
|
+
def retrieve(id, params={}, api_creds=nil)
|
12
|
+
find id, params, api_creds
|
13
|
+
rescue parent::RecordNotFound
|
14
|
+
false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def reload(find_params={})
|
19
|
+
return if id.blank?
|
20
|
+
parsed, @api_creds = request(:get, url, api_creds, find_params)
|
21
|
+
@attribs = {}.with_indifferent_access
|
22
|
+
load(parsed)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module NCore
|
2
|
+
module FindSingle
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
def find(params={}, api_creds=nil)
|
7
|
+
parsed, creds = request(:get, url, api_creds, params)
|
8
|
+
if parsed[:errors].any?
|
9
|
+
raise parent::QueryError, parsed[:errors]
|
10
|
+
end
|
11
|
+
new(parsed, creds)
|
12
|
+
end
|
13
|
+
|
14
|
+
def retrieve(params={}, api_creds=nil)
|
15
|
+
find params, api_creds
|
16
|
+
rescue parent::RecordNotFound
|
17
|
+
false
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def id
|
22
|
+
'singleton'
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def reload(find_params={})
|
28
|
+
parsed, @api_creds = request(:get, url, api_creds, find_params)
|
29
|
+
@attribs = {}.with_indifferent_access
|
30
|
+
load(parsed)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module NCore
|
2
|
+
module Update
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
def update!(id, attribs, api_creds=nil)
|
7
|
+
obj = new({id: id}, api_creds)
|
8
|
+
obj.save!(attribs)
|
9
|
+
end
|
10
|
+
|
11
|
+
def update(id, attribs, api_creds=nil)
|
12
|
+
obj = new({id: id}, api_creds)
|
13
|
+
obj.save(attribs)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def update(attribs={})
|
21
|
+
params = {json_root => attribs}
|
22
|
+
parsed, @api_creds = request(:put, url, api_creds, params)
|
23
|
+
load(data: attribs) if parsed[:errors].any?
|
24
|
+
load(parsed)
|
25
|
+
errors.empty? ? self : false
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'active_model'
|
2
|
+
|
3
|
+
module NCore
|
4
|
+
module ActiveModel
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
include ::ActiveModel::Conversion
|
9
|
+
extend ::ActiveModel::Translation
|
10
|
+
alias :errors :errors_for_actionpack
|
11
|
+
end
|
12
|
+
|
13
|
+
if defined?(Rails)
|
14
|
+
def logger
|
15
|
+
Rails.logger
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def new_record?
|
20
|
+
!id
|
21
|
+
end
|
22
|
+
|
23
|
+
def persisted?
|
24
|
+
!new_record?
|
25
|
+
end
|
26
|
+
|
27
|
+
def destroy(*args)
|
28
|
+
delete(*args)
|
29
|
+
end
|
30
|
+
|
31
|
+
# actionpack 4 requires a more robust Errors object
|
32
|
+
def errors_for_actionpack
|
33
|
+
e0 = ::ActiveModel::Errors.new(self)
|
34
|
+
@errors.each do |e|
|
35
|
+
e0.add :base, e
|
36
|
+
end
|
37
|
+
e0
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
Base.send :include, ActiveModel
|
43
|
+
SingletonBase.send :include, ActiveModel
|
44
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module NCore
|
2
|
+
module LogSubscriber
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
class_attribute :runtime_variable, instance_accessor: false
|
7
|
+
|
8
|
+
# make :request show up in parent::LogSubscriber.new.public_methods(false)
|
9
|
+
define_method :request do |event|
|
10
|
+
log_request event
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module ClassMethods
|
15
|
+
def runtime=(value)
|
16
|
+
Thread.current[runtime_variable] = value
|
17
|
+
end
|
18
|
+
|
19
|
+
def runtime
|
20
|
+
Thread.current[runtime_variable] ||= 0
|
21
|
+
end
|
22
|
+
|
23
|
+
def reset_runtime
|
24
|
+
rt, self.runtime = runtime, 0
|
25
|
+
rt
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def log_request(event)
|
30
|
+
self.class.runtime += event.duration
|
31
|
+
|
32
|
+
env = event.payload
|
33
|
+
url = env[:url].to_s
|
34
|
+
http_method = env[:method].to_s.upcase
|
35
|
+
http_status = env[:status] || -1
|
36
|
+
|
37
|
+
msg = "%s %s" % [http_method, url]
|
38
|
+
res = " -> %d (%.1f ms)" % [http_status, event.duration]
|
39
|
+
|
40
|
+
msg = color(msg, ActiveSupport::LogSubscriber::YELLOW, false)
|
41
|
+
if (200..299).include? http_status
|
42
|
+
res = color(res, ActiveSupport::LogSubscriber::GREEN, true)
|
43
|
+
else
|
44
|
+
res = color(res, ActiveSupport::LogSubscriber::RED, true)
|
45
|
+
end
|
46
|
+
|
47
|
+
if (200..299).include? http_status
|
48
|
+
debug " #{msg}"
|
49
|
+
debug " #{res}"
|
50
|
+
else
|
51
|
+
error " #{msg}"
|
52
|
+
error " #{res}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
# Extends ActionController's logging system so as to include Api
|
59
|
+
# cumulative runtime at the end of each action's log entry.
|
60
|
+
# See ActiveRecord::Railties::ControllerRuntime for reference
|
61
|
+
module ControllerRuntime
|
62
|
+
extend ActiveSupport::Concern
|
63
|
+
|
64
|
+
protected
|
65
|
+
|
66
|
+
mattr_accessor :api_runtime_list
|
67
|
+
self.api_runtime_list = []
|
68
|
+
|
69
|
+
def process_action(action, *args)
|
70
|
+
api_runtime_list.each do |arl|
|
71
|
+
arl[:log_sub].reset_runtime
|
72
|
+
arl[:rt] = 0
|
73
|
+
end
|
74
|
+
super
|
75
|
+
end
|
76
|
+
|
77
|
+
def cleanup_view_runtime
|
78
|
+
rt_before_render = {}
|
79
|
+
rt_after_render = {}
|
80
|
+
api_runtime_list.each do |arl|
|
81
|
+
rt_before_render[arl[:title]] = arl[:log_sub].reset_runtime
|
82
|
+
end
|
83
|
+
runtime = super
|
84
|
+
api_runtime_list.each do |arl|
|
85
|
+
rt_after_render[arl[:title]] = arl[:log_sub].reset_runtime
|
86
|
+
arl[:rt] = rt_before_render[arl[:title]] + rt_after_render[arl[:title]]
|
87
|
+
end
|
88
|
+
runtime - rt_after_render.values.sum
|
89
|
+
end
|
90
|
+
|
91
|
+
def append_info_to_payload(payload)
|
92
|
+
super
|
93
|
+
payload[:api_runtime] = {}
|
94
|
+
api_runtime_list.each do |arl|
|
95
|
+
payload[:api_runtime][arl[:title]] = arl[:rt] + arl[:log_sub].reset_runtime
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
module ClassMethods
|
101
|
+
|
102
|
+
def log_process_action(payload)
|
103
|
+
messages, rt_set = super, payload[:api_runtime]
|
104
|
+
rt_set.each do |title, rt|
|
105
|
+
messages << ("#{title}: %.1fms" % rt.to_f) if rt && rt > 0
|
106
|
+
end if rt_set
|
107
|
+
messages
|
108
|
+
end
|
109
|
+
|
110
|
+
def register_api_runtime(log_sub, title)
|
111
|
+
ControllerRuntime.api_runtime_list += [{log_sub: log_sub, title: title, rt: 0}]
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
end
|