Skip to content

Commit 494e869

Browse files
committed
Rename associations to relationships.
Rename HasMany to ToMany and HasOne to ToOne. Brings the project more in line with the JSON API terminology. This will break existing code that uses callbacks or overrides some resource methods.
1 parent 4b39ded commit 494e869

25 files changed

Lines changed: 587 additions & 562 deletions

README.md

Lines changed: 60 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -212,11 +212,33 @@ class AuthorResource < JSONAPI::Resource
212212
end
213213
```
214214

215-
#### Associations
215+
#### Relationships
216216

217-
Related resources need to be specified in the resource. These are declared with the `has_one` and the `has_many` methods.
217+
Related resources need to be specified in the resource. These may be declared with the `relationship` or the `has_one`
218+
and the `has_many` methods.
218219

219-
Here's a simple example where a post has a single author and an author can have many posts:
220+
Here's a simple example using the `relationship` method where a post has a single author and an author can have many
221+
posts:
222+
223+
```ruby
224+
class PostResource < JSONAPI::Resource
225+
attribute :title, :body
226+
227+
relationship :author, to: :one
228+
end
229+
```
230+
231+
And the corresponding author:
232+
233+
```ruby
234+
class AuthorResource < JSONAPI::Resource
235+
attribute :name
236+
237+
relationship :posts, to: :many
238+
end
239+
```
240+
241+
And here's the equivalent resources using the `has_one` and `has_many` methods:
220242

221243
```ruby
222244
class PostResource < JSONAPI::Resource
@@ -238,15 +260,15 @@ end
238260

239261
##### Options
240262

241-
The association methods support the following options:
263+
The relationship methods (`relationship`, `has_one`, and `has_many`) support the following options:
242264

243265
* `class_name` - a string specifying the underlying class for the related resource
244266
* `foreign_key` - the method on the resource used to fetch the related resource. Defaults to `<resource_name>_id` for has_one and `<resource_name>_ids` for has_many relationships.
245267
* `acts_as_set` - allows the entire set of related records to be replaced in one operation. Defaults to false if not set.
246-
* `polymorphic` - set to true to identify associations that are polymorphic.
268+
* `polymorphic` - set to true to identify relationships that are polymorphic.
247269
* `relation_name` - the name of the relation to use on the model. A lambda may be provided which allows conditional selection of the relation based on the context.
248270

249-
`has_one` associations support the additional option:
271+
`to_one` relationships support the additional option:
250272
* `foreign_key_on` - defaults to `:self`. To indicate that the foreign key is on the related resource specify `:related`.
251273

252274
Examples:
@@ -291,7 +313,8 @@ class BookResource < JSONAPI::Resource
291313
end
292314
```
293315

294-
The polymorphic association will require the resource and controller to exist, although routing to them will cause an error.
316+
The polymorphic relationship will require the resource and controller to exist, although routing to them will cause an
317+
error.
295318

296319
```ruby
297320
class TaggableResource < JSONAPI::Resource; end
@@ -301,7 +324,8 @@ class TaggablesController < JSONAPI::ResourceController; end
301324
#### Filters
302325

303326
Filters for locating objects of the resource type are specified in the resource definition. Single filters can be
304-
declared using the `filter` method, and multiple filters can be declared with the `filters` method on the resource class.
327+
declared using the `filter` method, and multiple filters can be declared with the `filters` method on the resource
328+
class.
305329

306330
For example:
307331

@@ -314,7 +338,8 @@ class ContactResource < JSONAPI::Resource
314338
end
315339
```
316340

317-
Then a request could pass in a filter for example `http://example.com/contacts?filter[name_last]=Smith` and the system will find all people where the last name exactly matches Smith.
341+
Then a request could pass in a filter for example `http://example.com/contacts?filter[name_last]=Smith` and the system
342+
will find all people where the last name exactly matches Smith.
318343

319344
##### Default Filters
320345

@@ -360,7 +385,7 @@ end
360385
```
361386

362387
When you create a relationship, a method is created to fetch record(s) for that relationship. This method calls
363-
`records_for(association_name)` by default.
388+
`records_for(relationship_name)` by default.
364389

365390
```ruby
366391
class PostResource < JSONAPI::Resource
@@ -378,13 +403,13 @@ end
378403

379404
```
380405

381-
For example, you may want raise an error if the user is not authorized to view the associated records.
406+
For example, you may want raise an error if the user is not authorized to view the related records.
382407

383408
```ruby
384409
class BaseResource < JSONAPI::Resource
385-
def records_for(association_name, options={})
410+
def records_for(relationship_name, options={})
386411
context = options[:context]
387-
records = model.public_send(association_name)
412+
records = model.public_send(relationship_name)
388413

389414
unless context.current_user.can_view?(records)
390415
raise NotAuthorizedError
@@ -567,17 +592,17 @@ Callbacks can also be defined for `JSONAPI::OperationsProcessor` events:
567592
- `:operation`: Any individual operation.
568593
- `:find_operation`: A `find_operation`.
569594
- `:show_operation`: A `show_operation`.
570-
- `:show_association_operation`: A `show_association_operation`.
595+
- `:show_relationship_operation`: A `show_relationship_operation`.
571596
- `:show_related_resource_operation`: A `show_related_resource_operation`.
572597
- `:show_related_resources_operation`: A `show_related_resources_operation`.
573598
- `:create_resource_operation`: A `create_resource_operation`.
574599
- `:remove_resource_operation`: A `remove_resource_operation`.
575600
- `:replace_fields_operation`: A `replace_fields_operation`.
576-
- `:replace_has_one_association_operation`: A `replace_has_one_association_operation`.
577-
- `:create_has_many_association_operation`: A `create_has_many_association_operation`.
578-
- `:replace_has_many_association_operation`: A `replace_has_many_association_operation`.
579-
- `:remove_has_many_association_operation`: A `remove_has_many_association_operation`.
580-
- `:remove_has_one_association_operation`: A `remove_has_one_association_operation`.
601+
- `:replace_has_one_relationship_operation`: A `replace_has_one_relationship_operation`.
602+
- `:create_has_many_relationship_operation`: A `create_has_many_relationship_operation`.
603+
- `:replace_has_many_relationship_operation`: A `replace_has_many_relationship_operation`.
604+
- `:remove_has_many_relationship_operation`: A `remove_has_many_relationship_operation`.
605+
- `:remove_has_one_relationship_operation`: A `remove_has_one_relationship_operation`.
581606

582607
The operation callbacks have access to two meta data hashes, `@operations_meta` and `@operation_meta`, two links hashes,
583608
`@operations_links` and `@operation_links`, the full list of `@operations`, each individual `@operation` and the
@@ -878,7 +903,7 @@ An array of resources. Nested resources can be specified with dot notation.
878903
A hash of resource types and arrays of fields for each resource type.
879904

880905
*Purpose*: determines which fields are serialized for a resource type. This encompasses both attributes and
881-
association ids in the links section for a resource. Fields are global for a resource type.
906+
relationship ids in the links section for a resource. Fields are global for a resource type.
882907

883908
*Example*: ```fields: { people: [:email, :comments], posts: [:title, :author], comments: [:body, :post]}```
884909

@@ -907,7 +932,7 @@ JR has a couple of helper methods available to assist you with setting up routes
907932
##### `jsonapi_resources`
908933

909934
Like `resources` in `ActionDispatch`, `jsonapi_resources` provides resourceful routes mapping between HTTP verbs and URLs
910-
and controller actions. This will also setup mappings for relationship URLs for a resource's associations. For example:
935+
and controller actions. This will also setup mappings for relationship URLs for a resource's relationships. For example:
911936

