active_model_serializers
active_model_serializers copied to clipboard
Execution context when using a block for `has_one` vs `attribute`
Expected behavior vs actual behavior
Expected the execution context (self) to be the same when using something like has_one :something do as it is with attribute :something do. Maybe this is by design but it seems unusual.
This discovery came about as a result of trying to access instance_options which seems to not be possible (see Additional information)
Steps to reproduce
Given
class TestSerializer < ActiveModel::Serializer
attribute :attr do
self.class.name
end
has_one :child do
{ class: self.class.name }
end
end
test output is
> TestSerializer.new(self).as_json
=> {:attr=>"TestSerializer", :child=>{:class=>"ActiveModel::Serializer::HasOneReflection"}}
Environment
ActiveModelSerializers Version: v0.10.10
Output of ruby -e "puts RUBY_DESCRIPTION": ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-linux]
OS Type & Version: Linux Mint 20.1
Integrated application and version (e.g., Rails, Grape, etc): Rails 6.0
Additional helpful information
The following syntax doesn't work either as instance_options is protected
has_one :h do |serializer|
if serializer.instance_options[:include_all]
...
end
Thanks for your report. What are you trying to do?
In this case I was trying to access the instance_options, but it is confusing that the methods act differently
well, attributes are on the object so don't need to be handled by a reflection like relations do.
I had thought you could yield the serializer instance to get access to that stuff. it's been a while since I've been in the code and I'm assuming you've read through the docs and code at this point, so I might be wrong.
The serializer is yielded but you can't access instance_options since its protected.
Some options I can think of are:
- Expose instance_options in the reflection (this is already done for scope and object)
- Make instance_options public on the serializer
- Have the reflection delegate to serializer so you get the best of both worlds (including methods you define yourself on the serializer)
fwiw, the work-around is just to use a method instead of a block