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

Query with fallbacks #51

Closed
shioyama opened this issue Jul 8, 2017 · 13 comments
Closed

Query with fallbacks #51

shioyama opened this issue Jul 8, 2017 · 13 comments
Labels

Comments

@shioyama
Copy link
Owner

shioyama commented Jul 8, 2017

i.e.

Mobility.locale = :en
Post.i18n.where(title: "foo")

...should return the post with title "foo" in English if a post with title in English exists, if not it should find a post with title "foo" in one of the fallback locales defined for the title attributes.

Ref: shioyama/friendly_id-mobility#4

@shioyama
Copy link
Owner Author

So I've looked into this a bit today, and I think before doing anything like this it might be good to take a few steps back and think about how querying is currently implemented.

Currently, the locale is always implicit when querying, so Post.i18n.where(title: "foo") will implicitly look for posts whose title in English is "foo".

I'm thinking that it would be useful to allow options ("query options") to be passed into the query method, which could e.g. include which locales to match for:

Post.i18n(locales: [:en, :ja]).where(title: "foo")
#=> finds posts whose title in English or Japanese is "foo"

This seems like a logical step toward something like fallbacks, which could be a different option.

Where I'm hesitating a bit is whether to couple accessor fallbacks (the fallbacks plugin) to querying fallbacks. Globalize does this but I'm thinking of keeping them separate and isolated, but open to feedback.

@shioyama
Copy link
Owner Author

I'm leaning now toward implementing this with a simple locale key in the query hash, like this:

Post.i18n.where(title: "foo", locale: [:en, :fr])

One advantage here is that you can apply locales to specific attributes, allowing you to potentially build up more complex multi-locale queries:

Post.i18n.where(title: "foo", locale: [:en, :fr]).where(content: "bar", locale: :de)

This is pretty far-fetched, but all else equal I think localizing the scope of the locale is better and this shouldn't be any more complicated than passing the locale to i18n.

On the other hand, this means that locale becomes a reserved key inside the i18n scope. I think this is fine, it pretty much is a reserved key anyway.

@shioyama
Copy link
Owner Author

shioyama commented May 27, 2018

So #233 now implements passing the locale in the options to where. It only accepts a single locale, but accepting an array of locales should not be so hard given that the entire querying interface has been rewritten.

@hellekin
Copy link

hellekin commented Oct 27, 2018

It looks to me like fallbacks do not work with :container backend:

[10] pry(main)> Mobility.config
=> #<Mobility::Configuration:0x000055bc07a2a468
 @accessor_method=:translates,
 @default_accessor_locales=#<Proc:0x000055bc07a2a3f0@/home/how/.gem/ruby/2.5.3/gems/mobility-0.8.4/lib/mobility/configuration.rb:107 (lambda)>,
 @default_backend=:container,
 @default_options={:cache=>true, :presence=>true, :query=>true, :default=>#<Object:0x000055bc0729a608>, :fallbacks=>true},
 @fallbacks_generator=#<Proc:0x000055bc07a2a418@/home/how/.gem/ruby/2.5.3/gems/mobility-0.8.4/lib/mobility/configuration.rb:106 (lambda)>,
 @plugins=[:query, :cache, :dirty, :fallbacks, :presence, :default, :attribute_methods, :fallthrough_accessors, :locale_accessors],
 @query_method=:i18n>
[11] pry(main)> I18n.default_locale
=> :en
[12] pry(main)> I18n.locale
=> :en
[13] pry(main)> Mobility.locale
=> :fr
[14] pry(main)> a[:name]
=> nil
[15] pry(main)> a[:translations]
=> {"en"=>{"name"=>"Dewey Maps", "summary"=>"Collective Agent for Dewey Maps"}, "fr"=>{"summary"=>"Un agent collectif pour Dewey Maps"}}
[16] pry(main)> a.name_backend.read(:fr)
=> nil
[17] pry(main)> a.name
=> nil
[18] pry(main)> a.name_backend.read(:en)
=> "Dewey Maps"
[19] pry(main)> a.name == a.name_backend.read(:en)
=> false

As fallbacks are set in the default configuration, I would expect a.name to fallback to the default locale, which is English.

I just read the roadmap and found a slot for "Migrating from untranslated to translated + writing to untranslated column" and another for "Querying with fallbacks" which leads to this issue. I guess @shioyama is working on it :)

@shioyama
Copy link
Owner Author

@hellekin This is really not the right place for a question about fallbacks on accessors, this issue is about fallbacks on querying (i.e. search).

But just quickly: I assume you're using I18n version 1.1, right? As of 1.1 I18n no longer falls back to the default locale, see ruby-i18n/i18n#415.

@hellekin
Copy link

Ah, thanks! Should this be moved to a new issue?

Changing config.i18n.fallbacks = [:en] explicitly indeed makes the fallbacks work.

@shioyama
Copy link
Owner Author

No need for issue since there is no "issue" 😄

@molfar
Copy link

molfar commented Feb 8, 2019

Back to the issue subject, is it supported fallbacks in queries? I'm trying to use mobility-friendly_id gem, and this question is actual.

@shioyama
Copy link
Owner Author

shioyama commented Feb 8, 2019

@molfar Not supported yet, if it was I would have closed this issue.

@mrbrdo
Copy link
Contributor

mrbrdo commented Apr 12, 2022

@shioyama so 3 years later, any chance we could see this supported any time soon? The friendly_id-mobility is kinda useless without this fallback support, and I'm sure it would benefit other use-cases as well.
Globalize does support his, right?

@shioyama
Copy link
Owner Author

This is not easy to support for all backends.

You have to understand that Globalize can support this kind of tricky thing because it only has one backend. Mobility has a half dozen of them. So querying with fallbacks would require some new abstraction at the backend layer, which would mean all backends would have to change. That's not something I'm going to do anytime soon.

Also though, even if it was possible, I don't want to add new functionality which then needs to be supported. I'd welcome someone to implement this for the table backend and either make a gem out of it or paste the code here, or it could go in the wiki.

@mrbrdo
Copy link
Contributor

mrbrdo commented Jun 22, 2022

@shioyama For reference here is how I implemented it for my use case with ActiveRecord table backend. It's not generalized/automatic though, but when used it will use fallback locales to perform the query. It uses COALESCE in SQL to use the first non-null value. It's not ideal but it works and is not too slow.

https://github.com/mrbrdo/spree_mobility/blob/949987fa86e4e36e03a0eff86881b872d6ee6894/lib/spree_mobility/translation_query.rb
https://github.com/mrbrdo/spree_mobility/blob/949987fa86e4e36e03a0eff86881b872d6ee6894/lib/spree_mobility/core_ext/spree/variant_decorator.rb#L9

@shioyama
Copy link
Owner Author

I'm closing this one. It would be "nice to have" but it's difficult to implement for all backends and I've scaled back my ambitions for mobility to maintaining current functionality.

This feels like something that could be implemented as a plugin.

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

No branches or pull requests

4 participants