From 37d6ac339a2e9e7f44da921a3a8378ac4def5238 Mon Sep 17 00:00:00 2001 From: Chris Salzberg Date: Sun, 17 Oct 2021 21:36:16 +0900 Subject: [PATCH 1/5] Automatically include BackendMethods and/or BackendClassMethods With this change, if no included hook is defined on a plugin *and* the plugin defines module(s) named BackendMethods (instance methods) and/or BackendClassMethods (class methods), a hook is auto-defined to include/extend those modules from the backend class. --- lib/mobility/plugin.rb | 8 ++++++++ .../plugins/active_record/column_fallback.rb | 7 +------ lib/mobility/plugins/active_record/dirty.rb | 8 +------- lib/mobility/plugins/default.rb | 5 ----- lib/mobility/plugins/presence.rb | 17 +++++++---------- lib/mobility/plugins/sequel/column_fallback.rb | 7 +------ 6 files changed, 18 insertions(+), 34 deletions(-) diff --git a/lib/mobility/plugin.rb b/lib/mobility/plugin.rb index 1391b2f15..47fdd7edf 100644 --- a/lib/mobility/plugin.rb +++ b/lib/mobility/plugin.rb @@ -95,6 +95,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 a07887824..c580712b1 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 3d2ae0711..406df2330 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 @@ -110,7 +104,7 @@ def reload(*) end end - BackendMethods = ActiveModel::Dirty::BackendMethods + BackendInstanceMethods = ActiveModel::Dirty::BackendMethods end end diff --git a/lib/mobility/plugins/default.rb b/lib/mobility/plugins/default.rb index d597f5127..d56edfc7d 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/presence.rb b/lib/mobility/plugins/presence.rb index 5237949ee..07a69b55f 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 fdfd6aac6..3e4cd3a2d 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] From 21c5cbf6e975f0c3c0e6097951f75cea6c6766e0 Mon Sep 17 00:00:00 2001 From: Chris Salzberg Date: Sun, 17 Oct 2021 21:40:14 +0900 Subject: [PATCH 2/5] Delete unused constant alias --- lib/mobility/plugins/active_record/dirty.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/mobility/plugins/active_record/dirty.rb b/lib/mobility/plugins/active_record/dirty.rb index 406df2330..3abf8d15d 100644 --- a/lib/mobility/plugins/active_record/dirty.rb +++ b/lib/mobility/plugins/active_record/dirty.rb @@ -103,8 +103,6 @@ def reload(*) end end end - - BackendInstanceMethods = ActiveModel::Dirty::BackendMethods end end From 7ceeff73f02b9c0ae813487c7cde53427c140aaa Mon Sep 17 00:00:00 2001 From: Chris Salzberg Date: Sun, 17 Oct 2021 21:40:40 +0900 Subject: [PATCH 3/5] BackendInstanceMethods -> BackendMethods --- lib/mobility/plugins/fallbacks.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/mobility/plugins/fallbacks.rb b/lib/mobility/plugins/fallbacks.rb index 2d639c1cf..e8ea025b9 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] From dc2aedded5fe10f5bfdc2ce83c0f863813b13776 Mon Sep 17 00:00:00 2001 From: Chris Salzberg Date: Sun, 17 Oct 2021 21:45:09 +0900 Subject: [PATCH 4/5] Add some inline docs about BackendMethods module auto-inclusion --- lib/mobility/plugin.rb | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/lib/mobility/plugin.rb b/lib/mobility/plugin.rb index 47fdd7edf..5b2388bd9 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 From 6c4b96bb15196b6aac514abfc36aa3f54ad0d23e Mon Sep 17 00:00:00 2001 From: Chris Salzberg Date: Fri, 5 Nov 2021 13:43:51 +0900 Subject: [PATCH 5/5] Update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d4a153bbc..8894620f1 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