I have a model model
, and am trying to render that with as_json
. I am calling the :methods
option on it like this:
model.as_json(methods: [:foo, :bar])
The output includes a key-value pair for the method foo
, but not for bar
. It might be the case that bar
is not defined correctly while foo
is not, I am not sure.
In such case, would as_json
silently ignore the application of the undefined methods? If so, is there a way to be notified by an error? Or, could there be any other reason that particular key-value pairs become silently ignored from the as_json
output?
I am using Active Model 4.2.7.
An option is override as_json
method in your model. Here you have to check if the methods are available in your model, if the method is not defined, remove it from options and do some notify action. This way the not available methods will be ignored.
An approximation code would be
class Model < ApplicationRecord
def as_json(options = {})
if options.key? :methods
if options[:methods].is_a? Array
methods_copy = options[:methods].clone
methods_copy.each do |opt|
if !self.respond_to? opt
# do notify, log, etc
options[:methods].delete opt
end
end
elsif options[:methods].is_a? Symbol
if !self.respond_to? options[:methods]
# do notify, log, etc
options.delete :methods
end
else
# do some actions here
end
end
super(options)
end
end
Then call as_json
as usual
model.as_json(methods: [:foo, :bar])
UPDATE
As I misread the question, here an update based on the answer of @sawa
Older versions of ActiveModel don't notify when some method is not defined when methods
options is passed.
Upgrading the above code
def as_json(options = {})
Array(options[:methods]).each do |m|
raise "method #{m} doesn't exists" if !self.respond_to?(m)
end
super(options)
end
Methods included in as_json
must be public methods. If bar
is a private method, it will not be included.
This situation is a subset of the responds_to?
issue mentioned in @sawa's answer , and is probably resolved by the same commit linked in the answer.
In such case, would
as_json
silently ignore the application of the undefined methods?
Yes in older versions of active model, and no since a certain version. To be more precise with older versions of active model, it is not the case that undefined methods are ignored; what are ignored are methods that do not return a truthy value to respond_to?
. In the code at: https://github.com/rails/rails/blob/master/activemodel/lib/active_model/serialization.rb
, there used to be a line:
Array(options[:methods]).each { |m| hash[m.to_s] = send(m) if respond_to?(m) }
where hash
is the output of this method. Methods specified by the :methods
option were ignored when they did not respond. However, this change altered the corresponding line into:
Array(options[:methods]).each { |m| hash[m.to_s] = send(m) }
which raises a method missing error when the method is not defined.
If so, is there a way to be notified by an error?
The easiest way is to update the active model to at least later than the commit mentioned above.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.