Skip to content

Commit 35beaf5

Browse files
committed
Merge pull request #344 from cerebris/abstract
Adds abstract option
2 parents 71efd94 + 9016c89 commit 35beaf5

4 files changed

Lines changed: 59 additions & 8 deletions

File tree

README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,25 @@ class ContactResource < JSONAPI::Resource
5454
end
5555
```
5656

57+
##### Abstract Resources
58+
59+
Resources that are not backed by a model (purely used as base classes for other resources) should be declared as
60+
abstract.
61+
62+
Because abstract resources do not expect to be backed by a model, they won't attempt to discover the model class
63+
or any of its relationships.
64+
65+
```ruby
66+
class BaseResource < JSONAPI::Resource
67+
abstract
68+
69+
has_one :creator
70+
end
71+
72+
class ContactResource < BaseResource
73+
end
74+
```
75+
5776
#### Attributes
5877

5978
Any of a resource's attributes that are accessible must be explicitly declared. Single attributes can be declared using

lib/jsonapi/resource.rb

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ def _replace_fields(field_data)
257257

258258
class << self
259259
def inherited(base)
260+
base.abstract(false)
260261
base._attributes = (_attributes || {}).dup
261262
base._relationships = (_relationships || {}).dup
262263
base._allowed_filters = (_allowed_filters || Set.new).dup
@@ -620,10 +621,20 @@ def paginator(paginator)
620621
@_paginator = paginator
621622
end
622623

624+
def abstract(val = true)
625+
@abstract = val
626+
end
627+
628+
def _abstract
629+
@abstract
630+
end
631+
623632
def _model_class
633+
return nil if _abstract
634+
624635
return @model if @model
625636
@model = _model_name.to_s.safe_constantize
626-
fail NameError, "model could not be found for #{self.name}" if @model.nil?
637+
warn "[MODEL NOT FOUND] Model could not be found for #{self.name}. If this a base Resource declare it as abstract." if @model.nil?
627638
@model
628639
end
629640

@@ -675,7 +686,7 @@ def _add_relationship(klass, *attrs)
675686
check_reserved_relationship_name(attr)
676687

677688
# Initialize from an ActiveRecord model's properties
678-
if _model_class < ActiveRecord::Base
689+
if _model_class && _model_class < ActiveRecord::Base
679690
model_association = _model_class.reflect_on_association(attr)
680691
if model_association
681692
options[:class_name] ||= model_association.class_name

test/fixtures/active_record.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -648,7 +648,11 @@ class NumerosTelefoneController < JSONAPI::ResourceController
648648
end
649649

650650
### RESOURCES
651-
class PersonResource < JSONAPI::Resource
651+
class BaseResource < JSONAPI::Resource
652+
abstract
653+
end
654+
655+
class PersonResource < BaseResource
652656
attributes :id, :name, :email
653657
attribute :date_joined, format: :date_with_timezone
654658

test/unit/resource/resource_test.rb

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ def self.records(options)
1111
class NoMatchResource < JSONAPI::Resource
1212
end
1313

14+
class NoMatchAbstractResource < JSONAPI::Resource
15+
abstract
16+
end
17+
1418
class CatResource < JSONAPI::Resource
1519
attribute :id
1620
attribute :name
@@ -55,12 +59,25 @@ def test_model
5559
assert_equal(PostResource._model_class, Post)
5660
end
5761

62+
def test_base_resource_abstract
63+
assert BaseResource._abstract
64+
end
65+
66+
def test_derived_not_abstract
67+
assert PersonResource < BaseResource
68+
refute PersonResource._abstract
69+
end
70+
5871
def test_nil_model_class
59-
error = assert_raises(NameError) { NoMatchResource._model_class }
60-
assert_equal(
61-
error.message,
62-
"model could not be found for NoMatchResource"
63-
)
72+
assert_output nil, "[MODEL NOT FOUND] Model could not be found for NoMatchResource. If this a base Resource declare it as abstract.\n" do
73+
assert_nil NoMatchResource._model_class
74+
end
75+
end
76+
77+
def test_nil_abstract_model_class
78+
assert_output nil, '' do
79+
assert_nil NoMatchAbstractResource._model_class
80+
end
6481
end
6582

6683
def test_model_alternate

0 commit comments

Comments
 (0)