Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand All @@ -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

Expand Down
1 change: 1 addition & 0 deletions jsonapi-resources.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -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
33 changes: 27 additions & 6 deletions lib/jsonapi/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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,
{
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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
Expand Down
30 changes: 23 additions & 7 deletions lib/jsonapi/resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -617,5 +632,6 @@ def _associate(klass, *attrs)
end
end
end

end
end
2 changes: 1 addition & 1 deletion test/controllers/controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
end
4 changes: 2 additions & 2 deletions test/fixtures/active_record.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
18 changes: 16 additions & 2 deletions test/unit/resource/resource_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down