Backends with Enumerable#71
Conversation
|
This is very exciting. Awesome work! The one thing I’m not sure about is the name of the |
Good point! I agree Regarding the appropriateness of iterator methods on the backend instance, I originaly named the backend instance It's these very subtle decisions that are the hardest... I suppose for now we should just stick with the |
|
It sure would sound better to iterate over |
c173f4f to
131ffae
Compare
We can define the minimum simplest method on each backend which yields locales only, and then in Mobility::Backend use this to yield locales and values for that locale together. Mobility::Backend#locales should return all locales *without* reading the actual values (since this could potentially be costly for backends), which means we can't simply use the `to_a` enumerable method here, and instead need to build up an array iterating through each locale.
|
@cbothner After thinking about this for a while, I've settled on the following solution. First, backends implement Then in def each
each_locale { |locale| yield Translation.new(self, locale) }
endHere, Translation = Struct.new(:backend, :locale) do
%w[read write].each do |accessor|
define_method accessor do |*args|
backend.send(accessor, locale, *args)
end
end
endNow if you call any iterator method, the values yielded are these Translation structs, from which you can get the actual value by calling post.title_backend.find { |t| t.read == "foo" }
#=> returns translation with title "foo"Since Also, def locales
map(&:locale)
endI may be overthinking this a bit, but it feels like this is the right balance. If |
Resolves #39.
This is a relatively small change, but an important one. Currently backends don't strictly "know" what translations they have. They only know how to query for a translation in a locale, or write to that locale.
There are many cases where you'd want to know what locales are available independent of the implementing backend, so it makes sense to add a method to get locales.
Originally I was just going to add a
localesmethod which would do this, but then it occurred to me that hey, this is Ruby, so let's make it more flexible by doing it the Ruby way. So instead of defining alocalesmethod, I simply defined aneachmethod on every backend which yields each locale successively to a block.In
Mobility::Backend, I then also added alistmethod which gets the list of locales from the iterator. I also includedEnumerableso that you can now call any enumerable method ont he backend and it apply it to the locales, which you can then build off to do anything you'd really want to do:The only thing I hesitated about slightly was whether the iterator should pass the locale and the translated value. I think in the end though, considering that for some backends it might be expensive to do operations which fetch values, it's better to implement the minimum, and on top of that you can read/write any value with
readandwrite.In the example above, you can get just a list of locales with
post.title_backend.list:@cbothner @jnylen Have a look and see what you think.