lib/jsonapi/resource.rb in jsonapi-resources-0.0.4 vs lib/jsonapi/resource.rb in jsonapi-resources-0.0.5

- old
+ new

@@ -1,5 +1,6 @@ +require 'jsonapi/configuration' require 'jsonapi/resource_for' require 'jsonapi/association' require 'action_dispatch/routing/mapper' module JSONAPI @@ -22,31 +23,49 @@ @object.destroy end def create_has_many_link(association_type, association_key_value, context) association = self.class._associations[association_type] - related_resource = self.class.resource_for(association.serialize_type_name).find_by_key(association_key_value, context) + related_resource = self.class.resource_for(association.type).find_by_key(association_key_value, context) - @object.send(association.serialize_type_name) << related_resource.object + # 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) << related_resource.object + else + raise JSONAPI::Exceptions::HasManyRelationExists.new(association_key_value) + end end 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 + 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 + 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 def remove_has_many_link(association_type, key, context) association = self.class._associations[association_type] - @object.send(association.serialize_type_name).delete(key) + @object.send(association.type).delete(key) end def remove_has_one_link(association_type, context) association = self.class._associations[association_type] @@ -93,11 +112,11 @@ keys end class << self def inherited(base) - base._attributes = (_attributes || Set.new).dup + 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 @@ -117,27 +136,30 @@ @_routing_resource_options ||= {} end # Methods used in defining a resource class def attributes(*attrs) - @_attributes.merge attrs attrs.each do |attr| attribute(attr) end end - def attribute(attr) - @_attributes.add attr + def attribute(attr, options = {}) + @_attributes[attr] = options 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 + def default_attribute_options + {format: :default} + end + def has_one(*attrs) _associate(Association::HasOne, *attrs) end def has_many(*attrs) @@ -159,28 +181,32 @@ def key(key) @_key = key.to_sym end # Override in your resource to filter the updateable keys - def updateable(keys, context = nil) - keys + def updateable_fields(context) + fields end # Override in your resource to filter the createable keys - def createable(keys, context = nil) - keys + def createable_fields(context) + fields end + def fields + _updateable_associations | _attributes.keys + end + # Override this method if you have more complex requirements than this basic find method provides 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.to_sym) + includes.push(filter) where_filters["#{filter}.#{_associations[filter].primary_key}"] = value else where_filters["#{_associations[filter].key}"] = value end else @@ -202,68 +228,21 @@ raise JSONAPI::Exceptions::RecordNotFound.new(key) end self.new(obj) end - def verify_create_params(object_params, context = nil) - verify_params(object_params, createable(_updateable_associations | _attributes.to_a), context) - end - - def verify_update_params(object_params, context = nil) - verify_params(object_params, updateable(_updateable_associations | _attributes.to_a), context) - end - - def verify_params(object_params, allowed_params, context) - # push links into top level param list with attributes in order to check for invalid params - if object_params[:links] - object_params[:links].each do |link, value| - object_params[link] = value - end - object_params.delete(:links) - end - verify_permitted_params(object_params, allowed_params) - - checked_attributes = {} - checked_has_one_associations = {} - checked_has_many_associations = {} - - object_params.each do |key, value| - param = key.to_sym - - association = _associations[param] - - if association.is_a?(JSONAPI::Association::HasOne) - checked_has_one_associations[param.to_sym] = resource_for(association.serialize_type_name).verify_key(value, context) - elsif association.is_a?(JSONAPI::Association::HasMany) - keys = [] - value.each do |value| - keys.push(resource_for(association.serialize_type_name).verify_key(value, context)) - end - checked_has_many_associations[param.to_sym] = keys - else - checked_attributes[param] = value - end - end - - return { - attributes: checked_attributes, - has_one: checked_has_one_associations, - has_many: checked_has_many_associations - } - end - 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 def is_filter_association?(filter) - filter == _serialize_as || _associations.include?(filter) + filter == _type || _associations.include?(filter) end def verify_filter(filter, raw, context = nil) filter_values = [] filter_values += CSV.parse_line(raw) unless raw.nil? || raw.empty? @@ -289,10 +268,14 @@ def verify_association_filter(filter, raw, context = nil) return filter, raw end # quasi private class methods + def _attribute_options(attr) + default_attribute_options.merge(@_attributes[attr]) + end + def _updateable_associations associations = [] @_associations.each do |key, association| if association.is_a?(JSONAPI::Association::HasOne) || association.acts_as_set @@ -301,32 +284,29 @@ end associations end def _has_association?(type) - @_associations.has_key?(type) + type = type.to_s + @_associations.has_key?(type.singularize.to_sym) || @_associations.has_key?(type.pluralize.to_sym) end def _association(type) - type = type.to_sym unless type.is_a?(Symbol) + type = type.to_sym @_associations[type] end def _model_name @_model_name ||= self.name.demodulize.sub(/Resource$/, '') end - def _serialize_as - @_serialize_as ||= self._type - end - def _key @_key ||= :id end def _as_parent_key - @_as_parent_key ||= "#{_serialize_as.to_s.singularize}_#{_key}" + @_as_parent_key ||= "#{_type.to_s.singularize}_#{_key}" end def _allowed_filters !@_allowed_filters.nil? ? @_allowed_filters : Set.new([_key]) end @@ -349,17 +329,13 @@ @model ||= _model_name.to_s.safe_constantize end end def _allowed_filter?(filter) - _allowed_filters.include?(filter.to_sym) + _allowed_filters.include?(filter) end - def _validate_field(field) - _attributes.include?(field) || _associations.key?(field) - end - private def _associate(klass, *attrs) options = attrs.extract_options! @@ -372,11 +348,11 @@ define_method key do @object.method(key).call end unless method_defined?(key) define_method "_#{attr}_object" do - type_name = self.class._associations[attr].serialize_type_name + type_name = self.class._associations[attr].type resource_class = self.class.resource_for(type_name) if resource_class associated_object = @object.send attr return resource_class.new(associated_object) end @@ -387,11 +363,11 @@ define_method key do @object.method(key).call end unless method_defined?(key) define_method "_#{attr}_objects" do - type_name = self.class._associations[attr].serialize_type_name + type_name = self.class._associations[attr].type resource_class = self.class.resource_for(type_name) resources = [] if resource_class associated_objects = @object.send attr associated_objects.each do |associated_object| @@ -401,17 +377,8 @@ return resources end end end end - - def verify_permitted_params(params, allowed_param_set) - params_not_allowed = [] - params.keys.each do |key| - param = key.to_sym - params_not_allowed.push(param) unless allowed_param_set.include?(param) - end - raise JSONAPI::Exceptions::ParametersNotAllowed.new(params_not_allowed) if params_not_allowed.length > 0 - end end end -end \ No newline at end of file +end