sequencescape-client-api 0.3.7 → 0.4.0.pre.rc2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.rubocop.yml +44 -0
- data/.rubocop_todo.yml +338 -0
- data/.ruby-version +1 -0
- data/Gemfile +1 -1
- data/README.markdown +13 -0
- data/lib/sequencescape-api.rb +1 -1
- data/lib/sequencescape-api/actions.rb +9 -8
- data/lib/sequencescape-api/associations.rb +8 -6
- data/lib/sequencescape-api/associations/base.rb +1 -1
- data/lib/sequencescape-api/associations/base/instance_methods.rb +10 -8
- data/lib/sequencescape-api/associations/belongs_to.rb +4 -4
- data/lib/sequencescape-api/associations/has_many.rb +14 -13
- data/lib/sequencescape-api/associations/has_many/json.rb +1 -1
- data/lib/sequencescape-api/associations/has_many/validation.rb +1 -1
- data/lib/sequencescape-api/composition.rb +11 -7
- data/lib/sequencescape-api/connection_factory.rb +6 -5
- data/lib/sequencescape-api/connection_factory/actions.rb +17 -12
- data/lib/sequencescape-api/core.rb +12 -7
- data/lib/sequencescape-api/core_ext/array.rb +1 -1
- data/lib/sequencescape-api/core_ext/hash.rb +3 -3
- data/lib/sequencescape-api/errors.rb +2 -2
- data/lib/sequencescape-api/finder_methods.rb +16 -11
- data/lib/sequencescape-api/rails.rb +8 -7
- data/lib/sequencescape-api/resource/active_model.rb +1 -1
- data/lib/sequencescape-api/resource/attribute_groups.rb +11 -7
- data/lib/sequencescape-api/resource/attributes.rb +8 -8
- data/lib/sequencescape-api/resource/instance_methods.rb +17 -9
- data/lib/sequencescape-api/resource/json.rb +18 -15
- data/lib/sequencescape-api/resource/modifications.rb +20 -11
- data/lib/sequencescape-api/resource_model_proxy.rb +7 -5
- data/lib/sequencescape-api/version.rb +1 -1
- data/lib/sequencescape.rb +4 -2
- data/lib/sequencescape/bait_library.rb +1 -1
- data/lib/sequencescape/bait_library_layout.rb +2 -2
- data/lib/sequencescape/barcoded_asset.rb +1 -1
- data/lib/sequencescape/batch.rb +6 -6
- data/lib/sequencescape/behaviour/qced.rb +3 -4
- data/lib/sequencescape/behaviour/receptacle.rb +3 -3
- data/lib/sequencescape/behaviour/state_driven.rb +4 -4
- data/lib/sequencescape/bulk_transfer.rb +1 -1
- data/lib/sequencescape/comment.rb +0 -2
- data/lib/sequencescape/extraction_attribute.rb +6 -0
- data/lib/sequencescape/library_event.rb +1 -1
- data/lib/sequencescape/library_tube.rb +1 -1
- data/lib/sequencescape/lot.rb +0 -1
- data/lib/sequencescape/lot_type.rb +1 -2
- data/lib/sequencescape/order_template.rb +1 -2
- data/lib/sequencescape/pipeline.rb +1 -1
- data/lib/sequencescape/plate.rb +29 -11
- data/lib/sequencescape/plate/pooling.rb +9 -3
- data/lib/sequencescape/plate/well_structure.rb +6 -6
- data/lib/sequencescape/plate_conversion.rb +3 -3
- data/lib/sequencescape/plate_creation.rb +3 -3
- data/lib/sequencescape/plate_purpose.rb +3 -3
- data/lib/sequencescape/plate_template.rb +0 -2
- data/lib/sequencescape/pooled_plate_creation.rb +3 -3
- data/lib/sequencescape/project.rb +2 -1
- data/lib/sequencescape/qc_decision.rb +0 -1
- data/lib/sequencescape/qc_file.rb +0 -3
- data/lib/sequencescape/qcable.rb +0 -3
- data/lib/sequencescape/qcable_creator.rb +1 -4
- data/lib/sequencescape/request.rb +3 -3
- data/lib/sequencescape/search.rb +10 -8
- data/lib/sequencescape/specific_tube_creation.rb +2 -2
- data/lib/sequencescape/stamp.rb +0 -1
- data/lib/sequencescape/state_change.rb +2 -2
- data/lib/sequencescape/study.rb +1 -1
- data/lib/sequencescape/submission.rb +1 -2
- data/lib/sequencescape/tag2_layout.rb +3 -3
- data/lib/sequencescape/tag2_layout_template.rb +2 -2
- data/lib/sequencescape/tag_group.rb +0 -1
- data/lib/sequencescape/tag_layout.rb +3 -3
- data/lib/sequencescape/tag_layout_template.rb +4 -4
- data/lib/sequencescape/transfer.rb +2 -2
- data/lib/sequencescape/transfer_request.rb +5 -7
- data/lib/sequencescape/transfer_template.rb +2 -2
- data/lib/sequencescape/tube.rb +3 -3
- data/lib/sequencescape/tube_creation.rb +3 -3
- data/lib/sequencescape/tube_from_tube_creation.rb +3 -3
- data/lib/sequencescape/tube_purpose.rb +3 -3
- data/lib/sequencescape/user.rb +2 -2
- data/lib/sequencescape/volume_update.rb +1 -1
- data/lib/sequencescape/well.rb +0 -2
- data/lib/sequencescape/work_completion.rb +1 -1
- data/sequencescape-api.gemspec +18 -17
- data/spec/sequencescape-api/associations_spec.rb +4 -2
- data/spec/sequencescape-api/finding_methods_spec.rb +3 -1
- data/spec/sequencescape-api/modifications_spec.rb +17 -16
- data/spec/sequencescape-api/root_spec.rb +11 -6
- data/spec/spec_helper.rb +3 -1
- data/spec/support/contract_helper.rb +18 -10
- data/spec/support/namespaces.rb +9 -9
- data/spec/support/shared_examples.rb +2 -0
- metadata +54 -36
- data/.rvmrc +0 -52
@@ -8,7 +8,7 @@ module Sequencescape
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
-
[
|
11
|
+
%i[UnauthenticatedError ResourceNotFound].each do |name|
|
12
12
|
const_set(name, Class.new(Error) { |c| c.send(:include, GeneralError) })
|
13
13
|
end
|
14
14
|
|
@@ -30,7 +30,7 @@ module Sequencescape
|
|
30
30
|
raise Sequencescape::Api::ResourceNotFound, json
|
31
31
|
end
|
32
32
|
|
33
|
-
def redirection(
|
33
|
+
def redirection(_json)
|
34
34
|
yield(self)
|
35
35
|
end
|
36
36
|
end
|
@@ -3,7 +3,7 @@ require 'ostruct'
|
|
3
3
|
module Sequencescape::Api::FinderMethods
|
4
4
|
module Delegation
|
5
5
|
def self.included(base)
|
6
|
-
base.with_options(:
|
6
|
+
base.with_options(to: :all) do |all|
|
7
7
|
all.delegate :each, :first, :last, :to_a, :size
|
8
8
|
all.delegate :empty?, :blank?
|
9
9
|
all.delegate :each_page, :first_page, :last_page
|
@@ -74,7 +74,7 @@ end
|
|
74
74
|
|
75
75
|
module Sequencescape::Api::FinderMethods::Caching
|
76
76
|
def all(reload = false)
|
77
|
-
@cached_all = super() if @cached_all.nil?
|
77
|
+
@cached_all = super() if @cached_all.nil? || reload
|
78
78
|
@cached_all
|
79
79
|
end
|
80
80
|
end
|
@@ -88,7 +88,8 @@ class Sequencescape::Api::PageOfResults
|
|
88
88
|
attr_reader :size
|
89
89
|
|
90
90
|
def initialize(api, json, &block)
|
91
|
-
@api
|
91
|
+
@api = api
|
92
|
+
@ctor = block
|
92
93
|
update_from_json(json)
|
93
94
|
end
|
94
95
|
|
@@ -109,7 +110,7 @@ class Sequencescape::Api::PageOfResults
|
|
109
110
|
end
|
110
111
|
end
|
111
112
|
|
112
|
-
def each_page
|
113
|
+
def each_page
|
113
114
|
walk_pages do
|
114
115
|
yield(@objects.dup)
|
115
116
|
end
|
@@ -127,9 +128,10 @@ class Sequencescape::Api::PageOfResults
|
|
127
128
|
|
128
129
|
def walk_pages
|
129
130
|
first_page
|
130
|
-
|
131
|
+
loop do
|
131
132
|
yield
|
132
133
|
break if actions.next.blank?
|
134
|
+
|
133
135
|
next_page
|
134
136
|
end
|
135
137
|
end
|
@@ -153,32 +155,35 @@ class Sequencescape::Api::PageOfResults
|
|
153
155
|
end
|
154
156
|
end
|
155
157
|
|
156
|
-
[
|
158
|
+
%i[first last previous next].each do |page|
|
157
159
|
line = __LINE__ + 1
|
158
|
-
class_eval(
|
160
|
+
class_eval("
|
159
161
|
def #{page}_page
|
160
162
|
self.tap do
|
161
163
|
api.read(actions.#{page}, UpdateHandler.new(self)) unless actions.read == actions.#{page}
|
162
164
|
yield(@objects.dup) if block_given?
|
163
165
|
end
|
164
166
|
end
|
165
|
-
|
167
|
+
", __FILE__, line)
|
166
168
|
end
|
167
169
|
private :last_page, :next_page
|
168
170
|
|
169
|
-
def update_from_json(json)
|
170
|
-
json.delete('uuids_to_ids')
|
171
|
+
def update_from_json(json) # rubocop:todo Metrics/MethodLength
|
172
|
+
json.delete('uuids_to_ids') # Discard unwanted rubbish
|
171
173
|
actions = json.delete('actions')
|
172
174
|
raise Sequencescape::Api::Error, 'No actions for page!' if actions.blank?
|
173
175
|
|
174
176
|
if api.capabilities.size_in_pages?
|
175
177
|
size = json.delete('size')
|
176
178
|
raise Sequencescape::Api::Error, 'No size for page!' if size.blank?
|
179
|
+
|
177
180
|
@size = size.to_i
|
178
181
|
end
|
179
182
|
|
180
183
|
raise Sequencescape::Api::Error, 'No object json in page!' if json.keys.empty?
|
181
|
-
|
184
|
+
|
185
|
+
@actions = OpenStruct.new(actions)
|
186
|
+
@objects = json[json.keys.first].map(&@ctor)
|
182
187
|
end
|
183
188
|
private :update_from_json
|
184
189
|
end
|
@@ -3,7 +3,7 @@ module Sequencescape::Api::Rails
|
|
3
3
|
# provide a user (based on the WTSISignOn cookie) specific Sequencescape::Api instance to
|
4
4
|
# use, accessible through `api`.
|
5
5
|
module ApplicationController
|
6
|
-
def self.included(base)
|
6
|
+
def self.included(base) # rubocop:todo Metrics/MethodLength
|
7
7
|
base.class_eval do
|
8
8
|
attr_reader :api
|
9
9
|
private :api
|
@@ -15,8 +15,8 @@ module Sequencescape::Api::Rails
|
|
15
15
|
end
|
16
16
|
|
17
17
|
# Order is important here: later ones override earlier.
|
18
|
-
rescue_from(::Sequencescape::Api::Error, :
|
19
|
-
rescue_from(::Sequencescape::Api::UnauthenticatedError, :
|
18
|
+
rescue_from(::Sequencescape::Api::Error, with: :sequencescape_api_error_handler)
|
19
|
+
rescue_from(::Sequencescape::Api::UnauthenticatedError, with: :sequencescape_api_unauthenticated_handler)
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
@@ -26,12 +26,12 @@ module Sequencescape::Api::Rails
|
|
26
26
|
private :api_class
|
27
27
|
|
28
28
|
def configure_api
|
29
|
-
@api = api_class.new({ :
|
29
|
+
@api = api_class.new({ cookie: cookies['WTSISignOn'] }.merge(api_connection_options))
|
30
30
|
end
|
31
31
|
private :configure_api
|
32
32
|
|
33
33
|
def api_connection_options
|
34
|
-
{
|
34
|
+
{}
|
35
35
|
end
|
36
36
|
private :api_connection_options
|
37
37
|
|
@@ -43,7 +43,7 @@ module Sequencescape::Api::Rails
|
|
43
43
|
|
44
44
|
def sequencescape_api_unauthenticated_handler(exception)
|
45
45
|
Rails.logger.error "#{exception}, #{exception.backtrace}"
|
46
|
-
raise StandardError,
|
46
|
+
raise StandardError, 'You are not authenticated; please visit the WTSI login page'
|
47
47
|
end
|
48
48
|
private :sequencescape_api_unauthenticated_handler
|
49
49
|
end
|
@@ -57,7 +57,7 @@ module Sequencescape::Api::Rails
|
|
57
57
|
def self.included(base)
|
58
58
|
base.class_eval do
|
59
59
|
attr_protected :remote_resource, :uuid
|
60
|
-
validates_presence_of :uuid, :
|
60
|
+
validates_presence_of :uuid, allow_blank: false
|
61
61
|
before_save :save_remote_resource
|
62
62
|
end
|
63
63
|
end
|
@@ -80,6 +80,7 @@ module Sequencescape::Api::Rails
|
|
80
80
|
def save_remote_resource
|
81
81
|
return true if @remote_resource.nil?
|
82
82
|
return true unless @remote_resource.can_save?
|
83
|
+
|
83
84
|
self[:uuid] = @remote_resource
|
84
85
|
@remote_resource.save
|
85
86
|
end
|
@@ -7,7 +7,7 @@ module Sequencescape::Api::Resource::Groups
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def attribute_group_json(options)
|
10
|
-
attribute_groups.each_with_object({}) do |(k,v), agj|
|
10
|
+
attribute_groups.each_with_object({}) do |(k, v), agj|
|
11
11
|
agj[k.to_s] = v.send(:as_json_for_update, options) if v.changed?
|
12
12
|
end
|
13
13
|
end
|
@@ -28,7 +28,7 @@ module Sequencescape::Api::Resource::Groups
|
|
28
28
|
end
|
29
29
|
|
30
30
|
module Json
|
31
|
-
def as_json_for_update(options)
|
31
|
+
def as_json_for_update(options) # rubocop:todo Metrics/MethodLength
|
32
32
|
super.tap do |json|
|
33
33
|
begin
|
34
34
|
if options[:root]
|
@@ -64,14 +64,18 @@ class Sequencescape::Api::Resource::Groups::Proxy
|
|
64
64
|
module InstanceMethods
|
65
65
|
def self.included(base)
|
66
66
|
base.class_eval do
|
67
|
-
|
68
|
-
|
67
|
+
private
|
68
|
+
|
69
|
+
def attributes
|
70
|
+
@_attributes_
|
71
|
+
end
|
69
72
|
end
|
70
73
|
end
|
71
74
|
|
72
75
|
def initialize(owner, attributes = {})
|
73
|
-
@owner
|
74
|
-
|
76
|
+
@owner = owner
|
77
|
+
@_attributes_ = {}
|
78
|
+
attributes.each { |k, v| send(:"#{k}=", v) if respond_to?(:"#{k}=", :include_private_methods) }
|
75
79
|
end
|
76
80
|
|
77
81
|
def as_json_for_update(options)
|
@@ -82,7 +86,7 @@ class Sequencescape::Api::Resource::Groups::Proxy
|
|
82
86
|
private :as_json_for_update
|
83
87
|
|
84
88
|
def clear_changed_attributes
|
85
|
-
|
89
|
+
clear_changes_information
|
86
90
|
end
|
87
91
|
private :clear_changed_attributes
|
88
92
|
end
|
@@ -5,7 +5,7 @@ module Sequencescape::Api::Resource::Attributes
|
|
5
5
|
def self.extended(base)
|
6
6
|
base.class_eval do
|
7
7
|
include InstanceMethods
|
8
|
-
class_attribute :defined_attributes, :
|
8
|
+
class_attribute :defined_attributes, instance_writer: false
|
9
9
|
self.defined_attributes = Set.new
|
10
10
|
end
|
11
11
|
end
|
@@ -20,16 +20,16 @@ module Sequencescape::Api::Resource::Attributes
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
def generate_attribute_reader(*names)
|
23
|
+
def generate_attribute_reader(*names) # rubocop:todo Metrics/MethodLength
|
24
24
|
options = names.extract_options!
|
25
25
|
conversion = options[:conversion].blank? ? nil : "try(#{options[:conversion].to_sym.inspect})"
|
26
26
|
|
27
27
|
names.each do |name|
|
28
28
|
defined_attributes << name.to_sym
|
29
|
-
converted = [
|
29
|
+
converted = ["#{name}_before_type_cast", conversion].compact.join('.')
|
30
30
|
|
31
31
|
line = __LINE__ + 1
|
32
|
-
class_eval(
|
32
|
+
class_eval("
|
33
33
|
def #{name}
|
34
34
|
#{converted}
|
35
35
|
end
|
@@ -37,25 +37,25 @@ module Sequencescape::Api::Resource::Attributes
|
|
37
37
|
def #{name}_before_type_cast
|
38
38
|
attributes[#{name.to_s.inspect}]
|
39
39
|
end
|
40
|
-
|
40
|
+
", __FILE__, line)
|
41
41
|
end
|
42
42
|
extend_attribute_methods(names)
|
43
43
|
end
|
44
44
|
private :generate_attribute_reader
|
45
45
|
|
46
|
-
def generate_attribute_writer(*names)
|
46
|
+
def generate_attribute_writer(*names) # rubocop:todo Metrics/MethodLength
|
47
47
|
options = names.extract_options!
|
48
48
|
|
49
49
|
names.each do |name|
|
50
50
|
defined_attributes << name.to_sym
|
51
51
|
|
52
52
|
line = __LINE__ + 1
|
53
|
-
class_eval(
|
53
|
+
class_eval("
|
54
54
|
def #{name}=(value)
|
55
55
|
#{name}_will_change! if not attributes.key?(#{name.to_s.inspect}) or #{name} != value
|
56
56
|
attributes[#{name.to_s.inspect}] = value
|
57
57
|
end
|
58
|
-
|
58
|
+
", __FILE__, line)
|
59
59
|
end
|
60
60
|
extend_attribute_methods(names)
|
61
61
|
end
|
@@ -1,24 +1,32 @@
|
|
1
1
|
module Sequencescape::Api::Resource::InstanceMethods
|
2
|
-
def self.included(base)
|
2
|
+
def self.included(base) # rubocop:todo Metrics/MethodLength
|
3
3
|
base.class_eval do
|
4
|
-
attr_reader :api, :actions, :
|
5
|
-
private :api, :actions
|
4
|
+
attr_reader :api, :actions, :uuid
|
5
|
+
private :api, :actions
|
6
6
|
alias_method(:model, :class)
|
7
7
|
alias_method(:id, :uuid)
|
8
8
|
|
9
|
-
delegate :hash, :
|
10
|
-
delegate :read_timeout, :
|
9
|
+
delegate :hash, to: :uuid
|
10
|
+
delegate :read_timeout, to: :api
|
11
11
|
|
12
|
-
attribute_accessor :created_at, :updated_at, :
|
12
|
+
attribute_accessor :created_at, :updated_at, conversion: :to_time
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def attributes
|
17
|
+
@_attributes_
|
18
|
+
end
|
13
19
|
end
|
14
20
|
end
|
15
21
|
|
16
22
|
def eql?(object_or_proxy)
|
17
23
|
return false unless object_or_proxy.respond_to?(:uuid)
|
18
|
-
|
24
|
+
|
25
|
+
uuid.eql?(object_or_proxy.uuid)
|
19
26
|
end
|
20
27
|
|
21
|
-
def initialize(api,
|
22
|
-
@api
|
28
|
+
def initialize(api, _json = nil, _wrapped = false)
|
29
|
+
@api = api
|
30
|
+
@_attributes_ = {}
|
23
31
|
end
|
24
32
|
end
|
@@ -7,11 +7,11 @@ module Sequencescape::Api::Resource::Json
|
|
7
7
|
|
8
8
|
module ClassMethods
|
9
9
|
def self.extended(base)
|
10
|
-
base.delegate :json_root, :
|
10
|
+
base.delegate :json_root, to: 'self.class'
|
11
11
|
end
|
12
12
|
|
13
13
|
def json_root
|
14
|
-
|
14
|
+
name.demodulize.underscore
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
@@ -19,7 +19,8 @@ module Sequencescape::Api::Resource::Json
|
|
19
19
|
include Sequencescape::Api::BasicErrorHandling
|
20
20
|
|
21
21
|
def initialize(api, owner)
|
22
|
-
@api
|
22
|
+
@api = api
|
23
|
+
@owner = owner
|
23
24
|
end
|
24
25
|
|
25
26
|
attr_reader :api
|
@@ -39,11 +40,11 @@ module Sequencescape::Api::Resource::Json
|
|
39
40
|
|
40
41
|
# Coerces the current object instance to another class.
|
41
42
|
def coerce_to(klazz)
|
42
|
-
api.read_uuid(
|
43
|
+
api.read_uuid(uuid, CoercionHandler.new(api, klazz))
|
43
44
|
end
|
44
45
|
|
45
46
|
def as_json(options = nil)
|
46
|
-
options = { :
|
47
|
+
options = { action: :create, root: true }.merge(options || {})
|
47
48
|
send(:"as_json_for_#{options[:action]}", options)
|
48
49
|
end
|
49
50
|
|
@@ -57,28 +58,28 @@ module Sequencescape::Api::Resource::Json
|
|
57
58
|
private :as_json_for_create
|
58
59
|
|
59
60
|
# Returns the appropriate JSON for when we are updating a resource.
|
60
|
-
def as_json_for_update(options)
|
61
|
+
def as_json_for_update(options) # rubocop:todo Metrics/MethodLength
|
61
62
|
if must_output_full_json?(options)
|
62
|
-
json = {
|
63
|
-
json['uuid'] = uuid if options[:uuid]
|
63
|
+
json = {}
|
64
|
+
json['uuid'] = uuid if options[:uuid] && uuid.present?
|
64
65
|
|
65
66
|
json.merge!(attributes_for_json(options))
|
66
|
-
json.merge!(associations_for_json(options.merge(:
|
67
|
+
json.merge!(associations_for_json(options.merge(root: false)))
|
67
68
|
|
68
69
|
return json unless options[:root]
|
70
|
+
|
69
71
|
{ json_root => json }
|
70
72
|
elsif options[:root]
|
71
73
|
# We are the root element so we must output something!
|
72
|
-
{ json_root => {
|
73
|
-
else
|
74
|
-
# We are not a root element, we haven't been changed, so we might as well not exist!
|
74
|
+
{ json_root => {} }
|
75
|
+
else # We are not a root element, we haven't been changed, so we might as well not exist!
|
75
76
|
nil
|
76
77
|
end
|
77
78
|
end
|
78
79
|
private :as_json_for_update
|
79
80
|
|
80
81
|
def unwrapped_json(json)
|
81
|
-
json[(json.keys - [
|
82
|
+
json[(json.keys - ['uuids_to_ids']).first]
|
82
83
|
end
|
83
84
|
private :unwrapped_json
|
84
85
|
|
@@ -88,13 +89,14 @@ module Sequencescape::Api::Resource::Json
|
|
88
89
|
|
89
90
|
def attributes_for_json(options)
|
90
91
|
attributes_to_send_to_server(options).tap do |changed_attributes|
|
91
|
-
[
|
92
|
+
%w[created_at updated_at].map(&changed_attributes.method(:delete))
|
92
93
|
end
|
93
94
|
end
|
94
95
|
private :attributes_for_json
|
95
96
|
|
96
97
|
def attributes_to_send_to_server(options)
|
97
|
-
return attributes if options[:force]
|
98
|
+
return attributes if options[:force] || (options[:action] == :create)
|
99
|
+
|
98
100
|
changes.keys.each_with_object({}) { |k, attributes| attributes[k.to_s] = send(k) }
|
99
101
|
end
|
100
102
|
private :attributes_to_send_to_server
|
@@ -102,6 +104,7 @@ module Sequencescape::Api::Resource::Json
|
|
102
104
|
def associations_for_json(options)
|
103
105
|
associations.each_with_object({}) do |(k, v), associations|
|
104
106
|
next unless must_output_full_json?(options, v)
|
107
|
+
|
105
108
|
associations[k.to_s] = v.as_json(options)
|
106
109
|
end
|
107
110
|
end
|
@@ -38,32 +38,33 @@ module Sequencescape::Api::Resource::Modifications
|
|
38
38
|
def initialize(api, json = nil, wrapped = false)
|
39
39
|
super
|
40
40
|
update_from_json(json, wrapped)
|
41
|
-
|
41
|
+
clear_changes_information
|
42
42
|
end
|
43
43
|
|
44
44
|
def update_attributes!(attributes)
|
45
|
-
|
45
|
+
clear_changes_information
|
46
46
|
update_from_json(attributes, false)
|
47
|
-
modify!(:
|
47
|
+
modify!(action: :update)
|
48
48
|
end
|
49
49
|
alias update! update_attributes!
|
50
50
|
|
51
51
|
def save!(options = nil)
|
52
52
|
action = persisted? ? :update : :create
|
53
|
-
modify!((options || {}).merge({ :
|
53
|
+
modify!((options || {}).merge({ action: action }))
|
54
54
|
end
|
55
55
|
|
56
|
-
|
57
|
-
|
56
|
+
# rubocop:todo Metrics/MethodLength
|
57
|
+
def modify!(options) # rubocop:todo Metrics/CyclomaticComplexity
|
58
|
+
raise Sequencescape::Api::Error, 'No actions exist' if options[:url].nil? && actions.nil?
|
58
59
|
|
59
60
|
action = options[:action]
|
60
|
-
skip_json = options[:skip_json]||false
|
61
|
+
skip_json = options[:skip_json] || false
|
61
62
|
http_verb = options[:http_verb] || options[:action]
|
62
63
|
url = options[:url]
|
63
64
|
url ||= (actions.send(action) or raise Sequencescape::Api::Error, "Cannot perform #{action}")
|
64
|
-
raise Sequencescape::Api::Error,
|
65
|
+
raise Sequencescape::Api::Error, 'Cannot perform modification without a URL' if url.blank?
|
65
66
|
|
66
|
-
|
67
|
+
tap do
|
67
68
|
run_validations! or raise Sequencescape::Api::ResourceInvalid, self
|
68
69
|
|
69
70
|
object = skip_json ? {} : self
|
@@ -75,9 +76,10 @@ module Sequencescape::Api::Resource::Modifications
|
|
75
76
|
Sequencescape::Api::ModifyingHandler.new(self)
|
76
77
|
)
|
77
78
|
|
78
|
-
|
79
|
+
clear_changes_information
|
79
80
|
end
|
80
81
|
end
|
82
|
+
# rubocop:enable Metrics/MethodLength
|
81
83
|
private :modify!
|
82
84
|
|
83
85
|
def update_from_json(json, wrapped = false)
|
@@ -92,7 +94,8 @@ module Sequencescape::Api::Resource::Modifications
|
|
92
94
|
when name.to_s == 'actions' then update_actions(value)
|
93
95
|
when name.to_s == 'uuid' then @uuid = (value || @uuid)
|
94
96
|
when respond_to?(:"#{name}=", :include_private) then send(:"#{name}=", value)
|
95
|
-
else
|
97
|
+
else
|
98
|
+
debug_log("Unrecognized attribute #{name}")
|
96
99
|
end
|
97
100
|
end
|
98
101
|
private :update_attribute
|
@@ -108,4 +111,10 @@ module Sequencescape::Api::Resource::Modifications
|
|
108
111
|
@actions = actions_from_attributes.nil? ? actions_before_update : OpenStruct.new(actions_from_attributes)
|
109
112
|
end
|
110
113
|
private :update_actions
|
114
|
+
|
115
|
+
private
|
116
|
+
|
117
|
+
def debug_log(message)
|
118
|
+
Rails.logger.debug(message) if defined?(Rails)
|
119
|
+
end
|
111
120
|
end
|