Skip to content

Commit 87718d8

Browse files
committed
Add an immutable option to JSON API resources.
Discussed here: #343
1 parent 5c6745c commit 87718d8

File tree

3 files changed

+41
-0
lines changed

3 files changed

+41
-0
lines changed

lib/json_api_client/errors.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ def initialize(env, msg = nil)
1111
class ClientError < ApiError
1212
end
1313

14+
class ResourceImmutableError < StandardError
15+
def initialize(msg = 'Resource immutable')
16+
super msg
17+
end
18+
end
19+
1420
class AccessDenied < ClientError
1521
end
1622

lib/json_api_client/resource.rb

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ class Resource
4040
instance_accessor: false
4141
class_attribute :add_defaults_to_changes,
4242
instance_writer: false
43+
44+
class_attribute :_immutable,
45+
instance_writer: false,
46+
default: false
47+
4348
self.primary_key = :id
4449
self.parser = Parsers::Parser
4550
self.paginator = Paginating::Paginator
@@ -94,6 +99,18 @@ def type
9499
table_name
95100
end
96101

102+
# Indicates whether this resource is mutable or immutable;
103+
# by default, all resources are mutable.
104+
#
105+
# @return [Boolean]
106+
def immutable(flag = true)
107+
self._immutable = flag
108+
end
109+
110+
def inherited(subclass)
111+
subclass._immutable = false
112+
end
113+
97114
# Specifies the relative path that should be used for this resource;
98115
# by default, this is inferred from the resource class name.
99116
#
@@ -215,6 +232,11 @@ def route_formatter
215232
# @option [Symbol] :on One of [:collection or :member] to decide whether it's a collect or member method
216233
# @option [Symbol] :request_method The request method (:get, :post, etc)
217234
def custom_endpoint(name, options = {})
235+
if _immutable
236+
request_method = options.fetch(:request_method, :get).to_sym
237+
raise JsonApiClient::Errors::ResourceImmutableError if request_method != :get
238+
end
239+
218240
if :collection == options.delete(:on)
219241
collection_endpoint(name, options)
220242
else
@@ -440,6 +462,7 @@ def valid?(context = nil)
440462
# @return [Boolean] Whether or not the save succeeded
441463
def save
442464
return false unless valid?
465+
raise JsonApiClient::Errors::ResourceImmutableError if _immutable
443466

444467
self.last_result_set = if persisted?
445468
self.class.requestor.update(self)
@@ -471,6 +494,8 @@ def save
471494
#
472495
# @return [Boolean] Whether or not the destroy succeeded
473496
def destroy
497+
raise JsonApiClient::Errors::ResourceImmutableError if _immutable
498+
474499
self.last_result_set = self.class.requestor.destroy(self)
475500
if last_result_set.has_errors?
476501
fill_errors

test/unit/resource_test.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,4 +95,14 @@ def test_default_params_overrideable
9595
assert_equal(article.type, 'Story')
9696
end
9797

98+
def test_immutable
99+
Article.immutable(true)
100+
article = Article.new(type: 'Story')
101+
assert_raises JsonApiClient::Errors::ResourceImmutableError do
102+
article.save
103+
end
104+
ensure
105+
Article.immutable(false)
106+
end
107+
98108
end

0 commit comments

Comments
 (0)