Skip to content

Commit 9fa26fa

Browse files
committed
Allow block for id customization
Allow an ID of object to be customized directly on the serializer by passing a block to `set_id` as opposed to only through a model property. We already allow for attributes that do not have a model property of the same name to be customized directly on the serializer using a block. This customization can be useful in situation in which you have different classes being serialized using the same serializer. For example, if we have `HorrorMovie`, `ComedyMovie` and `DramaMovie` using the same `MovieSerializer`, we can unify their IDs using ``` class MovieSerializer include FastJsonapi::ObjectSerializer attributes :name, :year set_id do |record| "#{record.name.downcase}-#{record.id}" end ``` which is preferable to creating a `#serialized_id` method in every model that will use `MovieSerializer` to encapsulate the customization. Closes #315
1 parent 11b5255 commit 9fa26fa

3 files changed

Lines changed: 50 additions & 20 deletions

File tree

lib/fast_jsonapi/object_serializer.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,8 @@ def set_type(type_name)
167167
self.record_type = run_key_transform(type_name)
168168
end
169169

170-
def set_id(id_name)
171-
self.record_id = id_name
170+
def set_id(id_name = nil, &block)
171+
self.record_id = block || id_name
172172
end
173173

174174
def cache_options(cache_options)

lib/fast_jsonapi/serialization_core.rb

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,10 @@ def record_hash(record, fieldset, params = {})
8686
end
8787

8888
def id_from_record(record)
89-
return record.send(record_id) if record_id
90-
raise MandatoryField, 'id is a mandatory field in the jsonapi spec' unless record.respond_to?(:id)
91-
record.id
89+
return record_id.call(record) if record_id.is_a?(Proc)
90+
return record.send(record_id) if record_id
91+
raise MandatoryField, 'id is a mandatory field in the jsonapi spec' unless record.respond_to?(:id)
92+
record.id
9293
end
9394

9495
# Override #to_json for alternative implementation

spec/lib/object_serializer_class_methods_spec.rb

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -195,28 +195,57 @@
195195
describe '#set_id' do
196196
subject(:serializable_hash) { MovieSerializer.new(resource).serializable_hash }
197197

198-
before do
199-
MovieSerializer.set_id :owner_id
200-
end
198+
context 'method name' do
199+
before do
200+
MovieSerializer.set_id :owner_id
201+
end
201202

202-
after do
203-
MovieSerializer.set_id nil
204-
end
203+
after do
204+
MovieSerializer.set_id nil
205+
end
206+
207+
context 'when one record is given' do
208+
let(:resource) { movie }
209+
210+
it 'returns correct hash which id equals owner_id' do
211+
expect(serializable_hash[:data][:id].to_i).to eq movie.owner_id
212+
end
213+
end
205214

206-
context 'when one record is given' do
207-
let(:resource) { movie }
215+
context 'when an array of records is given' do
216+
let(:resource) { [movie, movie] }
208217

209-
it 'returns correct hash which id equals owner_id' do
210-
expect(serializable_hash[:data][:id].to_i).to eq movie.owner_id
218+
it 'returns correct hash which id equals owner_id' do
219+
expect(serializable_hash[:data][0][:id].to_i).to eq movie.owner_id
220+
expect(serializable_hash[:data][1][:id].to_i).to eq movie.owner_id
221+
end
211222
end
212223
end
213224

214-
context 'when an array of records is given' do
215-
let(:resource) { [movie, movie] }
225+
context 'with block' do
226+
before do
227+
MovieSerializer.set_id { |record| "movie-#{record.owner_id}" }
228+
end
229+
230+
after do
231+
MovieSerializer.set_id nil
232+
end
216233

217-
it 'returns correct hash which id equals owner_id' do
218-
expect(serializable_hash[:data][0][:id].to_i).to eq movie.owner_id
219-
expect(serializable_hash[:data][1][:id].to_i).to eq movie.owner_id
234+
context 'when one record is given' do
235+
let(:resource) { movie }
236+
237+
it 'returns correct hash which id equals movie-id' do
238+
expect(serializable_hash[:data][:id]).to eq "movie-#{movie.owner_id}"
239+
end
240+
end
241+
242+
context 'when an array of records is given' do
243+
let(:resource) { [movie, movie] }
244+
245+
it 'returns correct hash which id equals movie-id' do
246+
expect(serializable_hash[:data][0][:id]).to eq "movie-#{movie.owner_id}"
247+
expect(serializable_hash[:data][1][:id]).to eq "movie-#{movie.owner_id}"
248+
end
220249
end
221250
end
222251
end

0 commit comments

Comments
 (0)