Class: JSONAPI::Resource
- Inherits:
-
Object
- Object
- JSONAPI::Resource
- Includes:
- ResourceFor
- Defined in:
- lib/jsonapi/resource.rb
Constant Summary collapse
- @@resource_types =
{}
Class Attribute Summary collapse
-
._allowed_filters ⇒ Object
Returns the value of attribute _allowed_filters.
-
._associations ⇒ Object
Returns the value of attribute _associations.
-
._attributes ⇒ Object
Returns the value of attribute _attributes.
-
._type ⇒ Object
Returns the value of attribute _type.
Instance Attribute Summary collapse
-
#object ⇒ Object
readonly
Returns the value of attribute object.
Class Method Summary collapse
- ._allowed_filter?(filter) ⇒ Boolean
- ._as_parent_key ⇒ Object
- ._association(type) ⇒ Object
-
._attribute_options(attr) ⇒ Object
quasi private class methods.
- ._has_association?(type) ⇒ Boolean
- ._key ⇒ Object
- ._model_name ⇒ Object
- ._resource_name_from_type(type) ⇒ Object
- ._updateable_associations ⇒ Object
- .attribute(attr, options = {}) ⇒ Object
-
.attributes(*attrs) ⇒ Object
Methods used in defining a resource class.
-
.createable_fields(context) ⇒ Object
Override in your resource to filter the createable keys.
- .default_attribute_options ⇒ Object
- .fields ⇒ Object
- .filter(attr) ⇒ Object
- .filters(*attrs) ⇒ Object
-
.find(filters, context = nil) ⇒ Object
Override this method if you have more complex requirements than this basic find method provides.
- .find_by_key(key, context = nil) ⇒ Object
- .has_many(*attrs) ⇒ Object
- .has_one(*attrs) ⇒ Object
- .inherited(base) ⇒ Object
- .is_filter_association?(filter) ⇒ Boolean
- .key(key) ⇒ Object
- .model_name(model) ⇒ Object
- .routing_options(options) ⇒ Object
- .routing_resource_options ⇒ Object
-
.updateable_fields(context) ⇒ Object
Override in your resource to filter the updateable keys.
-
.verify_association_filter(filter, raw, context = nil) ⇒ Object
override to allow for custom association logic, such as uuids, multiple keys or permission checks on keys.
-
.verify_custom_filter(filter, value, context = nil) ⇒ Object
override to allow for custom filters.
- .verify_filter(filter, raw, context = nil) ⇒ Object
- .verify_filters(filters, context = nil) ⇒ Object
-
.verify_key(key, context = nil) ⇒ Object
override to allow for key processing and checking.
Instance Method Summary collapse
- #_model_class ⇒ Object
- #create_has_many_link(association_type, association_key_value, context) ⇒ Object
- #create_has_one_link(association_type, association_key_value, context) ⇒ Object
- #create_new_object ⇒ Object
-
#fetchable(keys, context = nil) ⇒ Object
Override this on a resource instance to override the fetchable keys.
-
#initialize(object = create_new_object) ⇒ Resource
constructor
A new instance of Resource.
- #remove(context) ⇒ Object
- #remove_has_many_link(association_type, key, context) ⇒ Object
- #remove_has_one_link(association_type, context) ⇒ Object
- #replace_fields(field_data, context) ⇒ Object
- #replace_has_many_links(association_type, association_key_values, context) ⇒ Object
- #replace_has_one_link(association_type, association_key_value, context) ⇒ Object
- #save(context) ⇒ Object
Methods included from ResourceFor
Constructor Details
#initialize(object = create_new_object) ⇒ Resource
Returns a new instance of Resource.
14 15 16 |
# File 'lib/jsonapi/resource.rb', line 14 def initialize(object = create_new_object) @object = object end |
Class Attribute Details
._allowed_filters ⇒ Object
Returns the value of attribute _allowed_filters.
129 130 131 |
# File 'lib/jsonapi/resource.rb', line 129 def _allowed_filters @_allowed_filters end |
._associations ⇒ Object
Returns the value of attribute _associations.
129 130 131 |
# File 'lib/jsonapi/resource.rb', line 129 def _associations @_associations end |
._attributes ⇒ Object
Returns the value of attribute _attributes.
129 130 131 |
# File 'lib/jsonapi/resource.rb', line 129 def _attributes @_attributes end |
._type ⇒ Object
Returns the value of attribute _type.
129 130 131 |
# File 'lib/jsonapi/resource.rb', line 129 def _type @_type end |
Instance Attribute Details
#object ⇒ Object (readonly)
Returns the value of attribute object.
12 13 14 |
# File 'lib/jsonapi/resource.rb', line 12 def object @object end |
Class Method Details
._allowed_filter?(filter) ⇒ Boolean
333 334 335 |
# File 'lib/jsonapi/resource.rb', line 333 def _allowed_filter?(filter) _allowed_filters.include?(filter) end |
._as_parent_key ⇒ Object
306 307 308 |
# File 'lib/jsonapi/resource.rb', line 306 def _as_parent_key @_as_parent_key ||= "#{_type.to_s.singularize}_#{_key}" end |
._association(type) ⇒ Object
293 294 295 296 |
# File 'lib/jsonapi/resource.rb', line 293 def _association(type) type = type.to_sym @_associations[type] end |
._attribute_options(attr) ⇒ Object
quasi private class methods
273 274 275 |
# File 'lib/jsonapi/resource.rb', line 273 def (attr) .merge(@_attributes[attr]) end |
._has_association?(type) ⇒ Boolean
288 289 290 291 |
# File 'lib/jsonapi/resource.rb', line 288 def _has_association?(type) type = type.to_s @_associations.has_key?(type.singularize.to_sym) || @_associations.has_key?(type.pluralize.to_sym) end |
._key ⇒ Object
302 303 304 |
# File 'lib/jsonapi/resource.rb', line 302 def _key @_key ||= :id end |
._model_name ⇒ Object
298 299 300 |
# File 'lib/jsonapi/resource.rb', line 298 def _model_name @_model_name ||= self.name.demodulize.sub(/Resource$/, '') end |
._resource_name_from_type(type) ⇒ Object
314 315 316 317 318 319 320 321 |
# File 'lib/jsonapi/resource.rb', line 314 def _resource_name_from_type(type) class_name = @@resource_types[type] if class_name.nil? class_name = type.to_s.singularize.camelize + 'Resource' @@resource_types[type] = class_name end return class_name end |
._updateable_associations ⇒ Object
277 278 279 280 281 282 283 284 285 286 |
# File 'lib/jsonapi/resource.rb', line 277 def _updateable_associations associations = [] @_associations.each do |key, association| if association.is_a?(JSONAPI::Association::HasOne) || association.acts_as_set associations.push(key) end end associations end |
.attribute(attr, options = {}) ⇒ Object
146 147 148 149 150 151 152 153 154 155 |
# File 'lib/jsonapi/resource.rb', line 146 def attribute(attr, = {}) @_attributes[attr] = define_method attr do @object.send(attr) end unless method_defined?(attr) define_method "#{attr}=" do |value| @object.send "#{attr}=", value end unless method_defined?("#{attr}=") end |
.attributes(*attrs) ⇒ Object
Methods used in defining a resource class
140 141 142 143 144 |
# File 'lib/jsonapi/resource.rb', line 140 def attributes(*attrs) attrs.each do |attr| attribute(attr) end end |
.createable_fields(context) ⇒ Object
Override in your resource to filter the createable keys
191 192 193 |
# File 'lib/jsonapi/resource.rb', line 191 def createable_fields(context) fields end |
.default_attribute_options ⇒ Object
157 158 159 |
# File 'lib/jsonapi/resource.rb', line 157 def {format: :default} end |
.fields ⇒ Object
195 196 197 |
# File 'lib/jsonapi/resource.rb', line 195 def fields _updateable_associations | _attributes.keys end |
.filter(attr) ⇒ Object
177 178 179 |
# File 'lib/jsonapi/resource.rb', line 177 def filter(attr) @_allowed_filters.add(attr.to_sym) end |
.filters(*attrs) ⇒ Object
173 174 175 |
# File 'lib/jsonapi/resource.rb', line 173 def filters(*attrs) @_allowed_filters.merge(attrs) end |
.find(filters, context = nil) ⇒ Object
Override this method if you have more complex requirements than this basic find method provides
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
# File 'lib/jsonapi/resource.rb', line 200 def find(filters, context = nil) includes = [] where_filters = {} filters.each do |filter, value| if _associations.include?(filter) if _associations[filter].is_a?(JSONAPI::Association::HasMany) includes.push(filter) where_filters["#{filter}.#{_associations[filter].primary_key}"] = value else where_filters["#{_associations[filter].key}"] = value end else where_filters[filter] = value end end resources = [] _model_class.where(where_filters).includes(includes).each do |object| resources.push self.new(object) end return resources end |
.find_by_key(key, context = nil) ⇒ Object
225 226 227 228 229 230 231 |
# File 'lib/jsonapi/resource.rb', line 225 def find_by_key(key, context = nil) obj = _model_class.where({_key => key}).first if obj.nil? raise JSONAPI::Exceptions::RecordNotFound.new(key) end self.new(obj) end |
.has_many(*attrs) ⇒ Object
165 166 167 |
# File 'lib/jsonapi/resource.rb', line 165 def has_many(*attrs) _associate(Association::HasMany, *attrs) end |
.has_one(*attrs) ⇒ Object
161 162 163 |
# File 'lib/jsonapi/resource.rb', line 161 def has_one(*attrs) _associate(Association::HasOne, *attrs) end |
.inherited(base) ⇒ Object
116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/jsonapi/resource.rb', line 116 def inherited(base) base._attributes = (_attributes || {}).dup base._associations = (_associations || {}).dup base._allowed_filters = (_allowed_filters || Set.new).dup type = base.name.demodulize.sub(/Resource$/, '').underscore base._type = type.pluralize.to_sym # If eager loading is on this is how all the resource types are setup # If eager loading is off some resource types will be initialized in # _resource_name_from_type @@resource_types[base._type] ||= base.name.demodulize end |
.is_filter_association?(filter) ⇒ Boolean
242 243 244 |
# File 'lib/jsonapi/resource.rb', line 242 def is_filter_association?(filter) filter == _type || _associations.include?(filter) end |
.key(key) ⇒ Object
181 182 183 |
# File 'lib/jsonapi/resource.rb', line 181 def key(key) @_key = key.to_sym end |
.model_name(model) ⇒ Object
169 170 171 |
# File 'lib/jsonapi/resource.rb', line 169 def model_name(model) @_model_name = model.to_sym end |
.routing_options(options) ⇒ Object
131 132 133 |
# File 'lib/jsonapi/resource.rb', line 131 def () @_routing_resource_options = end |
.routing_resource_options ⇒ Object
135 136 137 |
# File 'lib/jsonapi/resource.rb', line 135 def @_routing_resource_options ||= {} end |
.updateable_fields(context) ⇒ Object
Override in your resource to filter the updateable keys
186 187 188 |
# File 'lib/jsonapi/resource.rb', line 186 def updateable_fields(context) fields end |
.verify_association_filter(filter, raw, context = nil) ⇒ Object
override to allow for custom association logic, such as uuids, multiple keys or permission checks on keys
268 269 270 |
# File 'lib/jsonapi/resource.rb', line 268 def verify_association_filter(filter, raw, context = nil) return filter, raw end |
.verify_custom_filter(filter, value, context = nil) ⇒ Object
override to allow for custom filters
263 264 265 |
# File 'lib/jsonapi/resource.rb', line 263 def verify_custom_filter(filter, value, context = nil) return filter, value end |
.verify_filter(filter, raw, context = nil) ⇒ Object
246 247 248 249 250 251 252 253 254 255 |
# File 'lib/jsonapi/resource.rb', line 246 def verify_filter(filter, raw, context = nil) filter_values = [] filter_values += CSV.parse_line(raw) unless raw.nil? || raw.empty? if is_filter_association?(filter) verify_association_filter(filter, filter_values, context) else verify_custom_filter(filter, filter_values, context) end end |
.verify_filters(filters, context = nil) ⇒ Object
233 234 235 236 237 238 239 240 |
# File 'lib/jsonapi/resource.rb', line 233 def verify_filters(filters, context = nil) verified_filters = {} filters.each do |filter, raw_value| verified_filter = verify_filter(filter, raw_value, context) verified_filters[verified_filter[0]] = verified_filter[1] end verified_filters end |
.verify_key(key, context = nil) ⇒ Object
override to allow for key processing and checking
258 259 260 |
# File 'lib/jsonapi/resource.rb', line 258 def verify_key(key, context = nil) return key end |
Instance Method Details
#_model_class ⇒ Object
324 325 326 |
# File 'lib/jsonapi/resource.rb', line 324 def _model_class @model ||= Object.const_get(_model_name) end |
#create_has_many_link(association_type, association_key_value, context) ⇒ Object
26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/jsonapi/resource.rb', line 26 def create_has_many_link(association_type, association_key_value, context) association = self.class._associations[association_type] = self.class.resource_for(association.type).find_by_key(association_key_value, context) # ToDo: Add option to skip relations that already exist instead of returning an error? relation = @object.send(association.type).where(association.primary_key => association_key_value).first if relation.nil? @object.send(association.type) << .object else raise JSONAPI::Exceptions::HasManyRelationExists.new(association_key_value) end end |
#create_has_one_link(association_type, association_key_value, context) ⇒ Object
45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/jsonapi/resource.rb', line 45 def create_has_one_link(association_type, association_key_value, context) association = self.class._associations[association_type] # ToDo: Add option to skip relations that already exist instead of returning an error? relation = @object.send("#{association.key}") if relation.nil? @object.send("#{association.key}=", association_key_value) else raise JSONAPI::Exceptions::HasOneRelationExists.new end end |
#create_new_object ⇒ Object
18 19 20 |
# File 'lib/jsonapi/resource.rb', line 18 def create_new_object self.class._model_class.new end |
#fetchable(keys, context = nil) ⇒ Object
Override this on a resource instance to override the fetchable keys
111 112 113 |
# File 'lib/jsonapi/resource.rb', line 111 def fetchable(keys, context = nil) keys end |
#remove(context) ⇒ Object
22 23 24 |
# File 'lib/jsonapi/resource.rb', line 22 def remove(context) @object.destroy end |
#remove_has_many_link(association_type, key, context) ⇒ Object
63 64 65 66 67 |
# File 'lib/jsonapi/resource.rb', line 63 def remove_has_many_link(association_type, key, context) association = self.class._associations[association_type] @object.send(association.type).delete(key) end |
#remove_has_one_link(association_type, context) ⇒ Object
69 70 71 72 73 |
# File 'lib/jsonapi/resource.rb', line 69 def remove_has_one_link(association_type, context) association = self.class._associations[association_type] @object.send("#{association.key}=", nil) end |
#replace_fields(field_data, context) ⇒ Object
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/jsonapi/resource.rb', line 75 def replace_fields(field_data, context) field_data[:attributes].each do |attribute, value| send "#{attribute}=", value end field_data[:has_one].each do |association_type, value| if value.nil? remove_has_one_link(association_type, context) else replace_has_one_link(association_type, value, context) end end if field_data[:has_one] field_data[:has_many].each do |association_type, values| replace_has_many_links(association_type, values, context) end if field_data[:has_many] end |
#replace_has_many_links(association_type, association_key_values, context) ⇒ Object
39 40 41 42 43 |
# File 'lib/jsonapi/resource.rb', line 39 def replace_has_many_links(association_type, association_key_values, context) association = self.class._associations[association_type] @object.send("#{association.key}=", association_key_values) end |
#replace_has_one_link(association_type, association_key_value, context) ⇒ Object
57 58 59 60 61 |
# File 'lib/jsonapi/resource.rb', line 57 def replace_has_one_link(association_type, association_key_value, context) association = self.class._associations[association_type] @object.send("#{association.key}=", association_key_value) end |
#save(context) ⇒ Object
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/jsonapi/resource.rb', line 93 def save(context) @object.save! rescue ActiveRecord::RecordInvalid => e errors = [] e.record.errors..each do |element| element[1].each do || errors.push(JSONAPI::Error.new( code: JSONAPI::VALIDATION_ERROR, status: :bad_request, title: "#{element[0]} - #{}", detail: "can't be blank", path: "\\#{element[0]}")) end end raise JSONAPI::Exceptions::ValidationErrors.new(errors) end |