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
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
@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
@!group Backend
Configuration @option (see Mobility::Backends::KeyValue::ClassMethods#configure
) @raise (see Mobility::Backends::KeyValue::ClassMethods#configure
)
# 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
# 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
# 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
# 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
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