diff --git a/CHANGELOG.md b/CHANGELOG.md index d4a153bb..8894620f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ ([#536](https://github.com/shioyama/mobility/pull/536)) - Support primary keys other then :id on model classes ([#542](https://github.com/shioyama/mobility/pull/542)) +- Make it easier to include modules into backend class + ([#538](https://github.com/shioyama/mobility/pull/538)) ## 1.2 diff --git a/lib/mobility/plugin.rb b/lib/mobility/plugin.rb index 1391b2f1..5b2388bd 100644 --- a/lib/mobility/plugin.rb +++ b/lib/mobility/plugin.rb @@ -15,8 +15,14 @@ module Mobility used to include any module(s) into the backend class, see {Mobility::Plugins::Backend}.) -Also includes a +configure+ class method to apply plugins to a pluggable -({Mobility::Pluggable} instance), with a block. +To define methods on the backend, the plugin +included+ hook also looks for +constants named +BackendMethods+ and/or +BackendClassMethods+ in the plugin +namespace. If it finds these, *and* no included hook has been defined on the +plugin, then it auto-generates an included hook in which the backend class +includes/extends these modules. + +The module also includes a +configure+ class method to apply plugins to a +pluggable ({Mobility::Pluggable} instance), with a block. @example Defining a plugin module MyPlugin @@ -36,6 +42,21 @@ module MyPlugin end end +@example With +BackendMethods+ module + module MyPlugin + extend Mobility::Plugin + + module BackendMethods + def read(locale, **) + # ... + end + + def write(locale, value, **) + # ... + end + end + end + @example Configure an attributes class with plugins class Translations < Mobility::Translations end @@ -95,6 +116,14 @@ def included(pluggable) if defined?(@default) && !pluggable.defaults.has_key?(name = Plugins.lookup_name(self)) pluggable.defaults[name] = @default end + if !method_defined?(:included) && + (defined?(self::BackendMethods) || defined?(self::BackendClassMethods)) + plugin = self + included_hook do |_, backend_class| + backend_class.include(plugin::BackendMethods) if defined?(plugin::BackendMethods) + backend_class.extend(plugin::BackendClassMethods) if defined?(plugin::BackendClassMethods) + end + end super end diff --git a/lib/mobility/plugins/active_record/column_fallback.rb b/lib/mobility/plugins/active_record/column_fallback.rb index a0788782..c580712b 100644 --- a/lib/mobility/plugins/active_record/column_fallback.rb +++ b/lib/mobility/plugins/active_record/column_fallback.rb @@ -13,11 +13,6 @@ module ColumnFallback requires :column_fallback, include: false - included_hook do |_, backend_class| - backend_class.include BackendInstanceMethods - backend_class.extend BackendClassMethods - end - def self.use_column_fallback?(options, locale) case column_fallback = options[:column_fallback] when TrueClass @@ -31,7 +26,7 @@ def self.use_column_fallback?(options, locale) end end - module BackendInstanceMethods + module BackendMethods def read(locale, **) if ColumnFallback.use_column_fallback?(options, locale) model.read_attribute(attribute) diff --git a/lib/mobility/plugins/active_record/dirty.rb b/lib/mobility/plugins/active_record/dirty.rb index 3d2ae071..3abf8d15 100644 --- a/lib/mobility/plugins/active_record/dirty.rb +++ b/lib/mobility/plugins/active_record/dirty.rb @@ -51,12 +51,6 @@ module Dirty end end - included_hook do |_, backend_class| - if options[:dirty] - backend_class.include BackendMethods - end - end - private def dirty_handler_methods @@ -109,8 +103,6 @@ def reload(*) end end end - - BackendMethods = ActiveModel::Dirty::BackendMethods end end diff --git a/lib/mobility/plugins/default.rb b/lib/mobility/plugins/default.rb index d597f512..d56edfc7 100644 --- a/lib/mobility/plugins/default.rb +++ b/lib/mobility/plugins/default.rb @@ -66,11 +66,6 @@ module Default requires :backend, include: :before - # Applies default plugin to attributes. - included_hook do |_klass, backend_class| - backend_class.include(BackendMethods) - end - # Generate a default value for given parameters. # @param [Object, Proc] default_value A default value or Proc # @param [Symbol] locale diff --git a/lib/mobility/plugins/fallbacks.rb b/lib/mobility/plugins/fallbacks.rb index 2d639c1c..e8ea025b 100644 --- a/lib/mobility/plugins/fallbacks.rb +++ b/lib/mobility/plugins/fallbacks.rb @@ -117,7 +117,7 @@ module Fallbacks # Applies fallbacks plugin to attributes. Completely disables fallbacks # on model if option is +false+. included_hook do |_, backend_class| - backend_class.include(BackendInstanceMethods) unless options[:fallbacks] == false + backend_class.include(BackendMethods) unless options[:fallbacks] == false # This is weird. We need to find a better way to allow customization of # rarely-customized code like this. backend_class.define_method(:generate_fallbacks, &method(:generate_fallbacks)) @@ -136,7 +136,7 @@ def [](locale) end end - module BackendInstanceMethods + module BackendMethods def read(locale, fallback: true, **kwargs) return super(locale, **kwargs) if !fallback || kwargs[:locale] diff --git a/lib/mobility/plugins/presence.rb b/lib/mobility/plugins/presence.rb index 5237949e..07a69b55 100644 --- a/lib/mobility/plugins/presence.rb +++ b/lib/mobility/plugins/presence.rb @@ -18,28 +18,25 @@ module Presence default true requires :backend, include: :before - # Applies presence plugin to attributes. - included_hook do |_, backend_class| - backend_class.include(BackendMethods) if options[:presence] - end - module BackendMethods # @!group Backend Accessors # @!macro backend_reader # @option options [Boolean] presence # *false* to disable presence filter. - def read(locale, **options) - options.delete(:presence) == false ? super : Presence[super] + def read(locale, **kwargs) + return super unless options[:presence] + kwargs.delete(:presence) == false ? super : Presence[super] end # @!macro backend_writer # @option options [Boolean] presence # *false* to disable presence filter. - def write(locale, value, **options) - if options.delete(:presence) == false + def write(locale, value, **kwargs) + return super unless options[:presence] + if kwargs.delete(:presence) == false super else - super(locale, Presence[value], **options) + super(locale, Presence[value], **kwargs) end end # @!endgroup diff --git a/lib/mobility/plugins/sequel/column_fallback.rb b/lib/mobility/plugins/sequel/column_fallback.rb index fdfd6aac..3e4cd3a2 100644 --- a/lib/mobility/plugins/sequel/column_fallback.rb +++ b/lib/mobility/plugins/sequel/column_fallback.rb @@ -13,11 +13,6 @@ module ColumnFallback requires :column_fallback, include: false - included_hook do |_, backend_class| - backend_class.include BackendInstanceMethods - backend_class.extend BackendClassMethods - end - def self.use_column_fallback?(options, locale) case column_fallback = options[:column_fallback] when TrueClass @@ -31,7 +26,7 @@ def self.use_column_fallback?(options, locale) end end - module BackendInstanceMethods + module BackendMethods def read(locale, **) if ColumnFallback.use_column_fallback?(options, locale) model[attribute.to_sym]