Class: Api::Base
- Inherits:
-
Object
- Object
- Api::Base
- Defined in:
- app/models/api/base.rb
Overview
Originally the warehouse was built nightly by calls the the v0.5 API. When the warehouse was switched to a queue based system the same JSON exposed via the API was used to form the message payload.
Base class for API v0.5, now used for Warehouse message rendering, the actual api is no longer exposed.
Direct Known Subclasses
AliquotIo, AssetLinkIo, BatchIo, BatchRequestIo, LaneIo, LibraryTubeIo, Messages::BarcodeIo, Messages::FlowcellIo, Messages::FluidigmPlateIo, Messages::PacBioRunIo, Messages::PacBioRunWithTag2Io, Messages::QcResultIo, Messages::TubeStockResourceIo, Messages::WellStockResourceIo, MultiplexedLibraryTubeIo, OrderIo, PacBioLibraryTubeIo, PlateIo, PlatePurposeIo, ProjectIo, PulldownMultiplexedLibraryTubeIo, ReferenceGenomeIo, RequestIo, SampleIo, SampleTubeIo, StudyIo, StudySampleIo, SubmissionIo, TagIo, WellIo
Class Method Summary collapse
- .attributes_from_json(params) ⇒ Object
-
.convert_json_attributes_to_attributes(json_attributes) ⇒ Object
rubocop:todo Metrics/MethodLength.
- .create!(params) ⇒ Object
-
.default_object ⇒ Object
Returns the default object to use (by default this is ‘nil’) and can be overridden by passing ‘:if_nil_use => :some_function_that_returns_default_object’ to with_association.
- .extra_json_attributes(&block) ⇒ Object
-
.json_attribute_for_attribute(attribute_or_association, *rest) ⇒ Object
rubocop:todo Metrics/MethodLength.
- .lookup_associated_record_from(json_attributes) {|association.to_s.classify.constantize.find_by(search_parameters)| ... } ⇒ Object
-
.map_attribute_to_json_attribute(attribute, json_attribute = attribute) ⇒ Object
TODO: Need to warn about ‘id’ not being ‘internal_id’.
-
.map_attribute_to_json_attribute_in_errors(attribute_errors) ⇒ Object
Maps the attribute names in the errors to their JSON counterparts, so that the end user gets the correct information.
-
.newer_than(object, timestamp) {|timestamp| ... } ⇒ Object
rubocop:todo Metrics/PerceivedComplexity, Metrics/AbcSize.
-
.performs_lookup? ⇒ Boolean
rubocop:enable Metrics/MethodLength.
-
.render_class_for_model(model) ⇒ Object
The default behaviour for any model I/O is to write out all of the columns as they appear.
- .renders_model(model) ⇒ Object
-
.to_hash(object) ⇒ Object
rubocop:todo Metrics/PerceivedComplexity, Metrics/MethodLength, Metrics/AbcSize.
-
.to_hash_for_list(object) ⇒ Object
rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/PerceivedComplexity.
- .update!(object, params) ⇒ Object
-
.with_association(association, options = {}) ⇒ Object
rubocop:todo Metrics/MethodLength.
-
.with_nested_has_many_association(association, options = {}) ⇒ Object
rubocop:todo Metrics/MethodLength.
Class Method Details
.attributes_from_json(params) ⇒ Object
245 246 247 |
# File 'app/models/api/base.rb', line 245 def attributes_from_json(params) convert_json_attributes_to_attributes(params[model_class.name.underscore]) end |
.convert_json_attributes_to_attributes(json_attributes) ⇒ Object
rubocop:todo Metrics/MethodLength
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 |
# File 'app/models/api/base.rb', line 250 def convert_json_attributes_to_attributes(json_attributes) # rubocop:todo Metrics/AbcSize return {} if json_attributes.blank? attributes = {} attribute_to_json_attribute_mappings.each do |attribute, json_attribute| attributes[attribute] = json_attributes[json_attribute] if json_attributes.key?(json_attribute) end associations.each do |association, helper| if helper.performs_lookup? helper.lookup_associated_record_from(json_attributes) do |associated_record| attributes[:"#{association}_id"] = associated_record.try(:id) end else association_attributes = helper.convert_json_attributes_to_attributes(json_attributes) attributes[:"#{association}_attributes"] = association_attributes unless association_attributes.empty? end end attributes end |
.create!(params) ⇒ Object
21 22 23 |
# File 'app/models/api/base.rb', line 21 def create!(params) model_class.create!(attributes_from_json(params)) end |
.default_object ⇒ Object
Returns the default object to use (by default this is ‘nil’) and can be overridden by passing ‘:if_nil_use => :some_function_that_returns_default_object’ to with_association.
171 172 173 |
# File 'app/models/api/base.rb', line 171 def self.default_object nil end |
.extra_json_attributes(&block) ⇒ Object
239 240 241 242 |
# File 'app/models/api/base.rb', line 239 def self.extra_json_attributes(&block) self.extra_json_attribute_handlers = Array.new if extra_json_attribute_handlers.empty? extra_json_attribute_handlers.push(block) end |
.json_attribute_for_attribute(attribute_or_association, *rest) ⇒ Object
rubocop:todo Metrics/MethodLength
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 |
# File 'app/models/api/base.rb', line 273 def json_attribute_for_attribute(attribute_or_association, *rest) # rubocop:todo Metrics/AbcSize json_attribute = attribute_to_json_attribute_mappings[attribute_or_association.to_sym] if json_attribute.blank? # If we have reached the end of the line, and the attribute_or_association is for what looks like # an association, then we'll look it up without the '_id' and return that value. if attribute_or_association.to_s =~ (/_id$/) && rest.empty? association = associations[attribute_or_association.to_s.sub(/_id$/, '').to_sym] raise StandardError, "Unexpected association #{attribute_or_association.inspect}" if association.nil? return association.json_attribute_for_attribute(:name) end json_attribute = associations[attribute_or_association.to_sym].json_attribute_for_attribute(*rest) end if json_attribute.blank? raise StandardError, "Unexpected attribute #{attribute_or_association.inspect} does not appear to be mapped" end json_attribute end |
.lookup_associated_record_from(json_attributes) {|association.to_s.classify.constantize.find_by(search_parameters)| ... } ⇒ Object
216 217 218 219 220 221 222 |
# File 'app/models/api/base.rb', line 216 def self.lookup_associated_record_from(json_attributes) attributes = convert_json_attributes_to_attributes(json_attributes) return unless attributes.key?(lookup_by) search_parameters = { lookup_by => attributes[lookup_by] } yield(association.to_s.classify.constantize.find_by(search_parameters)) end |
.map_attribute_to_json_attribute(attribute, json_attribute = attribute) ⇒ Object
TODO: Need to warn about ‘id’ not being ‘internal_id’
139 140 141 142 |
# File 'app/models/api/base.rb', line 139 def self.map_attribute_to_json_attribute(attribute, json_attribute = attribute) self.attribute_to_json_attribute_mappings = attribute_to_json_attribute_mappings.merge(attribute.to_sym => json_attribute.to_s) end |
.map_attribute_to_json_attribute_in_errors(attribute_errors) ⇒ Object
Maps the attribute names in the errors to their JSON counterparts, so that the end user gets the correct information.
31 32 33 |
# File 'app/models/api/base.rb', line 31 def map_attribute_to_json_attribute_in_errors(attribute_errors) attribute_errors.transform_keys { |a| json_attribute_for_attribute(*a.to_s.split('.')) } end |
.newer_than(object, timestamp) {|timestamp| ... } ⇒ Object
rubocop:todo Metrics/PerceivedComplexity, Metrics/AbcSize
153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'app/models/api/base.rb', line 153 def self.newer_than(object, ) # rubocop:todo Metrics/CyclomaticComplexity return if object.nil? || .nil? modified, = false, (object.respond_to?(:updated_at) ? object.updated_at : ) || , modified = , true if > associations.each_value do |helper| helper.newer_than(helper.target(object), ) { |t| , modified = t, true } end nested_has_many_associations.each_value do |helper| helper.target(object).each { |child| helper.newer_than(child, ) { |t| , modified = t, true } } end yield() if modified end |
.performs_lookup? ⇒ Boolean
rubocop:enable Metrics/MethodLength
212 213 214 |
# File 'app/models/api/base.rb', line 212 def self.performs_lookup? !!lookup_by end |
.render_class_for_model(model) ⇒ Object
The default behaviour for any model I/O is to write out all of the columns as they appear. Some of the columns are ignored, a few manipulated, but mostly it’s a direct copy. rubocop:todo Metrics/MethodLength, Metrics/AbcSize
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'app/models/api/base.rb', line 98 def render_class_for_model(model) # rubocop:todo Metrics/CyclomaticComplexity render_class = Class.new(self) # NOTE: It's quite annoying that you don't have any access to the inheritable class attributes from # within the Class.new block above, so we have to do a separate instance_eval to get it to work. render_class.instance_eval do self.model_class = model model.column_names.each { |column| map_attribute_to_json_attribute(column, column) } # TODO[xxx]: It's better that some of these are decided at generation, rather than execution, time. extra_json_attributes do |object, json_attributes| json_attributes['uuid'] = object.uuid if object.respond_to?(:uuid) # Users and roles json_attributes['user'] = object.user.nil? ? 'unknown' : object.user.login if object.respond_to?(:user) if object.respond_to?(:roles) object.roles.each do |role| json_attributes[role.name.underscore] = role.users.map do |user| { login: user.login, email: user.email, name: user.name } end end end end end render_class end |
.renders_model(model) ⇒ Object
130 131 132 |
# File 'app/models/api/base.rb', line 130 def self.renders_model(model) self.model_class = model end |
.to_hash(object) ⇒ Object
rubocop:todo Metrics/PerceivedComplexity, Metrics/MethodLength, Metrics/AbcSize
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'app/models/api/base.rb', line 42 def to_hash(object) # rubocop:todo Metrics/CyclomaticComplexity # If the object is nil we get a chance to use the 'default' object that was specified. By # default the "default" object is nil, but you can override it for associations through the # with_association(:name, :if_nil_use => :some_method). object ||= default_object return {} if object.nil? json_attributes = {} json_attributes['deleted_at'] = Time.zone.now if object.destroyed? attribute_to_json_attribute_mappings.each do |attribute, json_attribute| json_attributes[json_attribute] = object.send(attribute) end associations.each do |_association, helper| value = helper.target(object) json_attributes.update(helper.to_hash(value)) helper.newer_than(value, json_attributes['updated_at']) do || json_attributes['updated_at'] = end end nested_has_many_associations.each do |_association, helper| values = helper.target(object) all_targets = values.map do |value| helper.newer_than(value, json_attributes['updated_at']) do || json_attributes['updated_at'] = end helper.to_hash(value) end json_attributes.update(helper.alias.to_s => all_targets) end extra_json_attribute_handlers.each { |handler| handler.call(object, json_attributes) } json_attributes end |
.to_hash_for_list(object) ⇒ Object
rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/PerceivedComplexity
79 80 81 82 83 84 85 86 87 |
# File 'app/models/api/base.rb', line 79 def to_hash_for_list(object) raise StandardError, 'The object is nil, which is highly unexpected!' if object.nil? json_attributes = {} attribute_to_json_attribute_mappings_for_list.each do |attribute, json_attribute| json_attributes[json_attribute] = object.send(attribute) end json_attributes end |
.update!(object, params) ⇒ Object
25 26 27 |
# File 'app/models/api/base.rb', line 25 def update!(object, params) object.update!(attributes_from_json(params)) end |
.with_association(association, options = {}) ⇒ Object
rubocop:todo Metrics/MethodLength
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'app/models/api/base.rb', line 176 def self.with_association(association, = {}, &) # rubocop:todo Metrics/AbcSize association_helper = Class.new(Api::Base) association_helper.class_eval(&) association_helper.singleton_class.class_eval do alias_method(:default_object, [:if_nil_use]) if .key?(:if_nil_use) define_method(:lookup_by) { [:lookup_by] } define_method(:association) { association } define_method(:target) do |parent| target_object = parent.send(association) [:decorator] && target_object ? [:decorator].new(target_object) : target_object end end self.associations = Hash.new if associations.empty? associations[association.to_sym] = association_helper end |
.with_nested_has_many_association(association, options = {}) ⇒ Object
rubocop:todo Metrics/MethodLength
195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
# File 'app/models/api/base.rb', line 195 def self.with_nested_has_many_association(association, = {}, &) # rubocop:todo Metrics/AbcSize association_helper = Class.new(Api::Base) association_helper.class_eval(&) association_helper.singleton_class.class_eval do define_method(:association) { association } define_method(:alias) { [:as] || association } define_method(:target) do |parent| target_object = parent.send(association) [:decorator] && target_object ? [:decorator].new(target_object) : target_object end end self.nested_has_many_associations = Hash.new if nested_has_many_associations.empty? nested_has_many_associations[association.to_sym] = association_helper end |