lib/jsonapi/resource.rb in jsonapi-resources-0.6.0 vs lib/jsonapi/resource.rb in jsonapi-resources-0.6.1

- old
+ new

@@ -5,11 +5,10 @@ include Callbacks @@resource_types = {} attr_reader :context - attr_reader :model define_jsonapi_resources_callbacks :create, :update, :remove, :save, @@ -25,12 +24,16 @@ def initialize(model, context) @model = model @context = context end + def _model + @model + end + def id - model.public_send(self.class._primary_key) + _model.public_send(self.class._primary_key) end def is_new? id.nil? end @@ -110,11 +113,11 @@ end # Override this on a resource to customize how the associated records # are fetched for a model. Particularly helpful for authorization. def records_for(relation_name) - model.public_send relation_name + _model.public_send relation_name end private def save @@ -167,11 +170,11 @@ relation_name = relationship.relation_name(context: @context) # TODO: Add option to skip relations that already exist instead of returning an error? relation = @model.public_send(relation_name).where(relationship.primary_key => relationship_key_value).first if relation.nil? - @model.public_send(relation_name) << related_resource.model + @model.public_send(relation_name) << related_resource._model else fail JSONAPI::Exceptions::HasManyRelationExists.new(relationship_key_value) end end @@ -196,12 +199,12 @@ end def _replace_polymorphic_to_one_link(relationship_type, key_value, key_type) relationship = self.class._relationships[relationship_type.to_sym] - model.public_send("#{relationship.foreign_key}=", key_value) - model.public_send("#{relationship.polymorphic_type}=", key_type.to_s.classify) + _model.public_send("#{relationship.foreign_key}=", key_value) + _model.public_send("#{relationship.polymorphic_type}=", key_type.to_s.classify) @save_needed = true :completed end @@ -256,10 +259,11 @@ end class << self def inherited(base) base.abstract(false) + base.immutable(false) base._attributes = (_attributes || {}).dup base._relationships = (_relationships || {}).dup base._allowed_filters = (_allowed_filters || Set.new).dup type = base.name.demodulize.sub(/Resource$/, '').underscore @@ -497,11 +501,11 @@ records = apply_pagination(records, options[:paginator], order_options) resources = [] records.each do |model| - resources.push new(model, context) + resources.push resource_for(resource_type_for(model)).new(model, context) end resources end @@ -509,13 +513,17 @@ context = options[:context] records = records(options) records = apply_includes(records, options) model = records.where({_primary_key => key}).first fail JSONAPI::Exceptions::RecordNotFound.new(key) if model.nil? - new(model, context) + resource_for(resource_type_for(model)).new(model, context) end + def resource_type_for(model) + self.module_path + model.class.to_s.underscore + end + # Override this method if you want to customize the relation for # finder methods (find, find_by_key) def records(_options = {}) _model_class end @@ -552,44 +560,32 @@ @_resource_key_type || JSONAPI.configuration.resource_key_type end def verify_key(key, context = nil) key_type = resource_key_type - verification_proc = case key_type + case key_type when :integer - -> (key, context) { - begin - return key if key.nil? - Integer(key) - rescue - raise JSONAPI::Exceptions::InvalidFieldValue.new(:id, key) - end - } + return if key.nil? + Integer(key) when :string - -> (key, context) { - return key if key.nil? - if key.to_s.include?(',') - raise JSONAPI::Exceptions::InvalidFieldValue.new(:id, key) - else - key - end - } + return if key.nil? + if key.to_s.include?(',') + raise JSONAPI::Exceptions::InvalidFieldValue.new(:id, key) + else + key + end when :uuid - -> (key, context) { - return key if key.nil? - if key.to_s.match(/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/) - key - else - raise JSONAPI::Exceptions::InvalidFieldValue.new(:id, key) - end - } + return if key.nil? + if key.to_s.match(/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/) + key + else + raise JSONAPI::Exceptions::InvalidFieldValue.new(:id, key) + end else - key_type + key_type.call(key, context) end - - verification_proc.call(key, context) rescue raise JSONAPI::Exceptions::InvalidFieldValue.new(:id, key) end # override to allow for key processing and checking @@ -662,10 +658,22 @@ def _abstract @abstract end + def immutable(val = true) + @immutable = val + end + + def _immutable + @immutable + end + + def mutable? + !@immutable + end + def _model_class return nil if _abstract return @model if @model @model = _model_name.to_s.safe_constantize @@ -676,11 +684,11 @@ def _allowed_filter?(filter) !_allowed_filters[filter].nil? end def module_path - @module_path ||= name =~ /::[^:]+\Z/ ? ($`.freeze.gsub('::', '/') + '/').underscore : '' + name =~ /::[^:]+\Z/ ? ($`.freeze.gsub('::', '/') + '/').underscore : '' end def construct_order_options(sort_params) return {} unless sort_params @@ -700,17 +708,17 @@ end def check_reserved_attribute_name(name) # Allow :id since it can be used to specify the format. Since it is a method on the base Resource # an attribute method won't be created for it. - if [:type, :href, :links, :model].include?(name.to_sym) + if [:type].include?(name.to_sym) warn "[NAME COLLISION] `#{name}` is a reserved key in #{@@resource_types[_type]}." end end def check_reserved_relationship_name(name) - if [:id, :ids, :type, :types, :href, :hrefs, :link, :links].include?(name.to_sym) + if [:id, :ids, :type, :types].include?(name.to_sym) warn "[NAME COLLISION] `#{name}` is a reserved relationship name in #{@@resource_types[_type]}." end end def _add_relationship(klass, *attrs) @@ -753,11 +761,11 @@ end unless method_defined?(foreign_key) define_method attr do |options = {}| if relationship.polymorphic? associated_model = public_send(associated_records_method_name) - resource_klass = Resource.resource_for(self.class.module_path + associated_model.class.to_s.underscore) if associated_model + resource_klass = Resource.resource_for(self.class.resource_type_for(associated_model)) if associated_model return resource_klass.new(associated_model, @context) if resource_klass else resource_klass = relationship.resource_klass if resource_klass associated_model = public_send(associated_records_method_name) @@ -806,12 +814,10 @@ if paginator records = resource_klass.apply_pagination(records, paginator, order_options) end return records.collect do |record| - if relationship.polymorphic? - resource_klass = Resource.resource_for(self.class.module_path + record.class.to_s.underscore) - end + resource_klass = Resource.resource_for(self.class.resource_type_for(record)) resource_klass.new(record, @context) end end unless method_defined?(attr) end end