Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make compatible with Mobility translation gem #34

Closed
wants to merge 1 commit into from

Conversation

jmuheim
Copy link

@jmuheim jmuheim commented Sep 17, 2017

https://github.com/shioyama/mobility/ is a very nice translation gem. Sadly it doesn't play well with strip_attributes. This little change fixes it. Tests pass. All fine in my opinion.

See shioyama/mobility#97.

@rmm5t
Copy link
Owner

rmm5t commented Sep 17, 2017

I'm not too keen on this. Can you please explain why this isn't a bug in the mobility gem?

Strip attributes wasn't doing anything that any ActiveRecord library might do. I.e. Strip attributes is just adhering to the ActiveRecord interface for writing attributes.

What am I missing?

@jmuheim
Copy link
Author

jmuheim commented Sep 17, 2017

@shioyama, what do you think about this?

@rmm5t
Copy link
Owner

rmm5t commented Sep 18, 2017

Further reference material showing ActiveRecord's []= alias for write_attribute:
http://api.rubyonrails.org/classes/ActiveRecord/AttributeMethods.html#method-i-5B-5D-3D

Feel free to chime in with more information about why you think strip_attributes is at fault here, but for now, I'm closing this PR.

@rmm5t rmm5t closed this Sep 18, 2017
@shioyama
Copy link

Sorry I'm actually at RubyKaigi right now preparing for a talk, haven't had time to respond. I don't necessarily think this is the fault of strip_attributes, so no issue with closing this, but I will explain what the issue is later when I have a chance.

@jmuheim
Copy link
Author

jmuheim commented Sep 9, 2019

Any news on this? I'm still using my own fork to circumvent this problem. It would be nice to switch back to the official gem again.

@shioyama
Copy link

shioyama commented Sep 9, 2019

I'm not planning to do anything about this since I don't consider it a bug (either in this gem or in Mobility).

Translated attributes are not attributes, technically. They are mappings to attributes stored in different places. If I go ahead and override [], []= etc to make this stuff work, it will simply trigger more problems down the line. (I've experienced this in Globalize and it's not something I want to repeat).

Bottom line: there is no bug here. strip_attributes is a gem for stripping whitespace from ActiveModel attributes, but the translations in Mobility are not technically ActiveModel attributes, so the two won't play well together by default.

However, I will point out that strip_attributes would be more useful outside of the ActiveRecord/ActiveModel world if it worked off the more generic getter/setter methods (foo/foo=) rather than the (AR/AM-specific) getter/setter methods ([]/[]=). But maybe there are other considerations for why that's not a good idea; I don't know the code well enough to say.

@rmm5t
Copy link
Owner

rmm5t commented Sep 9, 2019

Yeah, strip_attributes has been around for a while now, and when I first wrote it, different conventions existed in Rails than they do now. Also, there are newer API endpoints that can now be considered too.

e.g. I might consider using the new attributes API instead of a before_validation callback.

class Strippable < ActiveRecord::Type::String
  def cast_value(value)
    value.to_s.strip
  end
end

class Something < ActiveRecord::Base
  attribute :title, Strippable
end

@shioyama
Copy link

shioyama commented Sep 9, 2019

The attributes API is great for stuff like value types, etc. but for something like just stripping whitespace wouldn't just basing off a basic getter/setter API work? I mean, override foo and foo= and super up, with whitespace stripped. Then any application could use the gem, whether or not it uses Rails.

@rmm5t
Copy link
Owner

rmm5t commented Sep 9, 2019

@shioyama All valid things to consider, and I will consider that when I later look into this.

This gem is already dependent on ActiveModel, because it can automatically inspect for all possible attributes on the model. I’d like to maintain that behavior regardless.

It’s possible that custom types is a bad idea, because it might prevent an application from defining their own custom types unless they were willing to inherit from some Strippable type. That would give a nod more to the overridden setters, but overridden setters won’t handle assignment while using write_attribute.

@shioyama
Copy link

Actually, rethinking this, I think you're probably right to use write_attribute, etc. I wish ActiveModel were more flexible but I think given how the attributes API works, and given your use cases, I would say you're doing it correctly.

@jrochkind
Copy link

jrochkind commented Jan 5, 2023

jsonb_accessor and attr_json are two gems that provide alternate implementations to have activerecord attributes that really serialize to keys in a json column.

strip_attributes does not work with either one as is -- but would if it used record.send "#{attr}=" instead of record[attr] =, as above.

(Some of the commentary above talks about "ActiveModel attributes" -- but really strip_attributes as it is only works with ActiveRecord attributes specifically. You can create classes with ActiveModel::Model and/or the newer ActiveModel::Attributes, which won't have []= or write_attribute methods at all, these aren't part of the ActiveModel suite of API's, they are an ActiveRecord thing. Of course, ActiveModel's may not have before_validation callbacks anyway, so. )

@gerardo-navarro
Copy link

I also stumbles across this problem. I can only support the statements made by other comments. 👍 I think that this could be a good addition for the gem as suggested by the others.

In this case, I did not need a full-fledged ActiveRecord model and just used an ActiveModel object, see below.

class InitialOffer
  include ActiveModel::Model
  include ActiveModel::Attributes # <= this is needed to make the method `#attributes` available
  include ActiveModel::Validations::Callbacks # as explained in the README this is needed to run the validation

  attribute :attr1
  attribute :attr2

  strip_attributes only: %i[
    attr1
    attr2
  ]
end

When providing a value with just whitespaces then it crashes because strip_attributes would convert blank values to nil by default.

InitialOffer.new(attr1: "      ").validate

This leads to the following error

/home/app/.gem/3.2.0/gems/activemodel-7.0.8/lib/active_model/attribute_methods.rb:450:in `method_missing': undefined method `[]=' for #<InitialOffer:0x0000ffff720ec230 ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants