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