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

Include fallbacks module by default but do not actually use it #13

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion lib/mobility.rb
Original file line number Diff line number Diff line change
Expand Up @@ -165,12 +165,16 @@ def config

# (see Mobility::Configuration#default_accessor_locales)
# @!method default_accessor_locales
%w[accessor_method default_fallbacks default_backend default_accessor_locales].each do |method_name|
%w[accessor_method default_backend default_accessor_locales].each do |method_name|
define_method method_name do
config.public_send(method_name)
end
end

define_method :default_fallbacks do |*args|
config.public_send(:default_fallbacks, *args)
end

# Configure Mobility
# @yield [Mobility::Configuration] Mobility configuration
def configure
Expand Down
15 changes: 8 additions & 7 deletions lib/mobility/attributes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -166,13 +166,6 @@ def initialize(method, *attributes_, **options_)
end
end

def include_backend_modules(backend_class, options)
backend_class.include(Backend::Cache) unless options[:cache] == false
backend_class.include(Backend::Dirty.for(options[:model_class])) if options[:dirty]
backend_class.include(Backend::Fallbacks) if options[:fallbacks]
backend_class.include(FallthroughAccessors.new(attributes)) if options[:fallthrough_accessors]
end

# Add this attributes module to shared {Mobility::Wrapper} and setup model
# with backend setup block (see {Mobility::Backend::Setup#setup_model}).
# @param model_class [Class] Class of model
Expand All @@ -189,6 +182,14 @@ def each &block

private

# Include backend modules depending on value of options.
def include_backend_modules(backend_class, options)
backend_class.include(Backend::Cache) unless options[:cache] == false
backend_class.include(Backend::Dirty.for(options[:model_class])) if options[:dirty]
backend_class.include(Backend::Fallbacks) unless options[:fallbacks] == false
backend_class.include(FallthroughAccessors.new(attributes)) if options[:fallthrough_accessors]
end

def define_backend(attribute)
_backend_class, _options = backend_class, options
define_method Backend.method_name(attribute) do
Expand Down
5 changes: 1 addition & 4 deletions lib/mobility/backend.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,9 @@ module Backend
# @!macro [new] backend_constructor
# @param model Model on which backend is defined
# @param [String] attribute Backend attribute
# @option backend_options [Hash] fallbacks Fallbacks hash
def initialize(model, attribute, **backend_options)
def initialize(model, attribute, **_)
@model = model
@attribute = attribute
fallbacks = backend_options[:fallbacks]
@fallbacks = I18n::Locale::Fallbacks.new(fallbacks) if fallbacks.is_a?(Hash)
end

# @!macro [new] backend_reader
Expand Down
25 changes: 18 additions & 7 deletions lib/mobility/backend/fallbacks.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,20 @@ class Post
#=> "Mobilité"
=end
module Fallbacks
# @!macro [new] backend_constructor
# @param model Model on which backend is defined
# @param [String] attribute Backend attribute
# @option backend_options [Hash] fallbacks Fallbacks hash
def initialize(model, attributes, **backend_options)
super
@fallbacks =
if (fallbacks = backend_options[:fallbacks]).is_a?(Hash)
Mobility.default_fallbacks(fallbacks)
elsif fallbacks == true
Mobility.default_fallbacks
end
end

# @!group Backend Accessors
# @!macro backend_reader
# @param [Boolean,Symbol,Array] fallback
Expand All @@ -86,18 +100,15 @@ def read(locale, fallback: nil, **options)
warn "You passed an option with key 'fallbacks', which will be
ignored. Did you mean 'fallback'?"
end
return super if fallback == false
(fallback ? [locale, *fallback] : fallbacks[locale]).detect do |locale|
value = super(locale, **options)
return super if fallback == false || fallbacks.nil?
(fallback ? [locale, *fallback] : fallbacks[locale]).detect do |fallback_locale|
value = super(fallback_locale, **options)
break value if value.present?
end
end

private

def fallbacks
@fallbacks ||= Mobility.default_fallbacks
end
attr_reader :fallbacks
end
end
end
7 changes: 5 additions & 2 deletions lib/mobility/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ class Configuration

# Default fallbacks instance
# @return [I18n::Locale::Fallbacks]
attr_accessor :default_fallbacks
def default_fallbacks(fallbacks = {})
@default_fallbacks.call(fallbacks)
end
attr_writer :default_fallbacks

# Default backend to use (can be symbol or actual backend class)
# @return [Symbol,Class]
Expand All @@ -31,7 +34,7 @@ def default_accessor_locales

def initialize
@accessor_method = :translates
@default_fallbacks = I18n::Locale::Fallbacks.new
@default_fallbacks = lambda { |fallbacks| I18n::Locale::Fallbacks.new(fallbacks) }
@default_accessor_locales = lambda { I18n.available_locales }
end
end
Expand Down
18 changes: 10 additions & 8 deletions spec/mobility/attributes_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@
describe "cache" do
it "includes Backend::Cache into backend when options[:cache] is not false" do
expect(backend_klass).to receive(:include).with(Mobility::Backend::Cache)
Article.include described_class.new(:accessor, "title", { backend: backend_klass })
Article.include described_class.new(:accessor, "title", { backend: backend_klass, fallbacks: false })
end

it "does not include Backend::Cache into backend when options[:cache] is false" do
expect(backend_klass).not_to receive(:include).with(Mobility::Backend::Cache)
Article.include described_class.new(:accessor, "title", { backend: backend_klass, cache: false })
Article.include described_class.new(:accessor, "title", { backend: backend_klass, cache: false, fallbacks: false })
end
end