912937
```ruby
913938
Rails.application.routes.draw do
@@ -920,20 +945,20 @@ gives the following routes
920945

921946
```
922947
Prefix Verb URI Pattern Controller#Action
923-
contact_relationships_phone_numbers GET /contacts/:contact_id/relationships/phone-numbers(.:format) contacts#show_association {:association=>"phone_numbers"}
924-
POST /contacts/:contact_id/relationships/phone-numbers(.:format) contacts#create_association {:association=>"phone_numbers"}
925-
DELETE /contacts/:contact_id/relationships/phone-numbers/:keys(.:format) contacts#destroy_association {:association=>"phone_numbers"}
926-
contact_phone_numbers GET /contacts/:contact_id/phone-numbers(.:format) phone_numbers#get_related_resources {:association=>"phone_numbers", :source=>"contacts"}
948+
contact_relationships_phone_numbers GET /contacts/:contact_id/relationships/phone-numbers(.:format) contacts#show_relationship {:relationship=>"phone_numbers"}
949+
POST /contacts/:contact_id/relationships/phone-numbers(.:format) contacts#create_relationship {:relationship=>"phone_numbers"}
950+
DELETE /contacts/:contact_id/relationships/phone-numbers/:keys(.:format) contacts#destroy_relationship {:relationship=>"phone_numbers"}
951+
contact_phone_numbers GET /contacts/:contact_id/phone-numbers(.:format) phone_numbers#get_related_resources {:relationship=>"phone_numbers", :source=>"contacts"}
927952
contacts GET /contacts(.:format) contacts#index
928953
POST /contacts(.:format) contacts#create
929954
contact GET /contacts/:id(.:format) contacts#show
930955
PATCH /contacts/:id(.:format) contacts#update
931956
PUT /contacts/:id(.:format) contacts#update
932957
DELETE /contacts/:id(.:format) contacts#destroy
933-
phone_number_relationships_contact GET /phone-numbers/:phone_number_id/relationships/contact(.:format) phone_numbers#show_association {:association=>"contact"}
934-
PUT|PATCH /phone-numbers/:phone_number_id/relationships/contact(.:format) phone_numbers#update_association {:association=>"contact"}
935-
DELETE /phone-numbers/:phone_number_id/relationships/contact(.:format) phone_numbers#destroy_association {:association=>"contact"}
936-
phone_number_contact GET /phone-numbers/:phone_number_id/contact(.:format) contacts#get_related_resource {:association=>"contact", :source=>"phone_numbers"}
958+
phone_number_relationships_contact GET /phone-numbers/:phone_number_id/relationships/contact(.:format) phone_numbers#show_relationship {:relationship=>"contact"}
959+
PUT|PATCH /phone-numbers/:phone_number_id/relationships/contact(.:format) phone_numbers#update_relationship {:relationship=>"contact"}
960+
DELETE /phone-numbers/:phone_number_id/relationships/contact(.:format) phone_numbers#destroy_relationship {:relationship=>"contact"}
961+
phone_number_contact GET /phone-numbers/:phone_number_id/contact(.:format) contacts#get_related_resource {:relationship=>"contact", :source=>"phone_numbers"}
937962
phone_numbers GET /phone-numbers(.:format) phone_numbers#index
938963
POST /phone-numbers(.:format) phone_numbers#create
939964
phone_number GET /phone-numbers/:id(.:format) phone_numbers#show
@@ -998,9 +1023,9 @@ end
9981023
Gives the following routes:
9991024

10001025
```
1001-
contact_relationships_phone_numbers GET /contacts/:contact_id/relationships/phone-numbers(.:format) contacts#show_association {:association=>"phone_numbers"}
1002-
POST /contacts/:contact_id/relationships/phone-numbers(.:format) contacts#create_association {:association=>"phone_numbers"}
1003-
DELETE /contacts/:contact_id/relationships/phone-numbers/:keys(.:format) contacts#destroy_association {:association=>"phone_numbers"}
1026+
contact_relationships_phone_numbers GET /contacts/:contact_id/relationships/phone-numbers(.:format) contacts#show_relationship {:relationship=>"phone_numbers"}
1027+
POST /contacts/:contact_id/relationships/phone-numbers(.:format) contacts#create_relationship {:relationship=>"phone_numbers"}
1028+
DELETE /contacts/:contact_id/relationships/phone-numbers/:keys(.:format) contacts#destroy_relationship {:relationship=>"phone_numbers"}
10041029
contacts GET /contacts(.:format) contacts#index
10051030
POST /contacts(.:format) contacts#create
10061031
contact GET /contacts/:id(.:format) contacts#show
@@ -1010,7 +1035,7 @@ contact_relationships_phone_numbers GET /contacts/:contact_id/relationships/p
10101035
10111036
```
10121037

1013-
The new routes allow you to show, create and destroy the associations between resources.
1038+
The new routes allow you to show, create and destroy the relationships between resources.
10141039

10151040
###### `jsonapi_related_resources`
10161041

@@ -1029,7 +1054,7 @@ gives the following routes:
10291054

10301055
```
10311056
Prefix Verb URI Pattern Controller#Action
1032-
contact_phone_numbers GET /contacts/:contact_id/phone-numbers(.:format) phone_numbers#get_related_resources {:association=>"phone_numbers", :source=>"contacts"}
1057+
contact_phone_numbers GET /contacts/:contact_id/phone-numbers(.:format) phone_numbers#get_related_resources {:relationship=>"phone_numbers", :source=>"contacts"}
10331058
contacts GET /contacts(.:format) contacts#index
10341059
POST /contacts(.:format) contacts#create
10351060
contact GET /contacts/:id(.:format) contacts#show
@@ -1057,7 +1082,7 @@ gives the following routes:
10571082

10581083
```
10591084
Prefix Verb URI Pattern Controller#Action
1060-
phone_number_contact GET /phone-numbers/:phone_number_id/contact(.:format) contacts#get_related_resource {:association=>"contact", :source=>"phone_numbers"}
1085+
phone_number_contact GET /phone-numbers/:phone_number_id/contact(.:format) contacts#get_related_resource {:relationship=>"contact", :source=>"phone_numbers"}
10611086
phone_numbers GET /phone-numbers(.:format) phone_numbers#index
10621087
POST /phone-numbers(.:format) phone_numbers#create
10631088
phone_number GET /phone-numbers/:id(.:format) phone_numbers#show

