v3 is breaking existing behavior
kapso opened this issue ยท 6 comments
We have an attribute params
in our serializer, which has started breaking after v3 upgrade.
class NotificationSerializer < BaseSerializer
attributes :id
attributes :params # This causes an error in v3
# attribute :params, &:params # This works in v3
end
Error
/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/alba-3.0.0/lib/alba/resource.rb:268:in `_fetch_attribute_from_resource_first': wrong number of arguments (given 1, expected 0) (ArgumentError)
__send__(attribute, obj)
I am guessing params
is also an internal method, so its not a big deal, but I just wanted to flag it here.
Environment
- Ruby version: 3.2.2
- gem 'alba', '3.0.0'
- gem 'rails', '7.0.8'
Encountering a similar issue. Two things contribute to the problem:
- Alba now prefers methods on the resource, #323
- Alba uses
__send__
to dispatch the attribute call, which is capable of hitting private methods
Our scenario
We have a Rails model with a format
column. Ruby objects have a private format
method thanks to Kernel#format
.
To demonstrate all objects knowledge of private format
method
> Object.new.format("%.2f", 1) # private method `format' called for #<Object:0x0000000103fce3e8> (NoMethodError)
> Object.new.__send__(:format, "%.2f", 1) # => "1.00"
So the corresponding Alba::Resource
understands the format
call. Our particular failure is that our ActiveRecord object can't be coerced into the format string expected as the first argument of Kernel#format
.
I'm assuming Alba uses BasicObject#__send__
for a good reason (instead of Object#public_send
). So in our case the workaround is to leverage prefer_object_method!
on this particular resource.
@kapso As @atcruice mentioned, using prefer_object_method!
is a quick workaround for this issue. However, I don't think it's an ideal solution.
Methods Alba inherits from Object
class should not be treated as "resource method". In other words, only methods explicitly defined in the resource class should be "resource methods". That's possible with Ruby's method_added
hook, so I'll implement it soon.
@atcruice The reason behind using public
instead of public_send
was performance. public
is faster than public_send
.
So does using public_send
solve the problem? For format
method, yes. For params
, no because it's a public method.
So, although it's a good idea to use public_send
instead of __send__
here, some problems still remain.
I noticed v3
is not working for boolean
field. I confirmed it is working on v2.4
.
For boolean field, I got the follow error. Subscription is model.
TypeError: no implicit conversion of Subscription into Integer
@remy727 Could you submit another issue with reproduction code?
@okuramasafumi sure. I created #343