Skip to content

Commit ea5296a

Browse files
committed
making object level links similar to attributes
1 parent 74f27cc commit ea5296a

6 files changed

Lines changed: 63 additions & 28 deletions

File tree

README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,31 @@ class MovieSerializer
205205
end
206206
```
207207

208+
### Links Per Object
209+
Links are defined in FastJsonapi using the `link` method. By default, link are read directly from the model property of the same name.In this example, `public_url` is expected to be a property of the object being serialized.
210+
211+
You can configure the method to use on the object for example a link with key `self` will get set to the value returned by a method called `url` on the movie object.
212+
213+
You can also use a block to define a url as shown in `custom_url`. You can access params in these blocks as well as shown in `personalized_url`
214+
215+
```ruby
216+
class MovieSerializer
217+
include FastJsonapi::ObjectSerializer
218+
219+
link :public_url
220+
221+
link :self, :url
222+
223+
link :custom_url do |object|
224+
"http://movies.com/#{object.name}-(#{object.year})"
225+
end
226+
227+
link :personalized_url do |object, params|
228+
"http://movies.com/#{object.name}-#{params[:user].reference_code}"
229+
end
230+
end
231+
```
232+
208233
### Compound Document
209234

210235
Support for top-level and nested included associations through ` options[:include] `.

lib/fast_jsonapi/object_serializer.rb

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def hash_for_one_record
3838

3939
return serializable_hash unless @resource
4040

41-
serializable_hash[:data] = self.class.record_hash(@resource, @params, self)
41+
serializable_hash[:data] = self.class.record_hash(@resource, @params)
4242
serializable_hash[:included] = self.class.get_included_records(@resource, @includes, @known_included_objects, @params) if @includes.present?
4343
serializable_hash
4444
end
@@ -49,7 +49,7 @@ def hash_for_collection
4949
data = []
5050
included = []
5151
@resource.each do |record|
52-
data << self.class.record_hash(record, @params, self)
52+
data << self.class.record_hash(record, @params)
5353
included.concat self.class.get_included_records(record, @includes, @known_included_objects, @params) if @includes.present?
5454
end
5555

@@ -229,9 +229,11 @@ def fetch_polymorphic_option(options)
229229
{}
230230
end
231231

232-
def link(name, value = nil, &block)
233-
self.data_links = {} unless data_links
234-
self.data_links[name] = block || value
232+
def link(link_name, link_method_name = nil, &block)
233+
self.data_links = {} if self.data_links.nil?
234+
link_method_name = link_name if link_method_name.nil?
235+
key = run_key_transform(link_name)
236+
self.data_links[key] = block || link_method_name
235237
end
236238

237239
def validate_includes!(includes)

lib/fast_jsonapi/serialization_core.rb

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,13 @@ def ids_hash_from_record_and_relationship(record, relationship, params = {})
6262
id_hash_from_record associated_object, polymorphic
6363
end
6464

65-
def links_hash(record, serializer_instance)
66-
@data_links.each_with_object({}) do |(key, method), link_hash|
67-
link_hash[key] = method.is_a?(Proc) ? serializer_instance.instance_exec(record, &method) : record.public_send(method)
65+
def links_hash(record, params = {})
66+
data_links.each_with_object({}) do |(key, method), link_hash|
67+
link_hash[key] = if method.is_a?(Proc)
68+
method.arity == 1 ? method.call(record) : method.call(record, params)
69+
else
70+
record.public_send(method)
71+
end
6872
end
6973
end
7074

@@ -90,17 +94,14 @@ def relationships_hash(record, relationships = nil, params = {})
9094
end
9195
end
9296

93-
def record_hash(record, params = {}, serializer_instance)
97+
def record_hash(record, params = {})
9498
if cached
9599
record_hash = Rails.cache.fetch(record.cache_key, expires_in: cache_length, race_condition_ttl: race_condition_ttl) do
96100
temp_hash = id_hash(id_from_record(record), record_type, true)
97101
temp_hash[:attributes] = attributes_hash(record, params) if attributes_to_serialize.present?
98102
temp_hash[:relationships] = {}
99103
temp_hash[:relationships] = relationships_hash(record, cachable_relationships_to_serialize, params) if cachable_relationships_to_serialize.present?
100-
if @data_links.present?
101-
temp_links_hash = links_hash(record, serializer_instance)
102-
temp_hash[:links] = temp_links_hash if temp_links_hash
103-
end
104+
temp_hash[:links] = links_hash(record, params) if data_links.present?
104105
temp_hash
105106
end
106107
record_hash[:relationships] = record_hash[:relationships].merge(relationships_hash(record, uncachable_relationships_to_serialize, params)) if uncachable_relationships_to_serialize.present?
@@ -109,10 +110,7 @@ def record_hash(record, params = {}, serializer_instance)
109110
record_hash = id_hash(id_from_record(record), record_type, true)
110111
record_hash[:attributes] = attributes_hash(record, params) if attributes_to_serialize.present?
111112
record_hash[:relationships] = relationships_hash(record, nil, params) if relationships_to_serialize.present?
112-
if @data_links.present?
113-
temp_links_hash = links_hash(record, serializer_instance)
114-
record_hash[:links] = temp_links_hash if temp_links_hash
115-
end
113+
record_hash[:links] = links_hash(record, params) if data_links.present?
116114
record_hash
117115
end
118116
end
@@ -168,7 +166,7 @@ def get_included_records(record, includes_list, known_included_objects, params =
168166
next if known_included_objects.key?(code)
169167

170168
known_included_objects[code] = inc_obj
171-
included_records << serializer.record_hash(inc_obj, params, serializer.new(record))
169+
included_records << serializer.record_hash(inc_obj, params)
172170
end
173171
end
174172
end

spec/lib/object_serializer_class_methods_spec.rb

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@
243243
context 'with block calling instance method on serializer' do
244244
before do
245245
MovieSerializer.link(:self) do |movie_object|
246-
movie_url(movie_object)
246+
movie_object.url
247247
end
248248
end
249249
let(:url) { "http://movies.com/#{movie.id}" }
@@ -275,6 +275,16 @@
275275
expect(serializable_hash[:data][:links][:object_id]).to eq movie.id
276276
end
277277
end
278+
279+
context 'with method and convention' do
280+
before do
281+
MovieSerializer.link(:url)
282+
end
283+
284+
it 'returns correct hash when serializable_hash is called' do
285+
expect(serializable_hash[:data][:links][:url]).to eq movie.url
286+
end
287+
end
278288
end
279289

280290
describe '#key_transform' do

spec/lib/object_serializer_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ class BlahSerializer
287287
context 'when serializing included, serialize any links' do
288288
before do
289289
ActorSerializer.link(:self) do |actor_object|
290-
actor_url(actor_object)
290+
actor_object.url
291291
end
292292
end
293293
subject(:serializable_hash) do

spec/shared/contexts/movie_context.rb

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ def advertising_campaign
4242
def cache_key
4343
"#{id}"
4444
end
45+
46+
def url
47+
"http://movies.com/#{id}"
48+
end
4549
end
4650

4751
class Actor
@@ -68,6 +72,10 @@ def awards
6872
def award_ids
6973
[id * 9, id * 9 + 1]
7074
end
75+
76+
def url
77+
"http://movies.com/actors/#{id}"
78+
end
7179
end
7280

7381
class AdvertisingCampaign
@@ -144,10 +152,6 @@ class MovieSerializer
144152
belongs_to :owner, record_type: :user
145153
belongs_to :movie_type
146154
has_one :advertising_campaign
147-
148-
def movie_url(movie)
149-
"http://movies.com/#{movie.id}"
150-
end
151155
end
152156

153157
class MovieWithoutIdStructSerializer
@@ -184,10 +188,6 @@ class ActorSerializer
184188
belongs_to :agency
185189
has_many :awards
186190
belongs_to :agency
187-
188-
def actor_url(actor)
189-
"http://movies.com/actors/#{actor.id}"
190-
end
191191
end
192192

193193
class AgencySerializer

0 commit comments

Comments
 (0)