Expand All @@ -62,6 +62,7 @@
Article.include described_class.new(:accessor, "title", {
backend: backend_klass,
cache: false,
fallbacks: false,
dirty: true,
fallthrough_accessors: false,
model_class: Article
Expand All @@ -70,7 +71,7 @@

it "does not include Backend::Model::Dirty into backend when options[:dirty] is falsey" do
expect(backend_klass).not_to receive(:include).with(Mobility::Backend::ActiveModel::Dirty)
Article.include described_class.new(:accessor, "title", { backend: backend_klass, cache: false, model_class: Article })
Article.include described_class.new(:accessor, "title", { backend: backend_klass, cache: false, fallbacks: false, model_class: Article })
end
end

Expand All @@ -85,6 +86,7 @@
Article.include described_class.new(:accessor, "title", {
backend: backend_klass,
cache: false,
fallbacks: false,
dirty: true,
fallthrough_accessors: false,
model_class: Article
Expand All @@ -93,20 +95,20 @@

it "does not include Backend::Sequel::Dirty into backend when options[:dirty] is falsey" do
expect(backend_klass).not_to receive(:include).with(Mobility::Backend::Sequel::Dirty)
Article.include described_class.new(:accessor, "title", { backend: backend_klass, cache: false, model_class: Article })
Article.include described_class.new(:accessor, "title", { backend: backend_klass, cache: false, fallbacks: false, model_class: Article })
end
end
end

describe "fallbacks" do
it "includes Backend::Fallbacks into backend when options[:fallbacks] is truthy" do
it "includes Backend::Fallbacks into backend when options[:fallbacks] is not false" do
expect(backend_klass).to receive(:include).with(Mobility::Backend::Fallbacks)
Article.include described_class.new(:accessor, "title", { backend: backend_klass, fallbacks: true, cache: false })
Article.include described_class.new(:accessor, "title", { backend: backend_klass, cache: false })
end

it "does not include Backend::Fallbacks into backend when options[:fallbacks] is falsey" do
it "does not include Backend::Fallbacks into backend when options[:fallbacks] is false" do
expect(backend_klass).not_to receive(:include).with(Mobility::Backend::Fallbacks)
Article.include described_class.new(:accessor, "title", { backend: backend_klass, cache: false })
Article.include described_class.new(:accessor, "title", { backend: backend_klass, cache: false, fallbacks: false })
end
end

Expand Down
76 changes: 51 additions & 25 deletions spec/mobility/backend/fallbacks_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def read(locale, **options)
{
"title" => {
:'de-DE' => "foo",
:'jp' => "フー",
:ja => "フー",
:'pt' => ""
}
}[attribute][locale]
Expand All @@ -21,39 +21,65 @@ def read(locale, **options)
end
let(:object) { (stub_const 'MobilityModel', Class.new).include(Mobility).new }

subject do
backend_class.new(object, "title", fallbacks: { :'en-US' => 'de-DE', :pt => 'de-DE' })
end
context "fallbacks is a hash" do
subject do
backend_class.new(object, "title", fallbacks: { :'en-US' => 'de-DE', :pt => 'de-DE' })
end

it "returns value when value is not nil" do
expect(subject.read(:"jp")).to eq("フー")
end
it "returns value when value is not nil" do
expect(subject.read(:ja)).to eq("フー")
end

it "falls through to fallback locale when value is nil" do
expect(subject.read(:"en-US")).to eq("foo")
end
it "falls through to fallback locale when value is nil" do
expect(subject.read(:"en-US")).to eq("foo")
end

it "falls through to fallback locale when value is blank" do
expect(subject.read(:pt)).to eq("foo")
end
it "falls through to fallback locale when value is blank" do
expect(subject.read(:pt)).to eq("foo")
end

it "returns nil when no fallback is found" do
expect(subject.read(:"fr")).to eq(nil)
end
it "returns nil when no fallback is found" do
expect(subject.read(:"fr")).to eq(nil)
end

it "returns nil when fallbacks: false option is passed" do
expect(subject.read(:"en-US", fallback: false)).to eq(nil)
end
it "returns nil when fallbacks: false option is passed" do
expect(subject.read(:"en-US", fallback: false)).to eq(nil)
end

it "uses locale passed in as value of fallback option when present" do
expect(subject.read(:"en-US", fallback: :ja)).to eq("フー")
end

it "uses locale passed in as value of fallback option when present" do
expect(subject.read(:"en-US", fallback: :jp)).to eq("フー")
it "uses array of locales passed in as value of fallback options when present" do
expect(subject.read(:"en-US", fallback: [:es, :'de-DE'])).to eq("foo")
end

it "passes options to getter in fallback locale" do
expect(subject.read(:'en-US', bar: true)).to eq("bar")
end
end

it "uses array of locales passed in as value of fallback options when present" do
expect(subject.read(:"en-US", fallback: [:es, :'de-DE'])).to eq("foo")
context "fallbacks is true" do
subject do
backend_class.new(object, "title", fallbacks: true)
end

it "uses default fallbacks" do
original_default_locale = I18n.default_locale
I18n.default_locale = :ja
expect(subject.read(:"en-US")).to eq("フー")
I18n.default_locale = original_default_locale
end
end

it "passes options to getter in fallback locale" do
expect(subject.read(:'en-US', bar: true)).to eq("bar")
context "fallbacks is falsey" do
subject { backend_class.new(object, "title") }

it "does not use fallbacks" do
original_default_locale = I18n.default_locale
I18n.default_locale = :ja
expect(subject.read(:"en-US")).to eq(nil)
I18n.default_locale = original_default_locale
end
end
end
13 changes: 0 additions & 13 deletions spec/mobility/backend_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,6 @@
end
end

context "with options" do
subject { MyBackend.new(model, attribute, options) }
let(:options) { { foo: "bar" } }

context "with fallbacks" do
let(:options) { { fallbacks: { :'en-US' => 'de-DE' } } }

it "sets @fallbacks variable" do
expect(subject.instance_variable_get(:'@fallbacks')).to eq(I18n::Locale::Fallbacks.new(:'en-US' => 'de-DE'))
end
end
end

describe ".setup" do
before do
MyBackend.class_eval do
Expand Down