-
Notifications
You must be signed in to change notification settings - Fork 87
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
Fix AM/AR::Dirty plugin compatibility issues with AR 5.2 #115
Comments
We may need to consider changing from tracking dirty changes on attribute locale accessors, to tracking changes on the attributes themselves. i.e., instead of what we do currently: post.title_changes
#=> { "title_en" => [nil, "foo"], "content_en" => [nil, "bar"]} we would have: post.title_changes
#=> { "title" => [nil, "foo"], "content" => [nil, "bar"]} This is, incidentally, what Globalize does. I opted to go with localized accessors so that Mobility could track the full set of locale-specific changes on translated attributes, i.e. if you change the title in English and in French, you will see each change separately. I prefer this approach, but we're running up against problems with how AR is increasingly trying to force everything to specify attribute names upfront, whereas localized names are open-ended (in general, we don't want to assume a set of predefined locales). That said, currently the dirty plugin depends on fallthrough accessors to actually fetch the localized values of attributes, which uses |
There currently seems to be three ways to specify locale accessors:
Unless I'm missing something, in case 1 and 2, we could explicitly declare the attributes. So the challenging case to handle is 3. In my case, my app only supports Japanese and English, and am using the locale specific accessors. I'd have no problem with being required to declare them up front. The case where you don't want to declare them up front is where your app supports arbitrary translation. In this case, you don't know up front which locales your going to need to support, so you can't declare them. Similarly though, if you don't know what locales your app is going to use, you probably aren't going to be using locale specific accessors for the same reason. Instead, you'd be setting the attribute either implicitly via the current locale ( This leads me to wonder if there really is a use case that would require someone to use |
You're right that it's an edge case we might not want to put too much emphasis on. I guess I like the design of having both fallthrough + explicit locales, whereby you can define explicit locales and yet still fallthrough to any locale. A use case for this is for example, your app supports mainly a small set of locales, which you set explicitly, but you also want to allow support for new locales organically, perhaps with a performance hit at first. In the case of the Dirty plugin, fallthrough was (I thought) a nice way to allow the plugin to be used without requiring the user to explicitly specify the locales they want to support upfront (it will work with or without them). If we did not have fallthrough accessors, I suppose what we would be able to do would be in So I'm not really happy with this. The annoying thing is that everything works fine for ActiveModel, since AM still simply calls |
But do we need explicit accessors for these organic locales? If your app isn't doing something explicitly with Portuguese (for instance), why would you have code like
Agreed that we don't want to require users to explicitly specify locales to do dirty tracking. |
So here's one solution: 9b55ccf What I do is to first check if This is not a solution yet - we're checking the regex once, then calling the method, which (if no method is defined for that locale accessor) will go to So... need to think about this more I guess. |
Ah I see, so your point is that we could support open-ended locales, just without supporting explicit locale accessors. That's a good point, and in that case I think it would be natural that you can use the Dirty plugin for locales you want to track, but not for the implicit ones. |
I'm leaning toward leaving fallthrough accessors as a plugin, but making Dirty require a fixed set of locales (from the union of |
Context
ActiveRecord 5.2.beta.2 has just been released, and we are now testing against it (see #112). There are about twenty specs failing currently, mostly around the Dirty plugin.
The main issue seems to be with rails/rails#28661 (fixing rails/rails#28660), which replaced a
__send__(attr)
to_attributes(attr)
, and ultimately to_read_attribute(attr)
. This is problematic since while in ActiveModel_read_attribute
simply maps to__send__
, which for a localized accessor liketitle_en
will correctly return the current value of the title, in AR it maps to this:Here,
@attributes
will not contain the localized translated attributes, sotitle_en
here will returnnil
. So most of the AR::Dirty specs are failing with changes all coming out as[nil, nil]
instead of e.g.[nil, "foo"]
.Possible Fix
I'm currently investigating if we could override
_read_attribute
to do something special for translated attributes, but it's tricky because in the dirty plugin we're using localized attributes to track changes in multiple locales. This is tricky since without a complex regex, we can't really tell if a given attribute passed to_read_attribute
is actually a translated attribute or not.I don't want to be matching regexes every time
_read_attribute
is called since this is a very frequently-used method and regexes are slow, so this could significantly impact performance. For now just tracking the problem here, I'll see if there are other ways to fix the problem.The text was updated successfully, but these errors were encountered: