naranya_ecm-sdk 0.0.42 → 0.0.43
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 +4 -4
- data/.gitignore +2 -1
- data/.rspec +3 -0
- data/Gemfile +1 -2
- data/lib/aasm/persistence/rest_persistence.rb +11 -6
- data/lib/naranya_ecm-sdk.rb +4 -65
- data/lib/naranya_ecm-sdk/version.rb +1 -1
- data/lib/naranya_ecm/models/media_resource.rb +1 -1
- data/lib/naranya_ecm/models/notification.rb +2 -2
- data/lib/naranya_ecm/rest/errors.rb +16 -3
- data/lib/naranya_ecm/rest/finder_methods.rb +4 -4
- data/lib/naranya_ecm/rest/model.rb +87 -19
- data/lib/naranya_ecm/rest/persistence.rb +234 -46
- data/lib/naranya_ecm/rest/relation.rb +15 -5
- data/lib/naranya_ecm/search/results.rb +19 -17
- data/lib/ncontent-sdk-testing.rb +13 -0
- data/lib/ncontent-sdk.rb +85 -0
- data/lib/ncontent/sdk/config.rb +75 -0
- data/lib/ncontent/sdk/faraday_middleware.rb +4 -0
- data/lib/ncontent/sdk/faraday_middleware/required_response_format.rb +14 -0
- data/lib/ncontent/sdk/faraday_middleware/response_parser.rb +35 -0
- data/lib/ncontent/sdk/faraday_middleware/rest_api_call_benchmark.rb +49 -0
- data/lib/ncontent/sdk/railtie.rb +59 -0
- data/lib/ncontent/sdk/rest_client.rb +131 -0
- data/lib/ncontent/sdk/testing/server_mock.rb +316 -0
- data/naranya_ecm-sdk.gemspec +24 -10
- metadata +85 -68
- data/lib/naranya_ecm/rest/client.rb +0 -92
- data/spec/models/category_spec.rb +0 -16
- data/spec/models/content_spec.rb +0 -20
- data/spec/models/content_version_spec.rb +0 -7
- data/spec/models/download_authorization.rb +0 -7
- data/spec/models/media_spec.rb +0 -7
- data/spec/models/module_spec.rb +0 -18
- data/spec/spec_helper.rb +0 -47
- data/spec/support/naranya_ecms_shared_specs.rb +0 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 183c574009558b2788b71cce8899e52e9a948344
|
4
|
+
data.tar.gz: d1ffcd41db7e78e43251c7714c7e7ec686223b15
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c010113401ef577a7b24a41e50614c4d98c77c91eba374f421279e224aa2529fac258423b9e2d19f00451d7950a7dad90f8a7e209f2dee6ddc230a6a60dae6e7
|
7
|
+
data.tar.gz: 5fd603773082dbcd115d97e36b1ab9f68649c3ae3bd81b1e717ea43b32f87389fdda26188de350378337c133ebd2511fea3560c9cf6e49de44b4965521f90d70
|
data/.gitignore
CHANGED
data/.rspec
ADDED
data/Gemfile
CHANGED
@@ -32,7 +32,7 @@ module AASM
|
|
32
32
|
base.send(:include, AASM::Persistence::RestPersistence::InstanceMethods)
|
33
33
|
|
34
34
|
base.before_validation(:aasm_ensure_initial_state, :on => :create)
|
35
|
-
|
35
|
+
|
36
36
|
# ensure initial aasm state even when validations are skipped
|
37
37
|
base.before_create(:aasm_ensure_initial_state)
|
38
38
|
|
@@ -108,18 +108,23 @@ module AASM
|
|
108
108
|
# end
|
109
109
|
|
110
110
|
private
|
111
|
-
|
111
|
+
|
112
112
|
def aasm_ensure_initial_state
|
113
113
|
send("#{self.class.aasm_column}=", aasm.enter_initial_state.to_s) if send(self.class.aasm_column).blank?
|
114
114
|
end
|
115
115
|
|
116
116
|
def aasm_fire_event(name, options, *args, &block)
|
117
117
|
local_success = super
|
118
|
-
|
118
|
+
|
119
119
|
if local_success
|
120
120
|
data = { name: name, target_type: self.class.name.demodulize, target_id: self.id }
|
121
|
-
|
122
|
-
|
121
|
+
|
122
|
+
response = NContent::SDK::RESTClient.post "/events.json" do |req|
|
123
|
+
req.headers[:content_type] = 'application/json'
|
124
|
+
req.body = ActiveSupport::JSON.encode(state_event: data)
|
125
|
+
end
|
126
|
+
|
127
|
+
remote_success = response.status < 400
|
123
128
|
unless remote_success
|
124
129
|
end
|
125
130
|
end
|
@@ -131,4 +136,4 @@ module AASM
|
|
131
136
|
|
132
137
|
end
|
133
138
|
end
|
134
|
-
end
|
139
|
+
end
|
data/lib/naranya_ecm-sdk.rb
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
require 'naranya_ecm-sdk/version'
|
2
2
|
|
3
3
|
require 'active_support/time'
|
4
|
-
require 'active_support/configurable'
|
5
4
|
require 'active_support/dependencies/autoload'
|
6
5
|
require 'active_support/core_ext/hash/indifferent_access.rb'
|
7
6
|
require 'yaml'
|
8
7
|
|
9
8
|
require 'fog/aws/storage' unless defined?(::Fog::AWS::Storage)
|
10
9
|
|
10
|
+
require 'ncontent-sdk'
|
11
|
+
|
11
12
|
module NaranyaEcm
|
12
13
|
|
13
14
|
extend ActiveSupport::Autoload
|
@@ -22,7 +23,6 @@ module NaranyaEcm
|
|
22
23
|
# that connects the NaranyaEcm models with the Naranya CaaS REST services.
|
23
24
|
module Rest
|
24
25
|
extend ActiveSupport::Autoload
|
25
|
-
autoload :Client
|
26
26
|
autoload :Errors
|
27
27
|
autoload :Persistence
|
28
28
|
autoload :Associations
|
@@ -65,68 +65,7 @@ module NaranyaEcm
|
|
65
65
|
autoload :Results
|
66
66
|
end
|
67
67
|
|
68
|
-
|
69
|
-
|
70
|
-
DEFAULT_CONFIG = {
|
71
|
-
site: "http://ecm.naranya.net:5000",
|
72
|
-
client_notify_url: "http://www.example.com/naranya_ecm/notifications",
|
73
|
-
notification_processing_modules: []
|
74
|
-
}.freeze
|
75
|
-
|
76
|
-
class << self
|
77
|
-
|
78
|
-
def storage
|
79
|
-
@storage ||= Fog::Storage.new options[:storage].except(:root_directory)
|
80
|
-
end
|
81
|
-
|
82
|
-
def root_directory
|
83
|
-
@root_directory ||= storage.directories.get(options[:storage][:root_directory])
|
84
|
-
end
|
85
|
-
|
86
|
-
def setup; yield config; end
|
87
|
-
def document_module; NaranyaEcm::Rest::Model; end
|
88
|
-
def timestamp_module; NaranyaEcm::Behaviors::Timestampable; end
|
89
|
-
|
90
|
-
def options
|
91
|
-
auto_conf unless config.present?
|
92
|
-
config
|
93
|
-
end
|
94
|
-
|
95
|
-
def cache
|
96
|
-
auto_conf unless config.present?
|
97
|
-
@cache ||= ActiveSupport::Cache.lookup_store *options[:cache]
|
98
|
-
end
|
99
|
-
|
100
|
-
def logger
|
101
|
-
auto_conf unless config.present?
|
102
|
-
@logger ||= Logger.new($stdout)
|
103
|
-
end
|
104
|
-
|
105
|
-
def load_config_from_yml(yml_path, env="production")
|
106
|
-
raise "YAML file doesn't extst" unless File.exist?(yml_path)
|
107
|
-
yml_config = DEFAULT_CONFIG.merge(YAML::load(ERB.new(File.read(yml_path)).result)[env])
|
108
|
-
.with_indifferent_access
|
109
|
-
setup { |config| yml_config.each { |key, val| config.send "#{key}=".to_sym, val } }
|
110
|
-
end
|
111
|
-
|
112
|
-
protected
|
113
|
-
|
114
|
-
def auto_conf
|
115
|
-
# Cargar configuracion dentro del folder de config en Rails:
|
116
|
-
if defined?(Rails)
|
117
|
-
yml_path = File.join(Rails.root, 'config', 'naranya_ecm.yml')
|
118
|
-
load_config_from_yml(yml_path, Rails.env)
|
119
|
-
|
120
|
-
# Use the Rails cache:
|
121
|
-
@cache = Rails.cache
|
122
|
-
|
123
|
-
# Use the Rails logger:
|
124
|
-
@logger = Rails.logger
|
125
|
-
elsif File.exists?('./naranya_ecm.yml')
|
126
|
-
load_config_from_yml('./naranya_ecm.yml')
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
end
|
68
|
+
def self.document_module; NaranyaEcm::Rest::Model; end
|
69
|
+
def self.timestamp_module; NaranyaEcm::Behaviors::Timestampable; end
|
131
70
|
|
132
71
|
end
|
@@ -95,7 +95,7 @@ module NaranyaEcm
|
|
95
95
|
# Returns the storage root directory, depending of the storage engine:
|
96
96
|
# - Amazon AWS S3: A Fog::Storage::AWS::Directory object
|
97
97
|
def self.root_directory
|
98
|
-
|
98
|
+
NContent::SDK.root_directory
|
99
99
|
end
|
100
100
|
|
101
101
|
def move_downloadable_to(path, force_move=false)
|
@@ -16,8 +16,8 @@ module NaranyaEcm
|
|
16
16
|
alias_method_chain :initialize, :attributes_hash
|
17
17
|
|
18
18
|
def process
|
19
|
-
|
20
|
-
|
19
|
+
NContent::SDK.logger.debug "NaranyaEcm::Notification: #{self.attributes}"
|
20
|
+
NContent::SDK.logger.debug "NaranyaEcm::Notification: No processing implemented."
|
21
21
|
end
|
22
22
|
|
23
23
|
def method_missing(method, *args, &block)
|
@@ -14,14 +14,14 @@ module NaranyaEcm::Rest
|
|
14
14
|
##
|
15
15
|
# Captura un response y genera + avienta una excepción.
|
16
16
|
def self.raise_by_failed_response(response, message = "")
|
17
|
-
klass = case response.
|
17
|
+
klass = case response.status
|
18
18
|
when 401 then AuthorizationRequired
|
19
19
|
when 403 then Forbidden
|
20
20
|
when 404 then ResourceNotFound
|
21
21
|
when 422 then UnprocessableEntity
|
22
22
|
else RemoteFailed
|
23
23
|
end
|
24
|
-
raise klass.new response, "Server responded with code #{response.
|
24
|
+
raise klass.new response, "Server responded with code #{response.status}. Message: #{message}"
|
25
25
|
end
|
26
26
|
|
27
27
|
end
|
@@ -73,6 +73,19 @@ module NaranyaEcm::Rest
|
|
73
73
|
end
|
74
74
|
|
75
75
|
class AuthorizationRequired < RestError
|
76
|
+
|
77
|
+
def self.parse_www_authenticate_header(response)
|
78
|
+
Hash[response.headers['WWW-Authenticate'].scan(/(\w+)="([^"]+)"/)] \
|
79
|
+
if response.headers['WWW-Authenticate']
|
80
|
+
end
|
81
|
+
|
82
|
+
delegate :parse_www_authenticate_header, to: :class
|
83
|
+
|
84
|
+
def initialize(given_response, msg = "")
|
85
|
+
data = parse_www_authenticate_header given_response
|
86
|
+
super given_response,
|
87
|
+
"#{data['error_description']} (HTTP status #{given_response.status})"
|
88
|
+
end
|
76
89
|
end
|
77
90
|
|
78
91
|
class Forbidden < RestError
|
@@ -84,4 +97,4 @@ module NaranyaEcm::Rest
|
|
84
97
|
class RemoteFailed < RestError
|
85
98
|
end
|
86
99
|
|
87
|
-
end
|
100
|
+
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'naranya_ecm/rest/errors'
|
2
|
-
require 'naranya_ecm/rest/client'
|
3
2
|
|
4
3
|
module NaranyaEcm::Rest
|
5
4
|
|
@@ -19,12 +18,13 @@ module NaranyaEcm::Rest
|
|
19
18
|
protected
|
20
19
|
|
21
20
|
def find_one(id)
|
22
|
-
self.load fetch_one(id)
|
21
|
+
found_resource = self.load fetch_one(id)
|
22
|
+
found_resource.instance_variable_set("@new_resource", false)
|
23
|
+
found_resource
|
23
24
|
end
|
24
25
|
|
25
26
|
def fetch_one(id)
|
26
|
-
|
27
|
-
Client.get("#{path}/#{id}.#{format}").to_hash
|
27
|
+
NContent::SDK::RESTClient.get("#{path}/#{id}.json").body
|
28
28
|
end
|
29
29
|
end
|
30
30
|
end
|
@@ -50,7 +50,7 @@ module NaranyaEcm::Rest
|
|
50
50
|
end
|
51
51
|
|
52
52
|
extend ActiveSupport::Concern
|
53
|
-
|
53
|
+
|
54
54
|
included do
|
55
55
|
|
56
56
|
include ActiveModel::Model
|
@@ -66,14 +66,16 @@ module NaranyaEcm::Rest
|
|
66
66
|
include NaranyaEcm::Rest::Persistence
|
67
67
|
|
68
68
|
extend NaranyaEcm::Rest::FinderMethods
|
69
|
-
|
69
|
+
|
70
70
|
alias_method_chain :initialize, :defaults
|
71
71
|
|
72
|
-
if
|
72
|
+
if NContent::SDK.config.extra_attributes.present? and
|
73
|
+
extra_fields = NContent::SDK.config.extra_attributes[self.name.demodulize.underscore]
|
74
|
+
|
73
75
|
extra_fields.each do |name, type|
|
74
|
-
|
76
|
+
|
75
77
|
field_options = {}
|
76
|
-
|
78
|
+
|
77
79
|
field_options[:type] = case type
|
78
80
|
when 'boolean'
|
79
81
|
NaranyaEcm::Rest::Model::BOOLEAN
|
@@ -88,12 +90,14 @@ module NaranyaEcm::Rest
|
|
88
90
|
end
|
89
91
|
|
90
92
|
def initialize_with_defaults(*args)
|
93
|
+
init_internals
|
94
|
+
|
91
95
|
initialize_without_defaults(*args)
|
92
96
|
# inicializar con los valores default los campos que esten nulos y tengan un default definido:
|
93
97
|
self.class.fields.values
|
94
98
|
.select { |f| instance_variable_get("@#{f[:name]}".to_sym).nil? && f[:default] }
|
95
99
|
.each { |f| instance_variable_set("@#{f[:name]}".to_sym, f[:default].call) }
|
96
|
-
|
100
|
+
|
97
101
|
end
|
98
102
|
|
99
103
|
def method_missing(method, *args, &block)
|
@@ -108,10 +112,42 @@ module NaranyaEcm::Rest
|
|
108
112
|
end
|
109
113
|
|
110
114
|
def attributes
|
111
|
-
|
112
|
-
self.
|
113
|
-
|
114
|
-
|
115
|
+
self.class.fields.values.inject('id' => self.id) do |hsh, attr_data|
|
116
|
+
hsh[attr_data[:name].to_s] = self.public_send attr_data[:name]
|
117
|
+
hsh
|
118
|
+
end.with_indifferent_access
|
119
|
+
end
|
120
|
+
|
121
|
+
# Returns an <tt>#inspect</tt>-like string for the value of the
|
122
|
+
# attribute +attr_name+. String attributes are truncated upto 50
|
123
|
+
# characters, Date and Time attributes are returned in the
|
124
|
+
# <tt>:db</tt> format, Array attributes are truncated upto 10 values.
|
125
|
+
# Other attributes return the value of <tt>#inspect</tt> without
|
126
|
+
# modification.
|
127
|
+
#
|
128
|
+
# person = Person.create!(name: 'David Heinemeier Hansson ' * 3)
|
129
|
+
#
|
130
|
+
# person.attribute_for_inspect(:name)
|
131
|
+
# # => "\"David Heinemeier Hansson David Heinemeier Hansson ...\""
|
132
|
+
#
|
133
|
+
# person.attribute_for_inspect(:created_at)
|
134
|
+
# # => "\"2012-10-22 00:15:07\""
|
135
|
+
#
|
136
|
+
# person.attribute_for_inspect(:tag_ids)
|
137
|
+
# # => "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...]"
|
138
|
+
def attribute_for_inspect(attr_name)
|
139
|
+
value = self.public_send(attr_name)
|
140
|
+
|
141
|
+
if value.is_a?(String) && value.length > 50
|
142
|
+
"#{value[0, 50]}...".inspect
|
143
|
+
elsif value.is_a?(Date) || value.is_a?(Time)
|
144
|
+
%("#{value.to_s(:db)}")
|
145
|
+
elsif value.is_a?(Array) && value.size > 10
|
146
|
+
inspected = value.first(10).inspect
|
147
|
+
%(#{inspected[0...-1]}, ...])
|
148
|
+
else
|
149
|
+
value.inspect
|
150
|
+
end
|
115
151
|
end
|
116
152
|
|
117
153
|
def associations
|
@@ -131,12 +167,19 @@ module NaranyaEcm::Rest
|
|
131
167
|
"#{self.class.path}/#{self.id}"
|
132
168
|
end
|
133
169
|
|
134
|
-
|
170
|
+
# Returns the contents of the record as a nicely formatted string.
|
171
|
+
def inspect
|
172
|
+
# We check defined?(@attributes) not to issue warnings if the object is
|
173
|
+
# allocated but not initialized.
|
174
|
+
inspection = (['id'] + self.class.fields.keys.sort).map { |name|
|
175
|
+
value = attribute_for_inspect(name)
|
176
|
+
"#{name}: #{value}" unless value == 'nil'
|
177
|
+
}.compact.join(", ")
|
135
178
|
|
136
|
-
|
137
|
-
@off_band_changes ||= {}.with_indifferent_access
|
138
|
-
end
|
179
|
+
inspection = "not initialized" if inspection.blank?
|
139
180
|
|
181
|
+
"#<#{self.class} #{inspection}>"
|
182
|
+
end
|
140
183
|
|
141
184
|
module ClassMethods
|
142
185
|
|
@@ -157,14 +200,14 @@ module NaranyaEcm::Rest
|
|
157
200
|
end
|
158
201
|
|
159
202
|
def field(name, options = {})
|
160
|
-
|
203
|
+
|
161
204
|
if options[:localize]
|
162
205
|
lookup_alias_name = name
|
163
206
|
name = "#{name}_translations".to_sym
|
164
207
|
end
|
165
208
|
|
166
209
|
fields[name] = {name: name}.merge(options).with_indifferent_access
|
167
|
-
|
210
|
+
|
168
211
|
attr_accessor name
|
169
212
|
define_attribute_method name
|
170
213
|
|
@@ -201,7 +244,7 @@ module NaranyaEcm::Rest
|
|
201
244
|
end
|
202
245
|
|
203
246
|
def where(given_conditions={})
|
204
|
-
Relation.new self, given_conditions.with_indifferent_access
|
247
|
+
Relation.new self, given_conditions.with_indifferent_access
|
205
248
|
end
|
206
249
|
|
207
250
|
delegate :first, :last, to: :all
|
@@ -209,7 +252,32 @@ module NaranyaEcm::Rest
|
|
209
252
|
def all
|
210
253
|
where()
|
211
254
|
end
|
212
|
-
|
255
|
+
|
256
|
+
end
|
257
|
+
|
258
|
+
# Returns +true+ if the resource is read only.
|
259
|
+
def readonly?
|
260
|
+
@readonly
|
213
261
|
end
|
262
|
+
|
263
|
+
# Marks this record as read only.
|
264
|
+
def readonly!
|
265
|
+
@readonly = true
|
266
|
+
end
|
267
|
+
|
268
|
+
protected
|
269
|
+
|
270
|
+
def off_band_changes
|
271
|
+
@off_band_changes ||= {}.with_indifferent_access
|
272
|
+
end
|
273
|
+
|
274
|
+
private
|
275
|
+
|
276
|
+
def init_internals
|
277
|
+
@readonly = false
|
278
|
+
@destroyed = false
|
279
|
+
@new_resource = true
|
280
|
+
end
|
281
|
+
|
214
282
|
end
|
215
|
-
end
|
283
|
+
end
|
@@ -1,9 +1,67 @@
|
|
1
1
|
module NaranyaEcm::Rest
|
2
2
|
|
3
3
|
module Persistence
|
4
|
-
|
5
4
|
extend ActiveSupport::Concern
|
6
5
|
|
6
|
+
class ReadOnlyResource < StandardError
|
7
|
+
end
|
8
|
+
|
9
|
+
class ResourceNotSaved < StandardError
|
10
|
+
end
|
11
|
+
|
12
|
+
class ResourceNotDestroyed < StandardError
|
13
|
+
end
|
14
|
+
|
15
|
+
module ClassMethods
|
16
|
+
|
17
|
+
# Updates an object (or multiple objects) and saves it to the server, if
|
18
|
+
# validations pass.
|
19
|
+
#
|
20
|
+
# The resulting object is returned whether the object was saved
|
21
|
+
# successfully to the server or not.
|
22
|
+
#
|
23
|
+
# ==== Parameters
|
24
|
+
#
|
25
|
+
# * +id+ - This should be the id or an array of ids to be updated.
|
26
|
+
# * +attributes+ - This should be a hash of attributes or an array of hashes.
|
27
|
+
#
|
28
|
+
# ==== Examples
|
29
|
+
#
|
30
|
+
# # Updates one resource
|
31
|
+
# Person.update(15, user_name: 'Samuel', group: 'expert')
|
32
|
+
#
|
33
|
+
# # Updates multiple resources
|
34
|
+
# people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy" } }
|
35
|
+
# Person.update(people.keys, people.values)
|
36
|
+
def update(id, attributes)
|
37
|
+
if id.is_a?(Array)
|
38
|
+
id.map.with_index { |one_id, idx| update(one_id, attributes[idx]) }
|
39
|
+
else
|
40
|
+
object = find(id)
|
41
|
+
object.update(attributes)
|
42
|
+
object
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def create(attributes={})
|
47
|
+
object_to_create = self.new attributes
|
48
|
+
object_to_create.save
|
49
|
+
object_to_create
|
50
|
+
end
|
51
|
+
|
52
|
+
def create!(attributes={})
|
53
|
+
created_object = create(attributes)
|
54
|
+
raise "ValidationError" unless created_object.persisted?
|
55
|
+
created_object
|
56
|
+
end
|
57
|
+
|
58
|
+
def delete(id, options={})
|
59
|
+
response = NContent::SDK::RESTClient.delete("#{self.path}/#{id}.json")
|
60
|
+
true
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
7
65
|
included do
|
8
66
|
define_model_callbacks :validation, :create, :update, :save, :destroy
|
9
67
|
end
|
@@ -13,18 +71,98 @@ module NaranyaEcm::Rest
|
|
13
71
|
self.update
|
14
72
|
end
|
15
73
|
|
16
|
-
|
74
|
+
# Returns true if this object hasn't been saved yet -- that is, a resource
|
75
|
+
# for the object doesn't exist at the server yet; otherwise, returns false.
|
76
|
+
def new_resource?
|
77
|
+
@new_resource
|
78
|
+
end
|
79
|
+
|
80
|
+
alias_method :new?, :new_resource?
|
81
|
+
alias_method :new_record?, :new_resource?
|
82
|
+
|
83
|
+
# Returns true if this object has been destroyed, otherwise returns false.
|
84
|
+
def destroyed?
|
85
|
+
@destroyed
|
86
|
+
end
|
87
|
+
|
88
|
+
# Returns true if the resource is persisted, i.e. it's not a new resource
|
89
|
+
# and it was not destroyed, otherwise returns false.
|
90
|
+
def persisted?
|
91
|
+
!(new_resource? || destroyed?)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Saves the resource at the server.
|
95
|
+
#
|
96
|
+
# If the model is new a resource gets created at the server, otherwise
|
97
|
+
# the existing resource gets updated.
|
98
|
+
#
|
99
|
+
# By default, save always run validations. If any of them fail the action
|
100
|
+
# is cancelled and +save+ returns +false+. However, if you supply
|
101
|
+
# validate: false, validations are bypassed altogether. See
|
102
|
+
# ActiveModel::Validations for more information.
|
103
|
+
#
|
104
|
+
# There's a series of callbacks associated with +save+. If any of the
|
105
|
+
# <tt>before_*</tt> callbacks return +false+ the action is cancelled and
|
106
|
+
# +save+ returns +false+. See ActiveModel::Callbacks for further
|
107
|
+
# details.
|
108
|
+
#
|
109
|
+
# Attributes marked as readonly are silently ignored if the resource is
|
110
|
+
# being updated.
|
111
|
+
def save(*)
|
17
112
|
run_callbacks :save do
|
18
113
|
@previously_changed = changes
|
19
|
-
result =
|
114
|
+
result = create_or_update
|
20
115
|
@changed_attributes.clear
|
21
116
|
result
|
22
117
|
end
|
23
118
|
end
|
24
119
|
|
120
|
+
# Saves the model.
|
121
|
+
#
|
122
|
+
# If the model is new a resource gets created at the server, otherwise
|
123
|
+
# the existing resource gets updated.
|
124
|
+
#
|
125
|
+
# With <tt>save!</tt> validations always run. If any of them fail
|
126
|
+
# ActiveModel::resourceInvalid gets raised. See ActiveModel::Validations
|
127
|
+
# for more information.
|
128
|
+
#
|
129
|
+
# There's a series of callbacks associated with <tt>save!</tt>. If any of
|
130
|
+
# the <tt>before_*</tt> callbacks return +false+ the action is cancelled
|
131
|
+
# and <tt>save!</tt> raises ActiveModel::resourceNotSaved. See
|
132
|
+
# ActiveModel::Callbacks for further details.
|
133
|
+
#
|
134
|
+
# Attributes marked as readonly are silently ignored if the resource is
|
135
|
+
# being updated.
|
136
|
+
def save!(*)
|
137
|
+
create_or_update || raise(resourceNotSaved.new(nil, self))
|
138
|
+
end
|
139
|
+
|
140
|
+
# Deletes the resource at the server and freezes this instance to
|
141
|
+
# reflect that no changes should be made (since they can't be
|
142
|
+
# persisted). Returns the frozen instance.
|
143
|
+
#
|
144
|
+
# The row is simply removed with an SQL +DELETE+ statement on the
|
145
|
+
# resource's primary key, and no callbacks are executed.
|
146
|
+
#
|
147
|
+
# To enforce the object's +before_destroy+ and +after_destroy+
|
148
|
+
# callbacks or any <tt>:dependent</tt> association
|
149
|
+
# options, use <tt>#destroy</tt>.
|
150
|
+
def delete
|
151
|
+
self.class.delete(id) if persisted?
|
152
|
+
@destroyed = true
|
153
|
+
freeze
|
154
|
+
end
|
155
|
+
|
156
|
+
# Deletes the resource at the server and freezes this instance to reflect
|
157
|
+
# that no changes should be made (since they can't be persisted).
|
158
|
+
#
|
159
|
+
# There's a series of callbacks associated with <tt>destroy</tt>. If
|
160
|
+
# the <tt>before_destroy</tt> callback return +false+ the action is cancelled
|
161
|
+
# and <tt>destroy</tt> returns +false+. See
|
162
|
+
# Activeresource::Callbacks for further details.
|
25
163
|
def destroy
|
26
164
|
run_callbacks :destroy do
|
27
|
-
#raise
|
165
|
+
#raise ReadOnlyresource if readonly?
|
28
166
|
#destroy_associations
|
29
167
|
self.class.delete(self.id) if persisted?
|
30
168
|
@destroyed = true
|
@@ -32,14 +170,74 @@ module NaranyaEcm::Rest
|
|
32
170
|
end
|
33
171
|
end
|
34
172
|
|
35
|
-
|
36
|
-
|
37
|
-
|
173
|
+
# Deletes the resource at the server and freezes this instance to reflect
|
174
|
+
# that no changes should be made (since they can't be persisted).
|
175
|
+
#
|
176
|
+
# There's a series of callbacks associated with <tt>destroy!</tt>. If
|
177
|
+
# the <tt>before_destroy</tt> callback return +false+ the action is cancelled
|
178
|
+
# and <tt>destroy!</tt> raises Activeresource::resourceNotDestroyed. See
|
179
|
+
# Activeresource::Callbacks for further details.
|
180
|
+
def destroy!
|
181
|
+
destroy || raise(ResourceNotDestroyed, self)
|
182
|
+
end
|
183
|
+
|
184
|
+
# Updates a single attribute and saves the resource.
|
185
|
+
# This is especially useful for boolean flags on existing resources.
|
186
|
+
# Also note that
|
187
|
+
#
|
188
|
+
# * Validation is skipped.
|
189
|
+
# * Callbacks are invoked.
|
190
|
+
# * updated_at/updated_on attribute is updated if that attribute is available.
|
191
|
+
# * Updates all the attributes that are dirty in this object.
|
192
|
+
#
|
193
|
+
# This method raises an +Activeresource::ActiveresourceError+ if the
|
194
|
+
# attribute is marked as readonly.
|
195
|
+
#
|
196
|
+
# See also +update_column+.
|
197
|
+
def update_attribute(name, value)
|
198
|
+
name = name.to_s
|
199
|
+
#verify_readonly_attribute(name)
|
200
|
+
send("#{name}=", value)
|
201
|
+
save(validate: false)
|
202
|
+
end
|
203
|
+
|
204
|
+
# Updates the attributes of the model from the passed-in hash and saves the
|
205
|
+
# resource, all wrapped in a transaction. If the object is invalid, the
|
206
|
+
# saving will fail and false will be returned.
|
207
|
+
def update(attributes)
|
208
|
+
assign_attributes(attributes)
|
209
|
+
save
|
210
|
+
end
|
211
|
+
|
212
|
+
def assign_attributes(given_attributes)
|
213
|
+
given_attributes.each do |key, val|
|
214
|
+
self.public_send "#{key}=", val
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
alias update_attributes update
|
38
219
|
|
39
|
-
|
220
|
+
# Updates its receiver just like +update+ but calls <tt>save!</tt> instead
|
221
|
+
# of +save+, so an exception is raised if the resource is invalid.
|
222
|
+
def update!(attributes)
|
223
|
+
# The following transaction covers any possible server side-effects of the
|
224
|
+
# attributes assignment. For example, setting the IDs of a child collection.
|
225
|
+
with_transaction_returning_status do
|
226
|
+
assign_attributes(attributes)
|
227
|
+
save!
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
alias update_attributes! update!
|
40
232
|
|
41
233
|
protected
|
42
234
|
|
235
|
+
def create_or_update
|
236
|
+
raise ReadOnlyResource, "#{self.class} is marked as readonly" if readonly?
|
237
|
+
result = new_resource? ? _create_resource : _update_resource
|
238
|
+
result != false
|
239
|
+
end
|
240
|
+
|
43
241
|
def load_server_errors(server_error_hash)
|
44
242
|
server_error_hash = server_error_hash.with_indifferent_access
|
45
243
|
if server_error_hash.present? && server_error_hash.has_key?(:errors) && server_error_hash[:errors].present?
|
@@ -54,10 +252,10 @@ module NaranyaEcm::Rest
|
|
54
252
|
end
|
55
253
|
|
56
254
|
def reload
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
255
|
+
response = NContent::SDK::RESTClient.get "#{path}.json"
|
256
|
+
|
257
|
+
load(response.body)
|
258
|
+
@new_resource = false
|
61
259
|
true
|
62
260
|
end
|
63
261
|
|
@@ -70,24 +268,31 @@ module NaranyaEcm::Rest
|
|
70
268
|
}
|
71
269
|
end
|
72
270
|
|
73
|
-
def
|
271
|
+
def _create_resource
|
74
272
|
run_callbacks :create do
|
75
273
|
|
76
|
-
|
77
|
-
create_path = "#{self.class.path}.#{format}"
|
274
|
+
create_path = "#{self.class.path}.json"
|
78
275
|
|
79
276
|
begin
|
80
|
-
|
81
|
-
|
277
|
+
|
278
|
+
response = NContent::SDK::RESTClient.post create_path do |req|
|
279
|
+
req.headers[:content_type] = 'application/json'
|
280
|
+
req.body = ActiveSupport::JSON.encode(
|
281
|
+
self.class.name.demodulize.underscore => attributes
|
282
|
+
)
|
283
|
+
end
|
284
|
+
|
285
|
+
self.load(response.body)
|
286
|
+
@new_resource = false
|
82
287
|
true
|
83
288
|
rescue UnprocessableEntity => e
|
84
|
-
self.load_server_errors(e.response.
|
289
|
+
self.load_server_errors(e.response.body)
|
85
290
|
false
|
86
291
|
end
|
87
292
|
end
|
88
293
|
end
|
89
294
|
|
90
|
-
def
|
295
|
+
def _update_resource
|
91
296
|
run_callbacks :update do
|
92
297
|
|
93
298
|
unless @is_touch
|
@@ -101,43 +306,26 @@ module NaranyaEcm::Rest
|
|
101
306
|
|
102
307
|
attributes_to_save.merge! off_band_changes
|
103
308
|
|
104
|
-
|
105
|
-
update_path = "#{self.path}.#{format}"
|
309
|
+
update_path = "#{self.path}.json"
|
106
310
|
|
107
311
|
begin
|
108
|
-
response =
|
312
|
+
response = NContent::SDK::RESTClient.put update_path do |req|
|
313
|
+
req.headers[:content_type] = 'application/json'
|
314
|
+
req.body = ActiveSupport::JSON.encode(
|
315
|
+
self.class.name.demodulize.underscore => attributes_to_save
|
316
|
+
)
|
317
|
+
end
|
318
|
+
|
109
319
|
self.reload!
|
110
320
|
off_band_changes.clear if off_band_changes.present?
|
111
321
|
true
|
112
322
|
rescue UnprocessableEntity
|
113
|
-
self.load_server_errors(response.
|
323
|
+
self.load_server_errors(response.body)
|
114
324
|
false
|
115
325
|
end
|
116
326
|
end
|
117
327
|
end
|
118
328
|
|
119
|
-
|
120
|
-
module ClassMethods
|
121
|
-
|
122
|
-
def create(attributes={})
|
123
|
-
object_to_create = self.new attributes
|
124
|
-
object_to_create.save
|
125
|
-
object_to_create
|
126
|
-
end
|
127
|
-
|
128
|
-
def create!(attributes={})
|
129
|
-
created_object = create(attributes)
|
130
|
-
raise "ValidationError" unless created_object.persisted?
|
131
|
-
created_object
|
132
|
-
end
|
133
|
-
|
134
|
-
def delete(id, options={})
|
135
|
-
response = Client.delete("#{self.path}/#{id}.json")
|
136
|
-
true
|
137
|
-
end
|
138
|
-
|
139
|
-
end
|
140
|
-
|
141
329
|
end
|
142
330
|
|
143
|
-
end
|
331
|
+
end
|