Skip to content

Commit

Permalink
Convert AttributeMethods into plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
shioyama committed Nov 27, 2017
1 parent 586353b commit d1e83a1
Show file tree
Hide file tree
Showing 11 changed files with 165 additions and 98 deletions.
1 change: 0 additions & 1 deletion lib/mobility.rb
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ def extended(model_class)

if Loaded::ActiveRecord
model_class.include(ActiveRecord) if model_class < ::ActiveRecord::Base
model_class.include(ActiveRecord::AttributeMethods) if model_class.ancestors.include?(::ActiveRecord::AttributeMethods)
end

if Loaded::Sequel
Expand Down
1 change: 0 additions & 1 deletion lib/mobility/active_record.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ module Mobility
=end
module ActiveRecord
require "mobility/active_record/attribute_methods"
require "mobility/active_record/uniqueness_validator"

def self.included(model_class)
Expand Down
36 changes: 0 additions & 36 deletions lib/mobility/active_record/attribute_methods.rb

This file was deleted.

4 changes: 3 additions & 1 deletion lib/mobility/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,16 @@ def initialize
dirty: false,
fallbacks: nil,
presence: true,
default: nil
default: nil,
attribute_methods: false
}
@plugins = %i[
cache
dirty
fallbacks
presence
default
attribute_methods
fallthrough_accessors
locale_accessors
]
Expand Down
39 changes: 39 additions & 0 deletions lib/mobility/plugins/active_record/attribute_methods.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
module Mobility
module Plugins
=begin
Module builder adding translated attributes to #attributes hash on model
instance. See {Mobility::Plugins::AttributeMethods} for further details.
=end
module ActiveRecord
module TranslatedAttributes
def translated_attributes
{}
end

def attributes
super.merge(translated_attributes)
end
end

class AttributeMethods < Module
def initialize(*attribute_names)
include TranslatedAttributes
define_method :translated_attributes do
super().merge(attribute_names.inject({}) do |attributes, name|
attributes.merge(name.to_s => send(name))
end)
end
delegate :translated_attribute_names, to: :class
end

def included(model_class)
model_class.class_eval do
define_method :untranslated_attributes, ::ActiveRecord::Base.instance_method(:attributes)
end
end
end
end
end
end
40 changes: 40 additions & 0 deletions lib/mobility/plugins/attribute_methods.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
module Mobility
module Plugins
=begin
Adds translated attribute names and values to the hash returned by #attributes.
Also adds a method #translated_attributes with names and values of translated
attributes only.
@note Adding translated attributes to #attributes can have unexpected
consequences, since these values are not true attribute values.
=end
module AttributeMethods
class << self
# Applies attribute_methods plugin for a given option value.
# @param [Attributes] attributes
# @param [Boolean] option Value of option
# @raise [ArgumentError] if model class does not support dirty tracking
def apply(attributes, option)
if option
include_attribute_methods_module(attributes.model_class, *attributes.names)
end
end

private

def include_attribute_methods_module(model_class, *attribute_names)
module_builder =
if Loaded::ActiveRecord && model_class.ancestors.include?(::ActiveRecord::AttributeMethods)
require "mobility/plugins/active_record/attribute_methods"
Plugins::ActiveRecord::AttributeMethods
else
raise ArgumentError, "#{model_class} does not support AttributeMethods plugin."
end
model_class.include module_builder.new(*attribute_names)
end
end
end
end
end
4 changes: 2 additions & 2 deletions spec/active_record/models.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
class Post < ActiveRecord::Base
extend Mobility
translates :title, backend: :key_value, cache: true, locale_accessors: true, dirty: true, type: :string
translates :content, backend: :key_value, cache: true, locale_accessors: true, dirty: true, type: :text
translates :title, backend: :key_value, cache: true, locale_accessors: true, dirty: true, type: :string, attribute_methods: true
translates :content, backend: :key_value, cache: true, locale_accessors: true, dirty: true, type: :text, attribute_methods: true
end

class FallbackPost < ActiveRecord::Base
Expand Down
27 changes: 27 additions & 0 deletions spec/integration/active_record_compatibility_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,31 @@
expect(post.title_ja).to eq(nil)
end
end

describe "#attributes" do
it "includes both original and translated attributes" do
post = Post.new
post.title = "foo"
post.content = "bar"
expect(post.attributes).to eq({ "published" => post.published, "id" => post.id, "title" => "foo", "content" => "bar" })
end
end

describe "#translated_attributes" do
it "includes only translated attributes" do
post = Post.new
post.title = "foo"
post.content = "bar"
expect(post.translated_attributes).to eq({ "title" => "foo", "content" => "bar" }) end
end

describe "#untranslated_attributes" do
it "includes only original attributes" do
post = Post.new
post.title = "foo"
post.content = "bar"
expect(post.untranslated_attributes).to eq({ "published" => post.published, "id" => post.id })
end

end
end
56 changes: 0 additions & 56 deletions spec/mobility/active_record/attribute_methods_spec.rb

This file was deleted.

53 changes: 53 additions & 0 deletions spec/mobility/plugins/active_record/attribute_methods_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
require "spec_helper"

describe Mobility::Plugins::ActiveRecord::AttributeMethods, orm: :active_record do
before do
stub_const 'Article', Class.new(ActiveRecord::Base)
Article.extend Mobility
Article.class_eval do
extend Mobility
translates :title, backend: :null, attribute_methods: true

def title
"foo"
end
end
end
let(:untranslated_attributes) do
{
"id" => nil,
"slug" => nil,
"published" => nil,
"created_at" => nil,
"updated_at" => nil
}
end

subject { Article.new }

describe "#translated_attribute_names" do
it 'returns title' do
expect(subject.translated_attribute_names).to include('title')
end
end

describe "#translated_attributes" do
it "returns hash of translated attribute names/values" do
expect(subject.translated_attributes).to eq("title" => "foo")
end
end

describe "#attributes" do
it "adds translated attributes to normal attributes" do
expect(subject.attributes).to eq(
untranslated_attributes.merge("title" => "foo")
)
end
end

describe "#untranslated_attributes" do
it "returns original value of attributes method" do
expect(subject.untranslated_attributes).to eq(untranslated_attributes)
end
end
end if Mobility::Loaded::ActiveRecord
2 changes: 1 addition & 1 deletion spec/performance/attributes_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
extend Mobility
end
attributes = described_class.new(backend: :null)
expect { klass.include attributes }.to allocate_under(125).objects
expect { klass.include attributes }.to allocate_under(150).objects
}
end

Expand Down

0 comments on commit d1e83a1

Please sign in to comment.