sequencescape-client-api 0.3.10 → 0.4.0.pre.rc1
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/.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 +1 -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 +1 -1
- 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 +19 -15
- 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 +0 -3
- 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 +4 -5
- 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 +53 -35
- 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.loggger.debug(message) if defined?(Rails)
|
|
119
|
+
end
|
|
111
120
|
end
|