diff --git a/README.md b/README.md index 58d9338f8..773934a7f 100644 --- a/README.md +++ b/README.md @@ -119,10 +119,10 @@ end Context flows through from the controller and can be used to control the attributes based on the current user (or other value). -##### Createable and Updateable Attributes +##### Creatable and Updatable Attributes -By default all attributes are assumed to be updateable and createable. To prevent some attributes from being accepted by -the `update` or `create` methods, override the `self.updateable_fields` and `self.createable_fields` methods on a resource. +By default all attributes are assumed to be updatable and creatable. To prevent some attributes from being accepted by +the `update` or `create` methods, override the `self.updatable_fields` and `self.creatable_fields` methods on a resource. This example prevents `full_name` from being set: @@ -136,18 +136,18 @@ class ContactResource < JSONAPI::Resource "#{@model.name_first}, #{@model.name_last}" end - def self.updateable_fields(context) + def self.updatable_fields(context) super - [:full_name] end - def self.createable_fields(context) + def self.creatable_fields(context) super - [:full_name] end end ``` The `context` is not by default used by the `ResourceController`, but may be used if you override the controller methods. -By using the context you have the option to determine the createable and updateable fields based on the user. +By using the context you have the option to determine the creatable and updatable fields based on the user. ##### Sortable Attributes diff --git a/jsonapi-resources.gemspec b/jsonapi-resources.gemspec index 25054c123..ca68ca234 100644 --- a/jsonapi-resources.gemspec +++ b/jsonapi-resources.gemspec @@ -25,5 +25,6 @@ Gem::Specification.new do |spec| spec.add_development_dependency 'minitest-spec-rails' spec.add_development_dependency 'minitest-reporters' spec.add_development_dependency 'simplecov' + spec.add_development_dependency 'pry' spec.add_dependency 'rails', '>= 4.0' end diff --git a/lib/jsonapi/request.rb b/lib/jsonapi/request.rb index 2a59593a8..4e6ce33be 100644 --- a/lib/jsonapi/request.rb +++ b/lib/jsonapi/request.rb @@ -316,11 +316,22 @@ def add_show_related_resources_operation(association_type) ) end + # TODO: Please remove after `createable_fields` is removed + # :nocov: + def creatable_fields + if @resource_klass.respond_to?(:createable_fields) + creatable_fields = @resource_klass.createable_fields(@context) + else + creatable_fields = @resource_klass.creatable_fields(@context) + end + end + # :nocov: + def parse_add_operation(data) Array.wrap(data).each do |params| verify_type(params[:type]) - data = parse_params(params, @resource_klass.createable_fields(@context)) + data = parse_params(params, creatable_fields) @operations.push JSONAPI::CreateResourceOperation.new( @resource_klass, { @@ -486,12 +497,23 @@ def verify_permitted_params(params, allowed_fields) raise JSONAPI::Exceptions::ParametersNotAllowed.new(params_not_allowed) if params_not_allowed.length > 0 end + # TODO: Please remove after `updateable_fields` is removed + # :nocov: + def updatable_fields + if @resource_klass.respond_to?(:updateable_fields) + @resource_klass.updateable_fields(@context) + else + @resource_klass.updatable_fields(@context) + end + end + # :nocov: + def parse_add_association_operation(data, association_type, parent_key) association = resource_klass._association(association_type) if association.is_a?(JSONAPI::Association::HasMany) object_params = {relationships: {format_key(association.name) => {data: data}}} - verified_param_set = parse_params(object_params, @resource_klass.updateable_fields(@context)) + verified_param_set = parse_params(object_params, updatable_fields) @operations.push JSONAPI::CreateHasManyAssociationOperation.new( resource_klass, @@ -509,8 +531,7 @@ def parse_update_association_operation(data, association_type, parent_key) if association.is_a?(JSONAPI::Association::HasOne) object_params = {relationships: {format_key(association.name) => {data: data}}} - - verified_param_set = parse_params(object_params, @resource_klass.updateable_fields(@context)) + verified_param_set = parse_params(object_params, updatable_fields) @operations.push JSONAPI::ReplaceHasOneAssociationOperation.new( resource_klass, @@ -526,7 +547,7 @@ def parse_update_association_operation(data, association_type, parent_key) end object_params = {relationships: {format_key(association.name) => {data: data}}} - verified_param_set = parse_params(object_params, @resource_klass.updateable_fields(@context)) + verified_param_set = parse_params(object_params, updatable_fields) @operations.push JSONAPI::ReplaceHasManyAssociationOperation.new( resource_klass, @@ -564,7 +585,7 @@ def parse_single_replace_operation(data, keys) @resource_klass, { resource_id: key, - data: parse_params(data, @resource_klass.updateable_fields(@context)) + data: parse_params(data, updatable_fields) } ) end diff --git a/lib/jsonapi/resource.rb b/lib/jsonapi/resource.rb index 32a888d33..f97d6f5ce 100644 --- a/lib/jsonapi/resource.rb +++ b/lib/jsonapi/resource.rb @@ -287,14 +287,29 @@ def primary_key(key) @_primary_key = key.to_sym end - # Override in your resource to filter the updateable keys - def updateable_fields(context = nil) - _updateable_associations | _attributes.keys - [:id] + # TODO: remove this after the createable_fields and updateable_fields are phased out + # :nocov: + def method_missing(method, *args) + if method.to_s.match /createable_fields/ + ActiveSupport::Deprecation.warn("`createable_fields` is deprecated, please use `creatable_fields` instead") + self.creatable_fields(*args) + elsif method.to_s.match /updateable_fields/ + ActiveSupport::Deprecation.warn("`updateable_fields` is deprecated, please use `updatable_fields` instead") + self.updatable_fields(*args) + else + super + end end + # :nocov: - # Override in your resource to filter the createable keys - def createable_fields(context = nil) - _updateable_associations | _attributes.keys + # Override in your resource to filter the updatable keys + def updatable_fields(context = nil) + _updatable_associations | _attributes.keys - [:id] + end + + # Override in your resource to filter the creatable keys + def creatable_fields(context = nil) + _updatable_associations | _attributes.keys end # Override in your resource to filter the sortable keys @@ -464,7 +479,7 @@ def _attribute_options(attr) default_attribute_options.merge(@_attributes[attr]) end - def _updateable_associations + def _updatable_associations @_associations.map { |key, association| key } end @@ -617,5 +632,6 @@ def _associate(klass, *attrs) end end end + end end diff --git a/test/controllers/controller_test.rb b/test/controllers/controller_test.rb index 593d5cd58..e25e14955 100644 --- a/test/controllers/controller_test.rb +++ b/test/controllers/controller_test.rb @@ -2321,4 +2321,4 @@ def test_index_default_filter_override assert json_response['data'].is_a?(Array) assert_equal 4, json_response['data'].size end -end \ No newline at end of file +end diff --git a/test/fixtures/active_record.rb b/test/fixtures/active_record.rb index fdbfc52f2..1861a1aae 100644 --- a/test/fixtures/active_record.rb +++ b/test/fixtures/active_record.rb @@ -613,11 +613,11 @@ def subject filters :title, :author, :tags, :comments filters :id, :ids - def self.updateable_fields(context) + def self.updatable_fields(context) super(context) - [:author, :subject] end - def self.createable_fields(context) + def self.creatable_fields(context) super(context) - [:subject] end diff --git a/test/unit/resource/resource_test.rb b/test/unit/resource/resource_test.rb index 709a77e22..16b9948db 100644 --- a/test/unit/resource/resource_test.rb +++ b/test/unit/resource/resource_test.rb @@ -132,8 +132,22 @@ def test_find_by_key_with_customized_base_records end end - def test_updateable_fields_does_not_include_id - assert(!CatResource.updateable_fields.include?(:id)) + def test_updatable_fields_does_not_include_id + assert(!CatResource.updatable_fields.include?(:id)) + end + + # TODO: Please remove after `updateable_fields` is removed + def test_updateable_fields_delegates_to_updatable_fields_with_deprecation + ActiveSupport::Deprecation.silence do + assert_empty(CatResource.updateable_fields(nil) - [:mother, :father, :name, :breed]) + end + end + + # TODO: Please remove after `createable_fields` is removed + def test_createable_fields_delegates_to_creatable_fields_with_deprecation + ActiveSupport::Deprecation.silence do + assert_empty(CatResource.createable_fields(nil) - [:mother, :father, :name, :breed, :id]) + end end def test_has_many_association_filters