lib/jsonapi-resources.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
require 'jsonapi/request'
1616
require 'jsonapi/operations_processor'
1717
require 'jsonapi/active_record_operations_processor'
18-
require 'jsonapi/association'
18+
require 'jsonapi/relationship'
1919
require 'jsonapi/include_directives'
2020
require 'jsonapi/operation_result'
2121
require 'jsonapi/operation_results'

lib/jsonapi/acts_as_resource_controller.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ module ActsAsResourceController
55
extend ActiveSupport::Concern
66

77
included do
8-
before_filter :ensure_correct_media_type, only: [:create, :update, :create_association, :update_association]
8+
before_filter :ensure_correct_media_type, only: [:create, :update, :create_relationship, :update_relationship]
99
append_before_filter :setup_request
1010
after_filter :setup_response
1111
end
@@ -18,19 +18,19 @@ def show
1818
process_request_operations
1919
end
2020

21-
def show_association
21+
def show_relationship
2222
process_request_operations
2323
end
2424

2525
def create
2626
process_request_operations
2727
end
2828

29-
def create_association
29+
def create_relationship
3030
process_request_operations
3131
end
3232

33-
def update_association
33+
def update_relationship
3434
process_request_operations
3535
end
3636

@@ -42,7 +42,7 @@ def destroy
4242
process_request_operations
4343
end
4444

45-
def destroy_association
45+
def destroy_relationship
4646
process_request_operations
4747
end
4848

lib/jsonapi/exceptions.rb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,12 @@ def errors
7373
end
7474
end
7575

76-
class HasManySetReplacementForbidden < Error
76+
class ToManySetReplacementForbidden < Error
7777
def errors
7878
[JSONAPI::Error.new(code: JSONAPI::FORBIDDEN,
7979
status: :forbidden,
8080
title: 'Complete replacement forbidden',
81-
detail: 'Complete replacement forbidden for this association')]
81+
detail: 'Complete replacement forbidden for this relationship')]
8282
end
8383
end
8484

@@ -188,17 +188,17 @@ def errors
188188
end
189189

190190
class InvalidInclude < Error
191-
attr_accessor :association, :resource
192-
def initialize(resource, association)
191+
attr_accessor :relationship, :resource
192+
def initialize(resource, relationship)
193193
@resource = resource
194-
@association = association
194+
@relationship = relationship
195195
end
196196

197197
def errors
198198
[JSONAPI::Error.new(code: JSONAPI::INVALID_INCLUDE,
199199
status: :bad_request,
200200
title: 'Invalid field',
201-
detail: "#{association} is not a valid association of #{resource}")]
201+
detail: "#{relationship} is not a valid relationship of #{resource}")]
202202
end
203203
end
204204

lib/jsonapi/link_builder.rb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ def query_link(query_params)
3131
"#{ primary_resources_url }?#{ query_params.to_query }"
3232
end
3333

34-
def relationships_related_link(source, association)
35-
"#{ self_link(source) }/#{ route_for_association(association) }"
34+
def relationships_related_link(source, relationship)
35+
"#{ self_link(source) }/#{ route_for_relationship(relationship) }"
3636
end
3737

38-
def relationships_self_link(source, association)
39-
"#{ self_link(source) }/relationships/#{ route_for_association(association) }"
38+
def relationships_self_link(source, relationship)
39+
"#{ self_link(source) }/relationships/#{ route_for_relationship(relationship) }"
4040
end
4141

4242
def self_link(source)
@@ -134,8 +134,8 @@ def regular_resource_url(source)
134134
"#{ base_url }#{ regular_resource_path(source) }"
135135
end
136136

137-
def route_for_association(association)
138-
format_route(association.name)
137+
def route_for_relationship(relationship)
138+
format_route(relationship.name)
139139
end
140140
end
141141
end

0 commit comments

Comments
 (0)