From 13057d371e199217b5b57dd0c3719f03d5f6f441 Mon Sep 17 00:00:00 2001 From: Chris Salzberg Date: Fri, 4 Aug 2017 23:06:49 +0900 Subject: [PATCH 1/7] Require core classes instead of autoloading them --- lib/mobility.rb | 26 +++++++++++++------------- lib/mobility/active_record.rb | 14 ++++++-------- lib/mobility/{orm.rb => loaded.rb} | 0 lib/mobility/sequel.rb | 12 +++++------- 4 files changed, 24 insertions(+), 28 deletions(-) rename lib/mobility/{orm.rb => loaded.rb} (100%) diff --git a/lib/mobility.rb b/lib/mobility.rb index 2293ad57d..9afa4d9fd 100644 --- a/lib/mobility.rb +++ b/lib/mobility.rb @@ -32,16 +32,15 @@ class MyClass =end module Mobility - autoload :Attributes, "mobility/attributes" - autoload :Backend, "mobility/backend" - autoload :Backends, "mobility/backends" - autoload :BackendResetter, "mobility/backend_resetter" - autoload :Configuration, "mobility/configuration" - autoload :Plugins, "mobility/plugins" - autoload :Translates, "mobility/translates" - autoload :Wrapper, "mobility/wrapper" - - require "mobility/orm" + require "mobility/attributes" + require "mobility/backend" + require "mobility/backends" + require "mobility/backend_resetter" + require "mobility/configuration" + require "mobility/loaded" + require "mobility/plugins" + require "mobility/translates" + require "mobility/wrapper" # General error for version compatibility conflicts class VersionNotSupportedError < ArgumentError; end @@ -49,8 +48,8 @@ class VersionNotSupportedError < ArgumentError; end begin require "active_record" raise VersionNotSupportedError, "Mobility is only compatible with ActiveRecord 4.2 and greater" if ::ActiveRecord::VERSION::STRING < "4.2" - autoload :ActiveModel, "mobility/active_model" - autoload :ActiveRecord, "mobility/active_record" + require "mobility/active_model" + require "mobility/active_record" Loaded::ActiveRecord = true rescue LoadError Loaded::ActiveRecord = false @@ -68,9 +67,10 @@ class VersionNotSupportedError < ArgumentError; end require "sequel" raise VersionNotSupportedError, "Mobility is only compatible with Sequel 4.0 and greater" if ::Sequel::MAJOR < 4 require "sequel/plugins/mobility" + #TODO avoid automatically including the inflector extension require "sequel/extensions/inflector" require "sequel/plugins/dirty" - autoload :Sequel, "mobility/sequel" + require "mobility/sequel" Loaded::Sequel = true rescue LoadError Loaded::Sequel = false diff --git a/lib/mobility/active_record.rb b/lib/mobility/active_record.rb index 65de3ee76..d93ddad90 100644 --- a/lib/mobility/active_record.rb +++ b/lib/mobility/active_record.rb @@ -14,16 +14,14 @@ module ActiveRecord autoload :UniquenessValidator, "mobility/active_record/uniqueness_validator" def self.included(model_class) - model_class.extend(ClassMethods) + query_method = Module.new do + define_method Mobility.query_method do + all + end + end + model_class.extend query_method model_class.const_set(:UniquenessValidator, Class.new(::Mobility::ActiveRecord::UniquenessValidator)) end - - module ClassMethods - # @return [ActiveRecord::Relation] relation extended with Mobility query methods. - define_method ::Mobility.query_method do - all - end - end end end diff --git a/lib/mobility/orm.rb b/lib/mobility/loaded.rb similarity index 100% rename from lib/mobility/orm.rb rename to lib/mobility/loaded.rb diff --git a/lib/mobility/sequel.rb b/lib/mobility/sequel.rb index e9b03af49..0581dc654 100644 --- a/lib/mobility/sequel.rb +++ b/lib/mobility/sequel.rb @@ -13,14 +13,12 @@ module Sequel autoload :Translation, "mobility/sequel/translation" def self.included(model_class) - model_class.extend(ClassMethods) - end - - module ClassMethods - # @return [Sequel::Dataset] dataset extended with Mobility query methods. - define_method ::Mobility.query_method do - dataset + query_method = Module.new do + define_method Mobility.query_method do + dataset + end end + model_class.extend query_method end end end From 8eea225beadb499296d6649f5a5adcd365f55563 Mon Sep 17 00:00:00 2001 From: Chris Salzberg Date: Fri, 4 Aug 2017 23:22:56 +0900 Subject: [PATCH 2/7] Convert autoload to require --- lib/mobility/active_model.rb | 1 - lib/mobility/active_record.rb | 9 ++------- lib/mobility/active_record/backend_resetter.rb | 2 ++ lib/mobility/active_record/string_translation.rb | 2 ++ lib/mobility/active_record/text_translation.rb | 2 ++ lib/mobility/backend.rb | 4 +--- lib/mobility/backend_resetter.rb | 3 +++ lib/mobility/backends/active_record/key_value.rb | 2 ++ lib/mobility/backends/active_record/table.rb | 1 + lib/mobility/backends/sequel/key_value.rb | 3 +++ lib/mobility/backends/sequel/pg_hash.rb | 2 ++ lib/mobility/backends/sequel/table.rb | 2 ++ lib/mobility/plugins/active_model.rb | 1 - lib/mobility/plugins/active_record.rb | 1 - lib/mobility/plugins/active_record/dirty.rb | 1 + lib/mobility/plugins/dirty.rb | 12 ++++++++++-- lib/mobility/plugins/sequel.rb | 1 - lib/mobility/sequel.rb | 7 ------- lib/mobility/sequel/string_translation.rb | 2 ++ lib/mobility/sequel/text_translation.rb | 2 ++ spec/mobility/plugins/active_model/dirty_spec.rb | 2 +- spec/mobility/plugins/active_record/dirty_spec.rb | 2 +- 22 files changed, 39 insertions(+), 25 deletions(-) diff --git a/lib/mobility/active_model.rb b/lib/mobility/active_model.rb index cd21cc1cc..7285b4c2d 100644 --- a/lib/mobility/active_model.rb +++ b/lib/mobility/active_model.rb @@ -1,5 +1,4 @@ module Mobility module ActiveModel - autoload :BackendResetter, "mobility/active_model/backend_resetter" end end diff --git a/lib/mobility/active_record.rb b/lib/mobility/active_record.rb index d93ddad90..cbf1f3060 100644 --- a/lib/mobility/active_record.rb +++ b/lib/mobility/active_record.rb @@ -5,13 +5,8 @@ module Mobility =end module ActiveRecord - autoload :AttributeMethods, "mobility/active_record/attribute_methods" - autoload :BackendResetter, "mobility/active_record/backend_resetter" - autoload :ModelTranslation, "mobility/active_record/model_translation" - autoload :StringTranslation, "mobility/active_record/string_translation" - autoload :TextTranslation, "mobility/active_record/text_translation" - autoload :Translation, "mobility/active_record/translation" - autoload :UniquenessValidator, "mobility/active_record/uniqueness_validator" + require "mobility/active_record/attribute_methods" + require "mobility/active_record/uniqueness_validator" def self.included(model_class) query_method = Module.new do diff --git a/lib/mobility/active_record/backend_resetter.rb b/lib/mobility/active_record/backend_resetter.rb index 6880b55d4..8636323dc 100644 --- a/lib/mobility/active_record/backend_resetter.rb +++ b/lib/mobility/active_record/backend_resetter.rb @@ -1,3 +1,5 @@ +require "mobility/active_model/backend_resetter" + module Mobility module ActiveRecord =begin diff --git a/lib/mobility/active_record/string_translation.rb b/lib/mobility/active_record/string_translation.rb index d10643039..c4c5bf29b 100644 --- a/lib/mobility/active_record/string_translation.rb +++ b/lib/mobility/active_record/string_translation.rb @@ -1,3 +1,5 @@ +require "mobility/active_record/translation" + module Mobility module ActiveRecord class StringTranslation < Translation diff --git a/lib/mobility/active_record/text_translation.rb b/lib/mobility/active_record/text_translation.rb index 0647f108c..ae901e01f 100644 --- a/lib/mobility/active_record/text_translation.rb +++ b/lib/mobility/active_record/text_translation.rb @@ -1,3 +1,5 @@ +require "mobility/active_record/translation" + module Mobility module ActiveRecord class TextTranslation < Translation diff --git a/lib/mobility/backend.rb b/lib/mobility/backend.rb index 6ac3f4863..c46ff0734 100644 --- a/lib/mobility/backend.rb +++ b/lib/mobility/backend.rb @@ -1,4 +1,5 @@ # frozen-string-literal: true +require "mobility/backend/orm_delegator" module Mobility =begin @@ -49,9 +50,6 @@ def self.configure(options) =end module Backend - autoload :OrmDelegator, 'mobility/backend/orm_delegator' - autoload :StringifyLocale, 'mobility/backend/stringify_locale' - # @return [String] Backend attribute attr_reader :attribute diff --git a/lib/mobility/backend_resetter.rb b/lib/mobility/backend_resetter.rb index 91efb4127..62e077851 100644 --- a/lib/mobility/backend_resetter.rb +++ b/lib/mobility/backend_resetter.rb @@ -31,10 +31,13 @@ def initialize(attribute_names, &block) # @param [Class] model_class Class of model to which backend resetter will be applied def self.for(model_class) if Loaded::ActiveRecord && model_class < ::ActiveRecord::Base + require "mobility/active_record/backend_resetter" ActiveRecord::BackendResetter elsif Loaded::ActiveRecord && model_class.ancestors.include?(::ActiveModel::Dirty) + require "mobility/active_model/backend_resetter" ActiveModel::BackendResetter elsif Loaded::Sequel && model_class < ::Sequel::Model + require "mobility/sequel/backend_resetter" Sequel::BackendResetter else self diff --git a/lib/mobility/backends/active_record/key_value.rb b/lib/mobility/backends/active_record/key_value.rb index da933024a..ccfb3ae01 100644 --- a/lib/mobility/backends/active_record/key_value.rb +++ b/lib/mobility/backends/active_record/key_value.rb @@ -1,4 +1,6 @@ # frozen-string-literal: true +require "mobility/active_record/string_translation" +require "mobility/active_record/text_translation" module Mobility module Backends diff --git a/lib/mobility/backends/active_record/table.rb b/lib/mobility/backends/active_record/table.rb index 2e62be287..9aa792c0f 100644 --- a/lib/mobility/backends/active_record/table.rb +++ b/lib/mobility/backends/active_record/table.rb @@ -1,4 +1,5 @@ # frozen-string-literal: true +require "mobility/active_record/model_translation" module Mobility module Backends diff --git a/lib/mobility/backends/sequel/key_value.rb b/lib/mobility/backends/sequel/key_value.rb index eb287e188..d690e714d 100644 --- a/lib/mobility/backends/sequel/key_value.rb +++ b/lib/mobility/backends/sequel/key_value.rb @@ -1,4 +1,7 @@ # frozen-string-literal: true +require "mobility/sequel/column_changes" +require "mobility/sequel/string_translation" +require "mobility/sequel/text_translation" module Mobility module Backends diff --git a/lib/mobility/backends/sequel/pg_hash.rb b/lib/mobility/backends/sequel/pg_hash.rb index 50f14672b..3201e98a6 100644 --- a/lib/mobility/backends/sequel/pg_hash.rb +++ b/lib/mobility/backends/sequel/pg_hash.rb @@ -1,3 +1,5 @@ +require "mobility/backend/stringify_locale" + module Mobility module Backends =begin diff --git a/lib/mobility/backends/sequel/table.rb b/lib/mobility/backends/sequel/table.rb index fded5d58d..74d2b5a04 100644 --- a/lib/mobility/backends/sequel/table.rb +++ b/lib/mobility/backends/sequel/table.rb @@ -1,3 +1,5 @@ +require "mobility/sequel/model_translation" + module Mobility module Backends =begin diff --git a/lib/mobility/plugins/active_model.rb b/lib/mobility/plugins/active_model.rb index 2060be716..786caea30 100644 --- a/lib/mobility/plugins/active_model.rb +++ b/lib/mobility/plugins/active_model.rb @@ -1,7 +1,6 @@ module Mobility module Plugins module ActiveModel - autoload :Dirty, 'mobility/plugins/active_model/dirty' end end end diff --git a/lib/mobility/plugins/active_record.rb b/lib/mobility/plugins/active_record.rb index d2ff5a0d3..303f14d70 100644 --- a/lib/mobility/plugins/active_record.rb +++ b/lib/mobility/plugins/active_record.rb @@ -1,7 +1,6 @@ module Mobility module Plugins module ActiveRecord - autoload :Dirty, 'mobility/plugins/active_record/dirty' end end end diff --git a/lib/mobility/plugins/active_record/dirty.rb b/lib/mobility/plugins/active_record/dirty.rb index 53a46aa0d..7db1f0220 100644 --- a/lib/mobility/plugins/active_record/dirty.rb +++ b/lib/mobility/plugins/active_record/dirty.rb @@ -1,4 +1,5 @@ # frozen-string-literal: true +require "mobility/plugins/active_model/dirty" module Mobility module Plugins diff --git a/lib/mobility/plugins/dirty.rb b/lib/mobility/plugins/dirty.rb index 3fcad4ec8..ceab6ed1e 100644 --- a/lib/mobility/plugins/dirty.rb +++ b/lib/mobility/plugins/dirty.rb @@ -1,3 +1,5 @@ +require "mobility/backend_resetter" + module Mobility module Plugins =begin @@ -36,9 +38,15 @@ def apply(attributes, option) def include_dirty_module(backend_class, model_class, *attribute_names) dirty_module = if Loaded::ActiveRecord && model_class.ancestors.include?(::ActiveModel::Dirty) - (model_class < ::ActiveRecord::Base) ? - Plugins::ActiveRecord::Dirty : Plugins::ActiveModel::Dirty + if (model_class < ::ActiveRecord::Base) + require "mobility/plugins/active_record/dirty" + Plugins::ActiveRecord::Dirty + else + require "mobility/plugins/active_model/dirty" + Plugins::ActiveModel::Dirty + end elsif Loaded::Sequel && model_class < ::Sequel::Model + require "mobility/plugins/sequel/dirty" Plugins::Sequel::Dirty else raise ArgumentError, "#{model_class} does not support Dirty module." diff --git a/lib/mobility/plugins/sequel.rb b/lib/mobility/plugins/sequel.rb index 0e9255508..6a48f3be4 100644 --- a/lib/mobility/plugins/sequel.rb +++ b/lib/mobility/plugins/sequel.rb @@ -1,7 +1,6 @@ module Mobility module Plugins module Sequel - autoload :Dirty, 'mobility/plugins/sequel/dirty' end end end diff --git a/lib/mobility/sequel.rb b/lib/mobility/sequel.rb index 0581dc654..2cc437762 100644 --- a/lib/mobility/sequel.rb +++ b/lib/mobility/sequel.rb @@ -5,13 +5,6 @@ module Mobility =end module Sequel - autoload :BackendResetter, "mobility/sequel/backend_resetter" - autoload :ColumnChanges, "mobility/sequel/column_changes" - autoload :ModelTranslation, "mobility/sequel/model_translation" - autoload :StringTranslation, "mobility/sequel/string_translation" - autoload :TextTranslation, "mobility/sequel/text_translation" - autoload :Translation, "mobility/sequel/translation" - def self.included(model_class) query_method = Module.new do define_method Mobility.query_method do diff --git a/lib/mobility/sequel/string_translation.rb b/lib/mobility/sequel/string_translation.rb index 4a07c532f..bedc03042 100644 --- a/lib/mobility/sequel/string_translation.rb +++ b/lib/mobility/sequel/string_translation.rb @@ -1,3 +1,5 @@ +require "mobility/sequel/translation" + module Mobility module Sequel class StringTranslation < ::Sequel::Model(:mobility_string_translations) diff --git a/lib/mobility/sequel/text_translation.rb b/lib/mobility/sequel/text_translation.rb index 2f16a7f5c..091ebb2bf 100644 --- a/lib/mobility/sequel/text_translation.rb +++ b/lib/mobility/sequel/text_translation.rb @@ -1,3 +1,5 @@ +require "mobility/sequel/translation" + module Mobility module Sequel class TextTranslation < ::Sequel::Model(:mobility_text_translations) diff --git a/spec/mobility/plugins/active_model/dirty_spec.rb b/spec/mobility/plugins/active_model/dirty_spec.rb index 7d7f55aaa..f29643dc4 100644 --- a/spec/mobility/plugins/active_model/dirty_spec.rb +++ b/spec/mobility/plugins/active_model/dirty_spec.rb @@ -286,4 +286,4 @@ def save end end end -end +end if Mobility::Loaded::ActiveRecord diff --git a/spec/mobility/plugins/active_record/dirty_spec.rb b/spec/mobility/plugins/active_record/dirty_spec.rb index 64b7da4bc..67a265a52 100644 --- a/spec/mobility/plugins/active_record/dirty_spec.rb +++ b/spec/mobility/plugins/active_record/dirty_spec.rb @@ -276,4 +276,4 @@ def clear_changes_information it_behaves_like "resets on model action", :save it_behaves_like "resets on model action", :reload end -end +end if Mobility::Loaded::ActiveRecord From 6ee2d28e09e4ab72ac56b384bcfab7bf43db54df Mon Sep 17 00:00:00 2001 From: Chris Salzberg Date: Fri, 4 Aug 2017 23:35:07 +0900 Subject: [PATCH 3/7] Remove autoload from plugins --- lib/mobility/attributes.rb | 5 +- lib/mobility/backends/key_value.rb | 2 + lib/mobility/plugins.rb | 10 --- lib/mobility/plugins/active_model/dirty.rb | 82 ++++++++++--------- lib/mobility/plugins/active_record/dirty.rb | 72 ++++++++-------- lib/mobility/plugins/dirty.rb | 1 + lib/mobility/plugins/sequel/dirty.rb | 66 +++++++-------- spec/mobility/plugins/cache_spec.rb | 1 + spec/mobility/plugins/default_spec.rb | 1 + spec/mobility/plugins/dirty_spec.rb | 1 + spec/mobility/plugins/fallbacks_spec.rb | 1 + .../plugins/fallthrough_accessors_spec.rb | 1 + .../mobility/plugins/locale_accessors_spec.rb | 1 + spec/mobility/plugins/presence_spec.rb | 1 + spec/performance/attributes_spec.rb | 2 +- 15 files changed, 127 insertions(+), 120 deletions(-) diff --git a/lib/mobility/attributes.rb b/lib/mobility/attributes.rb index 9482874bc..a61c5e552 100644 --- a/lib/mobility/attributes.rb +++ b/lib/mobility/attributes.rb @@ -201,8 +201,9 @@ def get_backend_class(backend) Module === backend ? backend : get_class_from_key(Mobility::Backends, backend) end - def get_plugin_class(name) - get_class_from_key(Mobility::Plugins, name) + def get_plugin_class(plugin) + require "mobility/plugins/#{plugin}" + get_class_from_key(Mobility::Plugins, plugin) end def get_class_from_key(parent_class, key) diff --git a/lib/mobility/backends/key_value.rb b/lib/mobility/backends/key_value.rb index a800c8c73..7e8eb96e1 100644 --- a/lib/mobility/backends/key_value.rb +++ b/lib/mobility/backends/key_value.rb @@ -1,3 +1,5 @@ +require "mobility/plugins/cache" + module Mobility module Backends =begin diff --git a/lib/mobility/plugins.rb b/lib/mobility/plugins.rb index 129f10dc9..3c1b3e116 100644 --- a/lib/mobility/plugins.rb +++ b/lib/mobility/plugins.rb @@ -31,15 +31,5 @@ module calls a class method, +apply+ (in this case +Foo.apply+), which takes =end module Plugins - autoload :ActiveModel, 'mobility/plugins/active_model' - autoload :ActiveRecord, 'mobility/plugins/active_record' - autoload :Cache, 'mobility/plugins/cache' - autoload :Default, 'mobility/plugins/default' - autoload :Dirty, 'mobility/plugins/dirty' - autoload :Fallbacks, 'mobility/plugins/fallbacks' - autoload :FallthroughAccessors, 'mobility/plugins/fallthrough_accessors' - autoload :LocaleAccessors, 'mobility/plugins/locale_accessors' - autoload :Presence, 'mobility/plugins/presence' - autoload :Sequel, 'mobility/plugins/sequel' end end diff --git a/lib/mobility/plugins/active_model/dirty.rb b/lib/mobility/plugins/active_model/dirty.rb index 9b0d7e374..077517121 100644 --- a/lib/mobility/plugins/active_model/dirty.rb +++ b/lib/mobility/plugins/active_model/dirty.rb @@ -22,56 +22,58 @@ module Plugins @see http://api.rubyonrails.org/classes/ActiveModel/Dirty.html Rails documentation for Active Model Dirty module =end - module ActiveModel::Dirty - # @!group Backend Accessors - # @!macro backend_writer - # @param [Hash] options - def write(locale, value, options = {}) - locale_accessor = Mobility.normalize_locale_accessor(attribute, locale) - if model.changed_attributes.has_key?(locale_accessor) && model.changed_attributes[locale_accessor] == value - model.attributes_changed_by_setter.except!(locale_accessor) - elsif read(locale, options.merge(fallback: false)) != value - model.send(:attribute_will_change!, locale_accessor) + module ActiveModel + module Dirty + # @!group Backend Accessors + # @!macro backend_writer + # @param [Hash] options + def write(locale, value, options = {}) + locale_accessor = Mobility.normalize_locale_accessor(attribute, locale) + if model.changed_attributes.has_key?(locale_accessor) && model.changed_attributes[locale_accessor] == value + model.attributes_changed_by_setter.except!(locale_accessor) + elsif read(locale, options.merge(fallback: false)) != value + model.send(:attribute_will_change!, locale_accessor) + end + super end - super - end - # @!endgroup + # @!endgroup - # Builds module which adds suffix/prefix methods for translated - # attributes so they act like normal dirty-tracked attributes. - class MethodsBuilder < Module - def initialize(*attribute_names) - attribute_names.each do |name| - method_suffixes.each do |suffix| - define_method "#{name}#{suffix}".freeze do - __send__("attribute#{suffix}".freeze, Mobility.normalize_locale_accessor(name)) + # Builds module which adds suffix/prefix methods for translated + # attributes so they act like normal dirty-tracked attributes. + class MethodsBuilder < Module + def initialize(*attribute_names) + attribute_names.each do |name| + method_suffixes.each do |suffix| + define_method "#{name}#{suffix}".freeze do + __send__("attribute#{suffix}".freeze, Mobility.normalize_locale_accessor(name)) + end end - end - define_method "restore_#{name}!".freeze do - locale_accessor = Mobility.normalize_locale_accessor(name) - if attribute_changed?(locale_accessor) - __send__("#{name}=".freeze, changed_attributes[locale_accessor]) + define_method "restore_#{name}!".freeze do + locale_accessor = Mobility.normalize_locale_accessor(name) + if attribute_changed?(locale_accessor) + __send__("#{name}=".freeze, changed_attributes[locale_accessor]) + end end end - end - define_method :restore_attribute! do |attr| - attribute_names.include?(attr.to_s) ? send("restore_#{attr}!".freeze) : super(attr) + define_method :restore_attribute! do |attr| + attribute_names.include?(attr.to_s) ? send("restore_#{attr}!".freeze) : super(attr) + end + private :restore_attribute! end - private :restore_attribute! - end - private + private - # Get method suffixes. Creating an object just to get the list of - # suffixes is not very efficient, but the most reliable way given that - # they change from Rails version to version. - def method_suffixes - @method_suffixes ||= - Class.new do - include ::ActiveModel::Dirty - end.attribute_method_matchers.map(&:suffix).select { |m| m =~ /\A_/ } + # Get method suffixes. Creating an object just to get the list of + # suffixes is not very efficient, but the most reliable way given that + # they change from Rails version to version. + def method_suffixes + @method_suffixes ||= + Class.new do + include ::ActiveModel::Dirty + end.attribute_method_matchers.map(&:suffix).select { |m| m =~ /\A_/ } + end end end end diff --git a/lib/mobility/plugins/active_record/dirty.rb b/lib/mobility/plugins/active_record/dirty.rb index 7db1f0220..cb680c79b 100644 --- a/lib/mobility/plugins/active_record/dirty.rb +++ b/lib/mobility/plugins/active_record/dirty.rb @@ -9,47 +9,49 @@ module Plugins details on usage. =end - module ActiveRecord::Dirty - include ActiveModel::Dirty - - # Builds module which patches a few AR methods to handle changes to - # translated attributes just like normal attributes. - class MethodsBuilder < ActiveModel::Dirty::MethodsBuilder - def initialize(*attribute_names) - super - @attribute_names = attribute_names - - changes_applied_method = ::ActiveRecord::VERSION::STRING < '5.1' ? :changes_applied : :changes_internally_applied - define_method changes_applied_method do - @previously_changed = changes - super() - end + module ActiveRecord + module Dirty + include ActiveModel::Dirty + + # Builds module which patches a few AR methods to handle changes to + # translated attributes just like normal attributes. + class MethodsBuilder < ActiveModel::Dirty::MethodsBuilder + def initialize(*attribute_names) + super + @attribute_names = attribute_names + + changes_applied_method = ::ActiveRecord::VERSION::STRING < '5.1' ? :changes_applied : :changes_internally_applied + define_method changes_applied_method do + @previously_changed = changes + super() + end - define_method :clear_changes_information do - @previously_changed = ActiveSupport::HashWithIndifferentAccess.new - super() - end + define_method :clear_changes_information do + @previously_changed = ActiveSupport::HashWithIndifferentAccess.new + super() + end - define_method :previous_changes do - (@previously_changed ||= ActiveSupport::HashWithIndifferentAccess.new).merge(super()) + define_method :previous_changes do + (@previously_changed ||= ActiveSupport::HashWithIndifferentAccess.new).merge(super()) + end end - end - # Overrides +ActiveRecord::AttributeMethods::ClassMethods#has_attribute+ to treat fallthrough attribute methods - # just like "real" attribute methods. - # - # @note Patching +has_attribute?+ is necessary as of AR 5.1 due to this commit[https://github.com/rails/rails/commit/4fed08fa787a316fa51f14baca9eae11913f5050]. - # (I have voiced my opposition to this change here[https://github.com/rails/rails/pull/27963#issuecomment-310092787]). - # @param [Attributes] attributes - def included(model_class) - names = @attribute_names - method_name_regex = /\A(#{names.join('|'.freeze)})_([a-z]{2}(_[a-z]{2})?)(=?|\??)\z/.freeze - has_attribute = Module.new do - define_method :has_attribute? do |attr_name| - super(attr_name) || !!method_name_regex.match(attr_name) + # Overrides +ActiveRecord::AttributeMethods::ClassMethods#has_attribute+ to treat fallthrough attribute methods + # just like "real" attribute methods. + # + # @note Patching +has_attribute?+ is necessary as of AR 5.1 due to this commit[https://github.com/rails/rails/commit/4fed08fa787a316fa51f14baca9eae11913f5050]. + # (I have voiced my opposition to this change here[https://github.com/rails/rails/pull/27963#issuecomment-310092787]). + # @param [Attributes] attributes + def included(model_class) + names = @attribute_names + method_name_regex = /\A(#{names.join('|'.freeze)})_([a-z]{2}(_[a-z]{2})?)(=?|\??)\z/.freeze + has_attribute = Module.new do + define_method :has_attribute? do |attr_name| + super(attr_name) || !!method_name_regex.match(attr_name) + end end + model_class.extend has_attribute end - model_class.extend has_attribute end end end diff --git a/lib/mobility/plugins/dirty.rb b/lib/mobility/plugins/dirty.rb index ceab6ed1e..7f3b45342 100644 --- a/lib/mobility/plugins/dirty.rb +++ b/lib/mobility/plugins/dirty.rb @@ -1,4 +1,5 @@ require "mobility/backend_resetter" +require "mobility/plugins/fallthrough_accessors" module Mobility module Plugins diff --git a/lib/mobility/plugins/sequel/dirty.rb b/lib/mobility/plugins/sequel/dirty.rb index d40b0e309..60dff7091 100644 --- a/lib/mobility/plugins/sequel/dirty.rb +++ b/lib/mobility/plugins/sequel/dirty.rb @@ -11,45 +11,47 @@ module Plugins @see http://sequel.jeremyevans.net/rdoc-plugins/index.html Sequel dirty plugin =end - module Sequel::Dirty - # @!group Backend Accessors - # @!macro backend_writer - # @param [Hash] options - def write(locale, value, options = {}) - locale_accessor = Mobility.normalize_locale_accessor(attribute, locale).to_sym - if model.column_changes.has_key?(locale_accessor) && model.initial_values[locale_accessor] == value - super - [model.changed_columns, model.initial_values].each { |h| h.delete(locale_accessor) } - elsif read(locale, options.merge(fallback: false)) != value - model.will_change_column(locale_accessor) - super + module Sequel + module Dirty + # @!group Backend Accessors + # @!macro backend_writer + # @param [Hash] options + def write(locale, value, options = {}) + locale_accessor = Mobility.normalize_locale_accessor(attribute, locale).to_sym + if model.column_changes.has_key?(locale_accessor) && model.initial_values[locale_accessor] == value + super + [model.changed_columns, model.initial_values].each { |h| h.delete(locale_accessor) } + elsif read(locale, options.merge(fallback: false)) != value + model.will_change_column(locale_accessor) + super + end end - end - # @!endgroup + # @!endgroup - # Builds module which overrides dirty methods to handle translated as - # well as normal (untranslated) attributes. - class MethodsBuilder < Module - def initialize(*attribute_names) - # Although we load the plugin in the included callback method, we - # need to include this module here in advance to ensure that its - # instance methods are included *before* the ones defined here. - include ::Sequel::Plugins::Dirty::InstanceMethods + # Builds module which overrides dirty methods to handle translated as + # well as normal (untranslated) attributes. + class MethodsBuilder < Module + def initialize(*attribute_names) + # Although we load the plugin in the included callback method, we + # need to include this module here in advance to ensure that its + # instance methods are included *before* the ones defined here. + include ::Sequel::Plugins::Dirty::InstanceMethods - %w[initial_value column_change column_changed? reset_column].each do |method_name| - define_method method_name do |column| - if attribute_names.map(&:to_sym).include?(column) - super(Mobility.normalize_locale_accessor(column).to_sym) - else - super(column) + %w[initial_value column_change column_changed? reset_column].each do |method_name| + define_method method_name do |column| + if attribute_names.map(&:to_sym).include?(column) + super(Mobility.normalize_locale_accessor(column).to_sym) + else + super(column) + end end end end - end - def included(model_class) - # this just adds Sequel::Plugins::Dirty to @plugins - model_class.plugin :dirty + def included(model_class) + # this just adds Sequel::Plugins::Dirty to @plugins + model_class.plugin :dirty + end end end end diff --git a/spec/mobility/plugins/cache_spec.rb b/spec/mobility/plugins/cache_spec.rb index a50fe5438..a8157f7dc 100644 --- a/spec/mobility/plugins/cache_spec.rb +++ b/spec/mobility/plugins/cache_spec.rb @@ -1,4 +1,5 @@ require "spec_helper" +require "mobility/plugins/cache" describe Mobility::Plugins::Cache do describe "when included into a class" do diff --git a/spec/mobility/plugins/default_spec.rb b/spec/mobility/plugins/default_spec.rb index 93242ed9b..cab38c2c8 100644 --- a/spec/mobility/plugins/default_spec.rb +++ b/spec/mobility/plugins/default_spec.rb @@ -1,4 +1,5 @@ require "spec_helper" +require "mobility/plugins/default" describe Mobility::Plugins::Default do describe "when included into a class" do diff --git a/spec/mobility/plugins/dirty_spec.rb b/spec/mobility/plugins/dirty_spec.rb index 75975d606..13ecfd464 100644 --- a/spec/mobility/plugins/dirty_spec.rb +++ b/spec/mobility/plugins/dirty_spec.rb @@ -1,4 +1,5 @@ require "spec_helper" +require "mobility/plugins/dirty" describe Mobility::Plugins::Dirty do describe ".apply" do diff --git a/spec/mobility/plugins/fallbacks_spec.rb b/spec/mobility/plugins/fallbacks_spec.rb index 0acfe7da6..b28f98956 100644 --- a/spec/mobility/plugins/fallbacks_spec.rb +++ b/spec/mobility/plugins/fallbacks_spec.rb @@ -1,4 +1,5 @@ require "spec_helper" +require "mobility/plugins/fallbacks" describe Mobility::Plugins::Fallbacks do describe "when included into a class" do diff --git a/spec/mobility/plugins/fallthrough_accessors_spec.rb b/spec/mobility/plugins/fallthrough_accessors_spec.rb index 5cfecd518..79bf8fd2e 100644 --- a/spec/mobility/plugins/fallthrough_accessors_spec.rb +++ b/spec/mobility/plugins/fallthrough_accessors_spec.rb @@ -1,4 +1,5 @@ require "spec_helper" +require "mobility/plugins/fallthrough_accessors" describe Mobility::Plugins::FallthroughAccessors do describe "when included into a class" do diff --git a/spec/mobility/plugins/locale_accessors_spec.rb b/spec/mobility/plugins/locale_accessors_spec.rb index dffe79e9d..b59ae4fd7 100644 --- a/spec/mobility/plugins/locale_accessors_spec.rb +++ b/spec/mobility/plugins/locale_accessors_spec.rb @@ -1,4 +1,5 @@ require "spec_helper" +require "mobility/plugins/locale_accessors" describe Mobility::Plugins::LocaleAccessors do describe "when included into a class" do diff --git a/spec/mobility/plugins/presence_spec.rb b/spec/mobility/plugins/presence_spec.rb index 6305143f1..d9913ce54 100644 --- a/spec/mobility/plugins/presence_spec.rb +++ b/spec/mobility/plugins/presence_spec.rb @@ -1,4 +1,5 @@ require "spec_helper" +require "mobility/plugins/presence" describe Mobility::Plugins::Presence do describe "when included into a class" do diff --git a/spec/performance/attributes_spec.rb b/spec/performance/attributes_spec.rb index c703038c7..d0571cb54 100644 --- a/spec/performance/attributes_spec.rb +++ b/spec/performance/attributes_spec.rb @@ -13,7 +13,7 @@ include Mobility end attributes = described_class.new(:accessor, backend: :null) - expect { klass.include attributes }.to allocate_under(100).objects + expect { klass.include attributes }.to allocate_under(120).objects } end From 57759049f968b097df95b5ed56d7a6eaaad6448a Mon Sep 17 00:00:00 2001 From: Chris Salzberg Date: Sat, 5 Aug 2017 12:47:23 +0900 Subject: [PATCH 4/7] Convert autoloads to requires in backend classes --- lib/mobility/attributes.rb | 4 +++- lib/mobility/backend/orm_delegator.rb | 18 ++++++++++++--- lib/mobility/backends.rb | 10 -------- lib/mobility/backends/active_record.rb | 8 ------- lib/mobility/backends/active_record/column.rb | 3 +++ .../active_record/jsonb/query_methods.rb | 2 ++ .../backends/active_record/key_value.rb | 2 ++ .../active_record/key_value/query_methods.rb | 2 ++ .../backends/active_record/pg_hash.rb | 3 +++ .../backends/active_record/serialized.rb | 4 ++++ lib/mobility/backends/active_record/table.rb | 2 ++ lib/mobility/backends/sequel.rb | 8 ------- lib/mobility/backends/sequel/column.rb | 3 +++ .../backends/sequel/column/query_methods.rb | 2 ++ .../backends/sequel/hstore/query_methods.rb | 1 + .../backends/sequel/jsonb/query_methods.rb | 1 + lib/mobility/backends/sequel/key_value.rb | 2 ++ .../sequel/key_value/query_methods.rb | 2 ++ lib/mobility/backends/sequel/pg_hash.rb | 2 ++ .../backends/sequel/postgres_query_methods.rb | 1 - lib/mobility/backends/sequel/serialized.rb | 4 ++++ .../sequel/serialized/query_methods.rb | 2 ++ lib/mobility/backends/sequel/table.rb | 2 ++ .../backends/sequel/table/query_methods.rb | 2 ++ .../mobility/translations_generator.rb | 2 +- .../backends/active_record/column_spec.rb | 3 ++- .../backends/active_record/hstore_spec.rb | 3 ++- .../backends/active_record/jsonb_spec.rb | 3 ++- .../backends/active_record/key_value_spec.rb | 3 ++- .../backends/active_record/serialized_spec.rb | 3 ++- .../backends/active_record/table_spec.rb | 3 ++- spec/mobility/backends/active_record_spec.rb | 2 +- spec/mobility/backends/sequel/column_spec.rb | 3 ++- spec/mobility/backends/sequel/hstore_spec.rb | 3 ++- spec/mobility/backends/sequel/jsonb_spec.rb | 3 ++- .../backends/sequel/key_value_spec.rb | 3 ++- .../backends/sequel/serialized_spec.rb | 3 ++- spec/mobility/backends/sequel/table_spec.rb | 3 ++- spec/mobility/backends/sequel_spec.rb | 4 ++-- .../plugins/active_model/dirty_spec.rb | 4 +++- .../plugins/active_record/dirty_spec.rb | 4 +++- spec/spec_helper.rb | 1 + spec/support/helpers.rb | 23 +++++++++++++++++++ 43 files changed, 117 insertions(+), 49 deletions(-) diff --git a/lib/mobility/attributes.rb b/lib/mobility/attributes.rb index a61c5e552..d34da4970 100644 --- a/lib/mobility/attributes.rb +++ b/lib/mobility/attributes.rb @@ -198,7 +198,9 @@ def define_writer(attribute) end def get_backend_class(backend) - Module === backend ? backend : get_class_from_key(Mobility::Backends, backend) + return backend if Module === backend + require "mobility/backends/#{backend}" + get_class_from_key(Mobility::Backends, backend) end def get_plugin_class(plugin) diff --git a/lib/mobility/backend/orm_delegator.rb b/lib/mobility/backend/orm_delegator.rb index de668756d..621def382 100644 --- a/lib/mobility/backend/orm_delegator.rb +++ b/lib/mobility/backend/orm_delegator.rb @@ -16,12 +16,24 @@ module OrmDelegator # @param [Class] model_class Class of model # @return [Class] Class of backend to use for model def for(model_class) + namespace = name.split('::'.freeze) if Loaded::ActiveRecord && model_class < ::ActiveRecord::Base - const_get(name.split("::".freeze).insert(-2, "ActiveRecord".freeze).join("::".freeze)) + require_backend("active_record", namespace.last.underscore) + const_get(namespace.insert(-2, "ActiveRecord".freeze).join("::".freeze)) elsif Loaded::Sequel && model_class < ::Sequel::Model - const_get(name.split("::".freeze).insert(-2, "Sequel".freeze).join("::".freeze)) + require_backend("sequel", namespace.last.underscore) + const_get(namespace.insert(-2, "Sequel".freeze).join("::".freeze)) else - raise ArgumentError, "#{name.split('::'.freeze).last} backend can only be used by ActiveRecord or Sequel models".freeze + raise ArgumentError, "#{namespace.last} backend can only be used by ActiveRecord or Sequel models".freeze + end + end + + private + + def require_backend(orm, backend) + begin + require "mobility/backends/#{orm}/#{backend}" + rescue LoadError end end end diff --git a/lib/mobility/backends.rb b/lib/mobility/backends.rb index 1b9d4b8ec..0e430553e 100644 --- a/lib/mobility/backends.rb +++ b/lib/mobility/backends.rb @@ -1,14 +1,4 @@ module Mobility module Backends - autoload :ActiveRecord, 'mobility/backends/active_record' - autoload :Column, 'mobility/backends/column' - autoload :HashValued, 'mobility/backends/hash_valued' - autoload :Hstore, 'mobility/backends/hstore' - autoload :Jsonb, 'mobility/backends/jsonb' - autoload :KeyValue, 'mobility/backends/key_value' - autoload :Null, 'mobility/backends/null' - autoload :Sequel, 'mobility/backends/sequel' - autoload :Serialized, 'mobility/backends/serialized' - autoload :Table, 'mobility/backends/table' end end diff --git a/lib/mobility/backends/active_record.rb b/lib/mobility/backends/active_record.rb index 24b970410..c4d53d190 100644 --- a/lib/mobility/backends/active_record.rb +++ b/lib/mobility/backends/active_record.rb @@ -1,14 +1,6 @@ module Mobility module Backends module ActiveRecord - autoload :Column, 'mobility/backends/active_record/column' - autoload :Hstore, 'mobility/backends/active_record/hstore' - autoload :Jsonb, 'mobility/backends/active_record/jsonb' - autoload :KeyValue, 'mobility/backends/active_record/key_value' - autoload :Serialized, 'mobility/backends/active_record/serialized' - autoload :QueryMethods, 'mobility/backends/active_record/query_methods' - autoload :Table, 'mobility/backends/active_record/table' - def setup_query_methods(query_methods) setup do |attributes, options| extend(Module.new do diff --git a/lib/mobility/backends/active_record/column.rb b/lib/mobility/backends/active_record/column.rb index 1781c2016..4f608c69a 100644 --- a/lib/mobility/backends/active_record/column.rb +++ b/lib/mobility/backends/active_record/column.rb @@ -1,3 +1,6 @@ +require "mobility/backends/active_record" +require "mobility/backends/column" + module Mobility module Backends =begin diff --git a/lib/mobility/backends/active_record/jsonb/query_methods.rb b/lib/mobility/backends/active_record/jsonb/query_methods.rb index e3ae46e28..38637503d 100644 --- a/lib/mobility/backends/active_record/jsonb/query_methods.rb +++ b/lib/mobility/backends/active_record/jsonb/query_methods.rb @@ -1,3 +1,5 @@ +require "mobility/backends/active_record/query_methods" + module Mobility module Backends class ActiveRecord::Jsonb::QueryMethods < ActiveRecord::QueryMethods diff --git a/lib/mobility/backends/active_record/key_value.rb b/lib/mobility/backends/active_record/key_value.rb index ccfb3ae01..260756a39 100644 --- a/lib/mobility/backends/active_record/key_value.rb +++ b/lib/mobility/backends/active_record/key_value.rb @@ -1,4 +1,6 @@ # frozen-string-literal: true +require "mobility/backends/active_record" +require "mobility/backends/key_value" require "mobility/active_record/string_translation" require "mobility/active_record/text_translation" diff --git a/lib/mobility/backends/active_record/key_value/query_methods.rb b/lib/mobility/backends/active_record/key_value/query_methods.rb index 7111eea66..b4417a9ff 100644 --- a/lib/mobility/backends/active_record/key_value/query_methods.rb +++ b/lib/mobility/backends/active_record/key_value/query_methods.rb @@ -1,3 +1,5 @@ +require "mobility/backends/active_record/query_methods" + module Mobility module Backends class ActiveRecord::KeyValue::QueryMethods < ActiveRecord::QueryMethods diff --git a/lib/mobility/backends/active_record/pg_hash.rb b/lib/mobility/backends/active_record/pg_hash.rb index 59de1eca2..07f254121 100644 --- a/lib/mobility/backends/active_record/pg_hash.rb +++ b/lib/mobility/backends/active_record/pg_hash.rb @@ -1,3 +1,6 @@ +require "mobility/backends/active_record" +require "mobility/backends/hash_valued" + module Mobility module Backends =begin diff --git a/lib/mobility/backends/active_record/serialized.rb b/lib/mobility/backends/active_record/serialized.rb index 93aa761b6..df23f26c1 100644 --- a/lib/mobility/backends/active_record/serialized.rb +++ b/lib/mobility/backends/active_record/serialized.rb @@ -1,3 +1,7 @@ +require "mobility/backends/active_record" +require "mobility/backends/hash_valued" +require "mobility/backends/serialized" + module Mobility module Backends =begin diff --git a/lib/mobility/backends/active_record/table.rb b/lib/mobility/backends/active_record/table.rb index 9aa792c0f..52ad871a4 100644 --- a/lib/mobility/backends/active_record/table.rb +++ b/lib/mobility/backends/active_record/table.rb @@ -1,4 +1,6 @@ # frozen-string-literal: true +require "mobility/backends/active_record" +require "mobility/backends/table" require "mobility/active_record/model_translation" module Mobility diff --git a/lib/mobility/backends/sequel.rb b/lib/mobility/backends/sequel.rb index 0c325ab92..9e28f5afd 100644 --- a/lib/mobility/backends/sequel.rb +++ b/lib/mobility/backends/sequel.rb @@ -1,14 +1,6 @@ module Mobility module Backends module Sequel - autoload :Column, 'mobility/backends/sequel/column' - autoload :Hstore, 'mobility/backends/sequel/hstore' - autoload :Jsonb, 'mobility/backends/sequel/jsonb' - autoload :KeyValue, 'mobility/backends/sequel/key_value' - autoload :Serialized, 'mobility/backends/sequel/serialized' - autoload :Table, 'mobility/backends/sequel/table' - autoload :QueryMethods, 'mobility/backends/sequel/query_methods' - def setup_query_methods(query_methods) setup do |attributes, options| extend(Module.new do diff --git a/lib/mobility/backends/sequel/column.rb b/lib/mobility/backends/sequel/column.rb index bfe433735..50a0595d8 100644 --- a/lib/mobility/backends/sequel/column.rb +++ b/lib/mobility/backends/sequel/column.rb @@ -1,3 +1,6 @@ +require "mobility/backends/sequel" +require "mobility/backends/column" + module Mobility module Backends =begin diff --git a/lib/mobility/backends/sequel/column/query_methods.rb b/lib/mobility/backends/sequel/column/query_methods.rb index 56cba67a2..3831fb97c 100644 --- a/lib/mobility/backends/sequel/column/query_methods.rb +++ b/lib/mobility/backends/sequel/column/query_methods.rb @@ -1,3 +1,5 @@ +require "mobility/backends/sequel/query_methods" + module Mobility module Backends class Sequel::Column::QueryMethods < Sequel::QueryMethods diff --git a/lib/mobility/backends/sequel/hstore/query_methods.rb b/lib/mobility/backends/sequel/hstore/query_methods.rb index d03fa2013..11a58cbea 100644 --- a/lib/mobility/backends/sequel/hstore/query_methods.rb +++ b/lib/mobility/backends/sequel/hstore/query_methods.rb @@ -1,4 +1,5 @@ require 'mobility/backends/sequel/postgres_query_methods' +require "mobility/backends/sequel/query_methods" Sequel.extension :pg_hstore, :pg_hstore_ops diff --git a/lib/mobility/backends/sequel/jsonb/query_methods.rb b/lib/mobility/backends/sequel/jsonb/query_methods.rb index 0d2fda320..69d8142c1 100644 --- a/lib/mobility/backends/sequel/jsonb/query_methods.rb +++ b/lib/mobility/backends/sequel/jsonb/query_methods.rb @@ -1,4 +1,5 @@ require 'mobility/backends/sequel/postgres_query_methods' +require "mobility/backends/sequel/query_methods" Sequel.extension :pg_json, :pg_json_ops diff --git a/lib/mobility/backends/sequel/key_value.rb b/lib/mobility/backends/sequel/key_value.rb index d690e714d..3003dc374 100644 --- a/lib/mobility/backends/sequel/key_value.rb +++ b/lib/mobility/backends/sequel/key_value.rb @@ -1,4 +1,6 @@ # frozen-string-literal: true +require "mobility/backends/sequel" +require "mobility/backends/key_value" require "mobility/sequel/column_changes" require "mobility/sequel/string_translation" require "mobility/sequel/text_translation" diff --git a/lib/mobility/backends/sequel/key_value/query_methods.rb b/lib/mobility/backends/sequel/key_value/query_methods.rb index 4828d0585..003a33f38 100644 --- a/lib/mobility/backends/sequel/key_value/query_methods.rb +++ b/lib/mobility/backends/sequel/key_value/query_methods.rb @@ -1,3 +1,5 @@ +require "mobility/backends/sequel/query_methods" + module Mobility module Backends class Sequel::KeyValue::QueryMethods < Sequel::QueryMethods diff --git a/lib/mobility/backends/sequel/pg_hash.rb b/lib/mobility/backends/sequel/pg_hash.rb index 3201e98a6..f445a417b 100644 --- a/lib/mobility/backends/sequel/pg_hash.rb +++ b/lib/mobility/backends/sequel/pg_hash.rb @@ -1,3 +1,5 @@ +require "mobility/backends/sequel" +require "mobility/backends/hash_valued" require "mobility/backend/stringify_locale" module Mobility diff --git a/lib/mobility/backends/sequel/postgres_query_methods.rb b/lib/mobility/backends/sequel/postgres_query_methods.rb index 2e4bb8944..361ece964 100644 --- a/lib/mobility/backends/sequel/postgres_query_methods.rb +++ b/lib/mobility/backends/sequel/postgres_query_methods.rb @@ -1,4 +1,3 @@ - module Mobility module Backends module PostgresQueryMethods diff --git a/lib/mobility/backends/sequel/serialized.rb b/lib/mobility/backends/sequel/serialized.rb index d7b86bbef..51ba50b2f 100644 --- a/lib/mobility/backends/sequel/serialized.rb +++ b/lib/mobility/backends/sequel/serialized.rb @@ -1,3 +1,7 @@ +require "mobility/backends/sequel" +require "mobility/backends/hash_valued" +require "mobility/backends/serialized" + module Mobility module Backends =begin diff --git a/lib/mobility/backends/sequel/serialized/query_methods.rb b/lib/mobility/backends/sequel/serialized/query_methods.rb index 4d35bf9e6..82a79b2b9 100644 --- a/lib/mobility/backends/sequel/serialized/query_methods.rb +++ b/lib/mobility/backends/sequel/serialized/query_methods.rb @@ -1,3 +1,5 @@ +require "mobility/backends/sequel/query_methods" + module Mobility module Backends class Sequel::Serialized::QueryMethods < Sequel::QueryMethods diff --git a/lib/mobility/backends/sequel/table.rb b/lib/mobility/backends/sequel/table.rb index 74d2b5a04..b7d78c470 100644 --- a/lib/mobility/backends/sequel/table.rb +++ b/lib/mobility/backends/sequel/table.rb @@ -1,3 +1,5 @@ +require "mobility/backends/sequel" +require "mobility/backends/key_value" require "mobility/sequel/model_translation" module Mobility diff --git a/lib/mobility/backends/sequel/table/query_methods.rb b/lib/mobility/backends/sequel/table/query_methods.rb index aede042ac..fe31a272d 100644 --- a/lib/mobility/backends/sequel/table/query_methods.rb +++ b/lib/mobility/backends/sequel/table/query_methods.rb @@ -1,3 +1,5 @@ +require "mobility/backends/sequel/query_methods" + module Mobility module Backends class Sequel::Table::QueryMethods < Sequel::QueryMethods diff --git a/lib/rails/generators/mobility/translations_generator.rb b/lib/rails/generators/mobility/translations_generator.rb index 7ae1f7c60..2ae7d4d8c 100644 --- a/lib/rails/generators/mobility/translations_generator.rb +++ b/lib/rails/generators/mobility/translations_generator.rb @@ -52,7 +52,7 @@ def self.prepare_for_invocation(name, value) if SUPPORTED_BACKENDS.include?(value) require_relative "./backend_generators/#{value}_backend".freeze Mobility::BackendGenerators.const_get("#{value}_backend".camelcase.freeze) - elsif Mobility::Backends.const_get(value.to_s.camelize.gsub(/\s+/, ''.freeze)) + elsif Mobility::Backends::ActiveRecord.const_get(value.to_s.camelize.gsub(/\s+/, ''.freeze)) raise Thor::Error, "The #{value} backend does not have a translations generator." else raise Thor::Error, "#{value} is not a Mobility backend." diff --git a/spec/mobility/backends/active_record/column_spec.rb b/spec/mobility/backends/active_record/column_spec.rb index 4be8a95dd..9585489b7 100644 --- a/spec/mobility/backends/active_record/column_spec.rb +++ b/spec/mobility/backends/active_record/column_spec.rb @@ -1,6 +1,7 @@ require "spec_helper" -describe Mobility::Backends::ActiveRecord::Column, orm: :active_record do +describe "Mobility::Backends::ActiveRecord::Column", orm: :active_record do + require "mobility/backends/active_record/column" extend Helpers::ActiveRecord context "with no plugins applied" do diff --git a/spec/mobility/backends/active_record/hstore_spec.rb b/spec/mobility/backends/active_record/hstore_spec.rb index 51329a287..187ad442b 100644 --- a/spec/mobility/backends/active_record/hstore_spec.rb +++ b/spec/mobility/backends/active_record/hstore_spec.rb @@ -1,6 +1,7 @@ require "spec_helper" -describe Mobility::Backends::ActiveRecord::Hstore, orm: :active_record, db: :postgres do +describe "Mobility::Backends::ActiveRecord::Hstore", orm: :active_record, db: :postgres do + require "mobility/backends/active_record/hstore" extend Helpers::ActiveRecord context "with no plugins applied" do diff --git a/spec/mobility/backends/active_record/jsonb_spec.rb b/spec/mobility/backends/active_record/jsonb_spec.rb index cdb135ba0..3304c9468 100644 --- a/spec/mobility/backends/active_record/jsonb_spec.rb +++ b/spec/mobility/backends/active_record/jsonb_spec.rb @@ -1,6 +1,7 @@ require "spec_helper" -describe Mobility::Backends::ActiveRecord::Jsonb, orm: :active_record, db: :postgres do +describe "Mobility::Backends::ActiveRecord::Jsonb", orm: :active_record, db: :postgres do + require "mobility/backends/active_record/jsonb" extend Helpers::ActiveRecord context "with no plugins applied" do diff --git a/spec/mobility/backends/active_record/key_value_spec.rb b/spec/mobility/backends/active_record/key_value_spec.rb index 5dfce4659..a78407eef 100644 --- a/spec/mobility/backends/active_record/key_value_spec.rb +++ b/spec/mobility/backends/active_record/key_value_spec.rb @@ -1,6 +1,7 @@ require "spec_helper" -describe Mobility::Backends::ActiveRecord::KeyValue, orm: :active_record do +describe "Mobility::Backends::ActiveRecord::KeyValue", orm: :active_record do + require "mobility/backends/active_record/key_value" extend Helpers::ActiveRecord context "with no plugins applied" do diff --git a/spec/mobility/backends/active_record/serialized_spec.rb b/spec/mobility/backends/active_record/serialized_spec.rb index 461b9ee2e..f05dabf02 100644 --- a/spec/mobility/backends/active_record/serialized_spec.rb +++ b/spec/mobility/backends/active_record/serialized_spec.rb @@ -1,6 +1,7 @@ require "spec_helper" -describe Mobility::Backends::ActiveRecord::Serialized, orm: :active_record do +describe "Mobility::Backends::ActiveRecord::Serialized", orm: :active_record do + require "mobility/backends/active_record/serialized" extend Helpers::ActiveRecord context "with no plugins applied" do diff --git a/spec/mobility/backends/active_record/table_spec.rb b/spec/mobility/backends/active_record/table_spec.rb index fa01e2009..d19312989 100644 --- a/spec/mobility/backends/active_record/table_spec.rb +++ b/spec/mobility/backends/active_record/table_spec.rb @@ -1,6 +1,7 @@ require "spec_helper" -describe Mobility::Backends::ActiveRecord::Table, orm: :active_record do +describe "Mobility::Backends::ActiveRecord::Table", orm: :active_record do + require "mobility/backends/active_record/table" extend Helpers::ActiveRecord before do diff --git a/spec/mobility/backends/active_record_spec.rb b/spec/mobility/backends/active_record_spec.rb index 632dcba38..d37d0dd51 100644 --- a/spec/mobility/backends/active_record_spec.rb +++ b/spec/mobility/backends/active_record_spec.rb @@ -1,6 +1,6 @@ require "spec_helper" -describe Mobility::Backends::ActiveRecord, orm: :active_record do +describe "Mobility::Backends::ActiveRecord", orm: :active_record do context "model with multiple backends" do before do stub_const 'Comment', Class.new(ActiveRecord::Base) diff --git a/spec/mobility/backends/sequel/column_spec.rb b/spec/mobility/backends/sequel/column_spec.rb index f8ff7ca14..04344def0 100644 --- a/spec/mobility/backends/sequel/column_spec.rb +++ b/spec/mobility/backends/sequel/column_spec.rb @@ -1,6 +1,7 @@ require "spec_helper" -describe Mobility::Backends::Sequel::Column, orm: :sequel do +describe "Mobility::Backends::Sequel::Column", orm: :sequel do + require "mobility/backends/sequel/column" extend Helpers::Sequel context "with no plugins applied" do diff --git a/spec/mobility/backends/sequel/hstore_spec.rb b/spec/mobility/backends/sequel/hstore_spec.rb index e5ab679fb..8b39fbef1 100644 --- a/spec/mobility/backends/sequel/hstore_spec.rb +++ b/spec/mobility/backends/sequel/hstore_spec.rb @@ -1,6 +1,7 @@ require "spec_helper" -describe Mobility::Backends::Sequel::Hstore, orm: :sequel, db: :postgres do +describe "Mobility::Backends::Sequel::Hstore", orm: :sequel, db: :postgres do + require "mobility/backends/sequel/hstore" extend Helpers::Sequel context "with no plugins applied" do diff --git a/spec/mobility/backends/sequel/jsonb_spec.rb b/spec/mobility/backends/sequel/jsonb_spec.rb index 72cce73f3..7981862cc 100644 --- a/spec/mobility/backends/sequel/jsonb_spec.rb +++ b/spec/mobility/backends/sequel/jsonb_spec.rb @@ -1,6 +1,7 @@ require "spec_helper" -describe Mobility::Backends::Sequel::Jsonb, orm: :sequel, db: :postgres do +describe "Mobility::Backends::Sequel::Jsonb", orm: :sequel, db: :postgres do + require "mobility/backends/sequel/jsonb" extend Helpers::Sequel context "with no plugins applied" do diff --git a/spec/mobility/backends/sequel/key_value_spec.rb b/spec/mobility/backends/sequel/key_value_spec.rb index d3cbbdfb6..a39d2d890 100644 --- a/spec/mobility/backends/sequel/key_value_spec.rb +++ b/spec/mobility/backends/sequel/key_value_spec.rb @@ -1,6 +1,7 @@ require "spec_helper" -describe Mobility::Backends::Sequel::KeyValue, orm: :sequel do +describe "Mobility::Backends::Sequel::KeyValue", orm: :sequel do + require "mobility/backends/sequel/key_value" extend Helpers::Sequel # Note: the cache is required for the Sequel Table backend, so we need to diff --git a/spec/mobility/backends/sequel/serialized_spec.rb b/spec/mobility/backends/sequel/serialized_spec.rb index b7daef546..916d77129 100644 --- a/spec/mobility/backends/sequel/serialized_spec.rb +++ b/spec/mobility/backends/sequel/serialized_spec.rb @@ -1,6 +1,7 @@ require "spec_helper" -describe Mobility::Backends::Sequel::Serialized, orm: :sequel do +describe "Mobility::Backends::Sequel::Serialized", orm: :sequel do + require "mobility/backends/sequel/serialized" extend Helpers::Sequel context "with no options applied" do diff --git a/spec/mobility/backends/sequel/table_spec.rb b/spec/mobility/backends/sequel/table_spec.rb index 4cd4843fb..8893328e5 100644 --- a/spec/mobility/backends/sequel/table_spec.rb +++ b/spec/mobility/backends/sequel/table_spec.rb @@ -1,6 +1,7 @@ require "spec_helper" -describe Mobility::Backends::Sequel::Table, orm: :sequel do +describe "Mobility::Backends::Sequel::Table", orm: :sequel do + require "mobility/backends/sequel/table" extend Helpers::Sequel # Note: the cache is required for the Sequel Table backend, so we need to diff --git a/spec/mobility/backends/sequel_spec.rb b/spec/mobility/backends/sequel_spec.rb index 820e3dc65..21904d0e5 100644 --- a/spec/mobility/backends/sequel_spec.rb +++ b/spec/mobility/backends/sequel_spec.rb @@ -1,6 +1,6 @@ require "spec_helper" -describe Mobility::Backends::Sequel, orm: :sequel do +describe "Mobility::Backends::Sequel", orm: :sequel do context "model with multiple backends" do before do stub_const 'Comment', Class.new(Sequel::Model) @@ -29,4 +29,4 @@ end end end -end +end if Mobility::Loaded::Sequel diff --git a/spec/mobility/plugins/active_model/dirty_spec.rb b/spec/mobility/plugins/active_model/dirty_spec.rb index f29643dc4..190239bb3 100644 --- a/spec/mobility/plugins/active_model/dirty_spec.rb +++ b/spec/mobility/plugins/active_model/dirty_spec.rb @@ -1,6 +1,8 @@ require "spec_helper" -describe Mobility::Plugins::ActiveModel::Dirty, orm: :active_record do +describe "Mobility::Plugins::ActiveModel::Dirty", orm: :active_record do + require "mobility/plugins/active_model/dirty" + let(:backend_class) do Class.new(Mobility::Backends::Null) do def read(locale, **options) diff --git a/spec/mobility/plugins/active_record/dirty_spec.rb b/spec/mobility/plugins/active_record/dirty_spec.rb index 67a265a52..1c8f03ad2 100644 --- a/spec/mobility/plugins/active_record/dirty_spec.rb +++ b/spec/mobility/plugins/active_record/dirty_spec.rb @@ -1,6 +1,8 @@ require "spec_helper" -describe Mobility::Plugins::ActiveRecord::Dirty, orm: :active_record do +describe "Mobility::Plugins::ActiveRecord::Dirty", orm: :active_record do + require "mobility/plugins/active_record/dirty" + let(:backend_class) do Class.new(Mobility::Backends::Null) do def read(locale, **options) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 88133b632..4f0e1ddfa 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -16,6 +16,7 @@ require 'json' require 'mobility' +require "mobility/backends/null" I18n.enforce_available_locales = true I18n.available_locales = [:en, :ja, :fr, :de, :cz, :pl, :'pt-BR'] diff --git a/spec/support/helpers.rb b/spec/support/helpers.rb index 0dbdfc9b2..8f0dd2917 100644 --- a/spec/support/helpers.rb +++ b/spec/support/helpers.rb @@ -5,6 +5,29 @@ def stringify_keys(hash) result end + def self.included(base) + base.extend LazyDescribedClass + end + + module LazyDescribedClass + # lazy-load described_class if it's a string + def described_class + klass = super + return klass if klass + + # crawl up metadata tree looking for description that can be constantized + this_metadata = metadata + while this_metadata do + candidate = this_metadata[:description_args].first + begin + return candidate.constantize if String === candidate + rescue NameError, NoMethodError + end + this_metadata = this_metadata[:parent_example_group] + end + end + end + module Backend def include_backend_examples *args it_behaves_like "Mobility backend", *args From 1e1e6b3263c635a8c98834326d9255aa1c604954 Mon Sep 17 00:00:00 2001 From: Chris Salzberg Date: Sat, 5 Aug 2017 12:47:39 +0900 Subject: [PATCH 5/7] Split ClassMethods from Setup --- lib/mobility/backend.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/mobility/backend.rb b/lib/mobility/backend.rb index c46ff0734..c6cddb58b 100644 --- a/lib/mobility/backend.rb +++ b/lib/mobility/backend.rb @@ -76,6 +76,7 @@ def initialize(model, attribute, **_) # Extend included class with +setup+ method def self.included(base) base.extend(Setup) + base.extend(ClassMethods) end # @param [String] attribute @@ -115,7 +116,9 @@ def setup_model(model_class, attribute_names, **options) return unless setup_block = @setup_block model_class.class_exec(attribute_names, options, &setup_block) end + end + module ClassMethods # {Attributes} uses this method to get a backend class specific to the # model using the backend. Backend classes can override this method to # return a class specific to the model class using the backend (e.g. From fdbea3c364fed06038ed8e5b3b164486cbe2511d Mon Sep 17 00:00:00 2001 From: Chris Salzberg Date: Sat, 5 Aug 2017 13:01:59 +0900 Subject: [PATCH 6/7] Only rescue LoadError if message matches --- lib/mobility.rb | 9 ++++++--- lib/mobility/backend/orm_delegator.rb | 6 ++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/mobility.rb b/lib/mobility.rb index 9afa4d9fd..00563da8a 100644 --- a/lib/mobility.rb +++ b/lib/mobility.rb @@ -51,7 +51,8 @@ class VersionNotSupportedError < ArgumentError; end require "mobility/active_model" require "mobility/active_record" Loaded::ActiveRecord = true - rescue LoadError + rescue LoadError => e + raise unless e.message =~ /active_record/ Loaded::ActiveRecord = false end @@ -59,7 +60,8 @@ class VersionNotSupportedError < ArgumentError; end require "rails" Loaded::Rails = true require "rails/generators/mobility/generators" - rescue LoadError + rescue LoadError => e + raise unless e.message =~ /rails/ Loaded::Rails = false end @@ -72,7 +74,8 @@ class VersionNotSupportedError < ArgumentError; end require "sequel/plugins/dirty" require "mobility/sequel" Loaded::Sequel = true - rescue LoadError + rescue LoadError => e + raise unless e.message =~ /sequel/ Loaded::Sequel = false end diff --git a/lib/mobility/backend/orm_delegator.rb b/lib/mobility/backend/orm_delegator.rb index 621def382..a17157551 100644 --- a/lib/mobility/backend/orm_delegator.rb +++ b/lib/mobility/backend/orm_delegator.rb @@ -32,8 +32,10 @@ def for(model_class) def require_backend(orm, backend) begin - require "mobility/backends/#{orm}/#{backend}" - rescue LoadError + orm_backend = "mobility/backends/#{orm}/#{backend}" + require orm_backend + rescue LoadError => e + raise unless e.message =~ /#{orm_backend}/ end end end From 1815bc0ccb7358ac57ea44d9dd844d6f6f54103c Mon Sep 17 00:00:00 2001 From: Chris Salzberg Date: Sat, 5 Aug 2017 13:23:16 +0900 Subject: [PATCH 7/7] Bump allocation spec limit --- spec/performance/attributes_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/performance/attributes_spec.rb b/spec/performance/attributes_spec.rb index d0571cb54..e050ed566 100644 --- a/spec/performance/attributes_spec.rb +++ b/spec/performance/attributes_spec.rb @@ -13,7 +13,7 @@ include Mobility end attributes = described_class.new(:accessor, backend: :null) - expect { klass.include attributes }.to allocate_under(120).objects + expect { klass.include attributes }.to allocate_under(125).objects } end