class Mobility::Backends::ActiveRecord::KeyValue

Implements the {Mobility::Backends::KeyValue} backend for ActiveRecord models.

@example

class Post < ApplicationRecord
  extend Mobility
  translates :title, backend: :key_value, association_name: :translations, type: :string
end

post = Post.create(title: "foo")
post.translations
#=> #<ActiveRecord::Associations::CollectionProxy ... >
post.translations.first.value
#=> "foo"
post.translations.first.class
#=> Mobility::ActiveRercord::StringTranslation

Public Class Methods

apply_scope(relation, predicate, locale = Mobility.locale, invert: false) click to toggle source

Joins translations using either INNER/OUTER join appropriate to the query. @param [ActiveRecord::Relation] relation Relation to scope @param [Object] predicate Arel predicate @param [Symbol] locale (Mobility.locale) Locale @option [Boolean] invert @return [ActiveRecord::Relation] relation Relation with joins applied (if needed)

# File lib/mobility/backends/active_record/key_value.rb, line 60
def apply_scope(relation, predicate, locale = Mobility.locale, invert: false)
  visitor = Visitor.new(self, locale)
  visitor.accept(predicate).inject(relation) do |rel, (attr, join_type)|
    join_type &&= ::Arel::Nodes::InnerJoin if invert
    join_translations(rel, attr, locale, join_type)
  end
end
build_node(attr, locale) click to toggle source

@param [String] attr Attribute name @param [Symbol] _locale Locale @return [Mobility::Plugins::Arel::Attribute] Arel attribute for aliased

translation table value column
# File lib/mobility/backends/active_record/key_value.rb, line 49
def build_node(attr, locale)
  aliased_table = class_name.arel_table.alias(table_alias(attr, locale))
  Plugins::Arel::Attribute.new(aliased_table, value_column, locale, self, attr.to_sym)
end
configure(options) click to toggle source

@!group Backend Configuration @option (see Mobility::Backends::KeyValue::ClassMethods#configure) @raise (see Mobility::Backends::KeyValue::ClassMethods#configure)

Calls superclass method
# File lib/mobility/backends/active_record/key_value.rb, line 34
def configure(options)
  super
  if type = options[:type]
    options[:association_name] ||= :"#{options[:type]}_translations"
    options[:class_name]       ||= const_get("#{type.capitalize}Translation")
  end
rescue NameError
  raise ArgumentError, "You must define a Mobility::Backends::ActiveRecord::KeyValue::#{type.capitalize}Translation class."
end

Private Class Methods

already_joined?(relation, name, locale, join_type) click to toggle source
# File lib/mobility/backends/active_record/key_value.rb, line 81
def already_joined?(relation, name, locale, join_type)
  if join = get_join(relation, name, locale)
    return true if (join_type == ::Arel::Nodes::OuterJoin) || (::Arel::Nodes::InnerJoin === join)
    relation.joins_values = relation.joins_values - [join]
  end
  false
end
get_join(relation, name, locale) click to toggle source
# File lib/mobility/backends/active_record/key_value.rb, line 89
def get_join(relation, name, locale)
  relation.joins_values.find do |v|
    (::Arel::Nodes::Join === v) && (v.left.name == (table_alias(name, locale)))
  end
end
join_translations(relation, key, locale, join_type) click to toggle source
# File lib/mobility/backends/active_record/key_value.rb, line 70
def join_translations(relation, key, locale, join_type)
  return relation if already_joined?(relation, key, locale, join_type)
  m = model_class.arel_table
  t = class_name.arel_table.alias(table_alias(key, locale))
  relation.joins(m.join(t, join_type).
                 on(t[key_column].eq(key).
                    and(t[:locale].eq(locale).
                        and(t[:"#{belongs_to}_type"].eq(model_class.base_class.name).
                            and(t[:"#{belongs_to}_id"].eq(m[:id]))))).join_sources)
end

Public Instance Methods

translation_for(locale, **) click to toggle source

Returns translation for a given locale, or builds one if none is present. @param [Symbol] locale @return [Mobility::Backends::ActiveRecord::KeyValue::TextTranslation,Mobility::Backends::ActiveRecord::KeyValue::StringTranslation]

# File lib/mobility/backends/active_record/key_value.rb, line 206
def translation_for(locale, **)
  translation = translations.find do |t|
    t.send(key_column) == attribute && t.locale == locale.to_s
  end
  translation ||= translations.build(locale: locale, key_column => attribute)
  translation
end