localizable_model 0.6.3 → 0.6.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 48163bd7ceadfa0afbf5b33da0fb3ac60de012c958da3398eba26ebc9219f1ff
4
- data.tar.gz: a56cdca02c5be879ed05b9fce006adab46f6f7d269ff51f66c0d63447faadc9c
3
+ metadata.gz: aa4b3cecd47009c23bced97ef733cb34a052d0f066dabf8bbcae2c5a4283dc15
4
+ data.tar.gz: 1899ba6b4ff4806f92b4939098c8ae69f004da8e1a06ee8a1779e141f60dcbbd
5
5
  SHA512:
6
- metadata.gz: 72f43ffba42d4ed42bfa9d3f67bed476358ee249893462aec1d720fa24845a314279c5a4dd05311d05df99061b8582b5ddc6b335470953a91749f381ca9a3b53
7
- data.tar.gz: b002bdc0ca4628c17c288d1f5e64b883ba70f285c8084068721b9e9eb88e1e1a38e551f0b531a0ba598658fab19fd05d7b6b66c2b0f38e4461cc86c9e94968ee
6
+ metadata.gz: 5bf37f75cdbb03226737be1fc26fc5b137b8e2cc7167d4d353e9d936a25a18594be731dbd8993eb52658661ed683cfd9123f2e2b7037593e485b710475f290d9
7
+ data.tar.gz: 601c0947961bf37ba06702443027b9b817ad9f954ea6d70523752c30830f647f9a0d3e03d111b6a75919dcb84afe78826e95a7ff7f545d0f36d75490df85237f
data/README.md CHANGED
@@ -1,9 +1,5 @@
1
1
  [![Version](https://img.shields.io/gem/v/localizable_model.svg?style=flat)](https://rubygems.org/gems/localizable_model)
2
- [![Build Status](https://travis-ci.org/anyone-oslo/localizable_model.svg?branch=master)](https://travis-ci.org/anyone-oslo/localizable_model)
3
- [![Code Climate](https://codeclimate.com/github/anyone-oslo/localizable_model/badges/gpa.svg)](https://codeclimate.com/github/anyone-oslo/localizable_model)
4
- [![Test Coverage](https://codeclimate.com/github/anyone-oslo/localizable_model/badges/coverage.svg)](https://codeclimate.com/github/anyone-oslo/localizable_model)
5
- [![Inline docs](http://inch-ci.org/github/anyone-oslo/localizable_model.svg)](http://inch-ci.org/github/anyone-oslo/localizable_model)
6
- [![Security](https://hakiri.io/github/anyone-oslo/localizable_model/master.svg)](https://hakiri.io/github/anyone-oslo/localizable_model/master)
2
+ [![Build](https://github.com/anyone-oslo/localizable_model/actions/workflows/build.yml/badge.svg)](https://github.com/anyone-oslo/localizable_model/actions/workflows/build.yml)
7
3
 
8
4
  # LocalizableModel
9
5
 
data/Rakefile CHANGED
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "bundler/gem_tasks"
2
4
  require "rspec/core/rake_task"
3
5
 
4
- APP_RAKEFILE = "spec/internal/Rakefile".freeze
6
+ APP_RAKEFILE = "spec/internal/Rakefile"
5
7
  load "rails/tasks/engine.rake"
6
8
 
7
9
  RSpec::Core::RakeTask.new
@@ -1,15 +1,15 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  class Localization < ActiveRecord::Base
4
4
  belongs_to :localizable, polymorphic: true, optional: true, touch: true
5
5
 
6
6
  class << self
7
7
  def locales
8
- order("locale ASC").pluck(Arel.sql("DISTINCT locale"))
8
+ order(:locale).pluck(Arel.sql("DISTINCT locale"))
9
9
  end
10
10
 
11
11
  def names
12
- order("name ASC").pluck(Arel.sql("DISTINCT name"))
12
+ order(:name).pluck(Arel.sql("DISTINCT name"))
13
13
  end
14
14
  end
15
15
 
@@ -20,6 +20,6 @@ class Localization < ActiveRecord::Base
20
20
  delegate :empty?, to: :to_s
21
21
 
22
22
  def translate(locale)
23
- localizable.localizations.find_by(name: name, locale: locale)
23
+ localizable.localizations.find_by(name:, locale:)
24
24
  end
25
25
  end
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  module LocalizableModel
4
4
  # = LocalizableModel::ActiveRecordExtension
@@ -19,20 +19,26 @@ module LocalizableModel
19
19
  # end
20
20
  # end
21
21
  #
22
- def localizable(&block)
23
- unless is_a?(LocalizableModel::ClassMethods)
24
- send :extend, LocalizableModel::ClassMethods
25
- send :include, LocalizableModel::InstanceMethods
26
- has_many(:localizations,
27
- as: :localizable,
28
- dependent: :destroy,
29
- autosave: true)
30
- before_save :cleanup_localizations!
31
- end
32
- localizable_configuration.instance_eval(&block) if block_given?
22
+ def localizable(&)
23
+ extend_with_localizable_model!
24
+ localizable_configuration.instance_eval(&) if block_given?
33
25
  define_localizable_methods!
34
26
  end
27
+
28
+ def extend_with_localizable_model!
29
+ return if is_a?(LocalizableModel::ClassMethods)
30
+
31
+ send :extend, LocalizableModel::ClassMethods
32
+ send :include, LocalizableModel::InstanceMethods
33
+ has_many(:localizations,
34
+ as: :localizable,
35
+ dependent: :destroy,
36
+ autosave: true)
37
+ before_save :cleanup_localizations!
38
+ end
35
39
  end
36
40
  end
37
41
 
38
- ActiveRecord::Base.send(:extend, LocalizableModel::ActiveRecordExtension)
42
+ ActiveSupport.on_load(:active_record) do
43
+ extend LocalizableModel::ActiveRecordExtension
44
+ end
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  module LocalizableModel
4
4
  class AnyLocalizer
@@ -30,15 +30,15 @@ module LocalizableModel
30
30
  end
31
31
 
32
32
  def localized?(attribute)
33
- !localized(attribute).blank?
33
+ localized(attribute).present?
34
34
  end
35
35
 
36
36
  def localized(attribute)
37
37
  localized = locales.inject(nil) do |str, l|
38
- str ||= -> {
38
+ str || lambda {
39
39
  value = record.localize(l).send(attribute)
40
- value.blank? ? nil : value
41
- }.call()
40
+ value.presence
41
+ }.call
42
42
  end
43
43
  localized || ""
44
44
  end
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  module LocalizableModel
4
4
  # = LocalizableModel::ClassMethods
@@ -21,7 +21,7 @@ module LocalizableModel
21
21
  #
22
22
  def localized(locale)
23
23
  in_locale(locale)
24
- .where("localizations.locale = ?", locale)
24
+ .where(localizations: { locale: })
25
25
  .references(:localizations)
26
26
  end
27
27
 
@@ -37,16 +37,10 @@ module LocalizableModel
37
37
  private
38
38
 
39
39
  def define_localizable_methods!
40
- localizable_configuration.attributes.keys.each do |name|
41
- define_method name do
42
- localizer.get(name).to_s
43
- end
44
- define_method "#{name}?" do
45
- localizer.value_for?(name)
46
- end
47
- define_method "#{name}=" do |value|
48
- localizer.set(name, value)
49
- end
40
+ localizable_configuration.attributes.each_key do |name|
41
+ define_method(name) { localizer.get(name).to_s }
42
+ define_method("#{name}?") { localizer.value_for?(name) }
43
+ define_method("#{name}=") { |value| localizer.set(name, value) }
50
44
  end
51
45
  end
52
46
 
@@ -1,9 +1,9 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  module LocalizableModel
4
4
  class Configuration
5
5
  def initialize(attributes = nil)
6
- @attributes = attributes
6
+ @attribute_table = attributes
7
7
  end
8
8
 
9
9
  def attribute(attribute_name, options = {})
@@ -36,13 +36,14 @@ module LocalizableModel
36
36
 
37
37
  def hashify(list)
38
38
  return list if list.is_a?(Hash)
39
- list.each_with_object({}) do |e, a|
40
- a[e] = {}
39
+
40
+ list.index_with do |_e|
41
+ {}
41
42
  end
42
43
  end
43
44
 
44
45
  def attribute_table
45
- @attributes ||= {}
46
+ @attribute_table ||= {}
46
47
  end
47
48
  end
48
49
  end
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  module LocalizableModel
4
4
  class Engine < ::Rails::Engine
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  module LocalizableModel
4
4
  # = LocalizableModel::InstanceMethods
@@ -19,9 +19,10 @@ module LocalizableModel
19
19
 
20
20
  # Returns an AnyLocalizer for the model.
21
21
  #
22
- def any_locale
22
+ def any_localizer
23
23
  @any_localizer ||= AnyLocalizer.new(self)
24
24
  end
25
+ alias any_locale any_localizer
25
26
 
26
27
  # Setter for locale
27
28
  #
@@ -89,8 +90,8 @@ module LocalizableModel
89
90
  # A localized model responds to :foo, :foo= and :foo?
90
91
  #
91
92
  def respond_to?(method_name, *args)
92
- requested_attribute, = method_name.to_s.match(/(.*?)([\?=]?)$/)[1..2]
93
- localizer.attribute?(requested_attribute.to_sym) ? true : super
93
+ requested_attribute, = method_name.to_s.match(/(.*?)([?=]?)$/)[1..2]
94
+ localizer.attribute?(requested_attribute.to_sym) || super
94
95
  end
95
96
 
96
97
  alias translate localize
@@ -113,9 +114,13 @@ module LocalizableModel
113
114
  localizer.cleanup_localizations!
114
115
  end
115
116
 
117
+ def respond_to_missing?(method_name, include_private = false)
118
+ localizer.attribute?(method_to_attr(method_name)) || super
119
+ end
120
+
116
121
  def method_missing(method_name, *args)
117
122
  attr = method_to_attr(method_name)
118
- super unless localizer.attribute?(attr)
123
+ return super unless localizer.attribute?(attr)
119
124
 
120
125
  case method_name.to_s
121
126
  when /\?$/
@@ -128,7 +133,7 @@ module LocalizableModel
128
133
  end
129
134
 
130
135
  def method_to_attr(method_name)
131
- method_name.to_s.match(/(.*?)([\?=]?)$/)[1].to_sym
136
+ method_name.to_s.match(/(.*?)([?=]?)$/)[1].to_sym
132
137
  end
133
138
  end
134
139
  end
@@ -1,16 +1,15 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  module LocalizableModel
4
4
  class Localizer
5
5
  attr_accessor :locale
6
+
6
7
  def initialize(model)
7
8
  @model = model
8
9
  @configuration = model.class.localizable_configuration
9
10
  end
10
11
 
11
- def attribute?(attribute)
12
- @configuration.attribute?(attribute)
13
- end
12
+ delegate :attribute?, to: :@configuration
14
13
 
15
14
  def locales
16
15
  @model.localizations.map(&:locale).uniq
@@ -28,7 +27,7 @@ module LocalizableModel
28
27
  end
29
28
 
30
29
  def get(attribute, options = {})
31
- get_options = { locale: locale }.merge(options)
30
+ get_options = { locale: }.merge(options)
32
31
  find_localizations(
33
32
  attribute.to_s,
34
33
  get_options[:locale].to_s
@@ -40,7 +39,7 @@ module LocalizableModel
40
39
  end
41
40
 
42
41
  def set(attribute, value, options = {})
43
- set_options = { locale: locale }.merge(options)
42
+ set_options = { locale: }.merge(options)
44
43
  if value.is_a?(Hash) || value.is_a?(ActionController::Parameters)
45
44
  value.each { |loc, val| set(attribute, val, locale: loc) }
46
45
  else
@@ -72,11 +71,12 @@ module LocalizableModel
72
71
 
73
72
  def get_value(attribute, locale)
74
73
  localization = find_localizations(attribute, locale).try(&:first)
75
- localization.value if localization
74
+ localization&.value
76
75
  end
77
76
 
78
77
  def require_locale!(attribute, locale)
79
78
  return if locale
79
+
80
80
  raise(ArgumentError,
81
81
  "Tried to set :#{attribute}, but no locale has been set")
82
82
  end
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  module LocalizableModel
4
4
  # = LocalizableModel::ScopeExtension
@@ -20,10 +20,51 @@ module LocalizableModel
20
20
  self
21
21
  end
22
22
 
23
+ # Orders results by localized attribute values.
24
+ #
25
+ # Product.in_locale(:nb).order_by_localization(:name)
26
+ # Product.in_locale(:en).order_by_localization(:name, :description)
27
+ #
28
+ def order_by_localization(*attributes)
29
+ attributes = attributes.flatten.map(&:to_s)
30
+
31
+ require_localized_attributes!(attributes)
32
+ order(*attributes.map { |attr| order_by_localization_clause(attr) })
33
+ end
34
+
23
35
  protected
24
36
 
25
37
  def localize_records
26
38
  @records.each { |r| r.localize!(@locale) }
27
39
  end
40
+
41
+ private
42
+
43
+ def localization_values
44
+ Localization
45
+ .arel_table
46
+ .project(Localization.arel_table[:value])
47
+ .where(Localization.arel_table[:localizable_id].eq(arel_table[:id]))
48
+ .where(Localization.arel_table[:localizable_type].eq(name))
49
+ end
50
+
51
+ def order_by_localization_clause(attribute)
52
+ Arel::Nodes::Ascending.new(
53
+ localization_values
54
+ .where(Localization.arel_table[:name].eq(attribute))
55
+ .where(Localization.arel_table[:locale].eq(@locale.to_s))
56
+ ).nulls_last
57
+ end
58
+
59
+ def require_localized_attributes!(attributes)
60
+ raise ArgumentError, "No attributes specified" if attributes.empty?
61
+
62
+ invalid = attributes.reject do |attr|
63
+ klass.localized_attributes.include?(attr.to_sym)
64
+ end
65
+ return if invalid.empty?
66
+
67
+ raise ArgumentError, "#{invalid.join(', ')} are not localized attributes"
68
+ end
28
69
  end
29
70
  end
@@ -1,5 +1,5 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  module LocalizableModel
4
- VERSION = "0.6.3".freeze unless LocalizableModel.const_defined?("VERSION")
4
+ VERSION = "0.6.5" unless LocalizableModel.const_defined?("VERSION")
5
5
  end
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  load "localizable_model/active_record_extension.rb"
4
4
  load "localizable_model/any_localizer.rb"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "rails/generators/active_record/migration"
2
4
 
3
5
  module LocalizableModel
@@ -6,7 +8,7 @@ module LocalizableModel
6
8
  include ActiveRecord::Generators::Migration
7
9
 
8
10
  desc "Creates the LocalizableModel migration"
9
- source_root File.expand_path("../templates", __FILE__)
11
+ source_root File.expand_path("templates", __dir__)
10
12
 
11
13
  def copy_files
12
14
  migration_template(
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class CreateLocalizations < ActiveRecord::Migration
2
4
  def change
3
5
  create_table :localizations do |t|
@@ -6,9 +8,9 @@ class CreateLocalizations < ActiveRecord::Migration
6
8
  t.string :locale
7
9
  t.text :value, limit: 16_777_215
8
10
  t.timestamps null: false
9
- t.index([:localizable_id, :localizable_type, :name, :locale],
11
+ t.index(%i[localizable_id localizable_type name locale],
10
12
  name: "index_localizations_on_locale")
11
- t.index [:localizable_id, :localizable_type]
13
+ t.index %i[localizable_id localizable_type]
12
14
  end
13
15
  end
14
16
  end
metadata CHANGED
@@ -1,97 +1,26 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: localizable_model
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.3
4
+ version: 0.6.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Inge Jørgensen
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2019-02-09 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: mysql2
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: pg
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: 0.18.3
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: 0.18.3
41
- - !ruby/object:Gem::Dependency
42
- name: rspec-rails
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: 3.5.1
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: 3.5.1
55
- - !ruby/object:Gem::Dependency
56
- name: factory_girl
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: 4.8.0
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: 4.8.0
69
- - !ruby/object:Gem::Dependency
70
- name: shoulda-matchers
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: 3.1.0
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: 3.1.0
83
12
  - !ruby/object:Gem::Dependency
84
13
  name: rails
85
14
  requirement: !ruby/object:Gem::Requirement
86
15
  requirements:
87
- - - "~>"
16
+ - - ">"
88
17
  - !ruby/object:Gem::Version
89
18
  version: '5.0'
90
19
  type: :runtime
91
20
  prerelease: false
92
21
  version_requirements: !ruby/object:Gem::Requirement
93
22
  requirements:
94
- - - "~>"
23
+ - - ">"
95
24
  - !ruby/object:Gem::Version
96
25
  version: '5.0'
97
26
  description: LocalizableModel provides localization support for ActiveRecord objects
@@ -118,8 +47,8 @@ files:
118
47
  - lib/rails/generators/localizable_model/migration/templates/create_localizations.rb
119
48
  homepage: ''
120
49
  licenses: []
121
- metadata: {}
122
- post_install_message:
50
+ metadata:
51
+ rubygems_mfa_required: 'true'
123
52
  rdoc_options: []
124
53
  require_paths:
125
54
  - lib
@@ -127,15 +56,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
127
56
  requirements:
128
57
  - - ">="
129
58
  - !ruby/object:Gem::Version
130
- version: 1.9.2
59
+ version: 3.1.0
131
60
  required_rubygems_version: !ruby/object:Gem::Requirement
132
61
  requirements:
133
62
  - - ">="
134
63
  - !ruby/object:Gem::Version
135
64
  version: '0'
136
65
  requirements: []
137
- rubygems_version: 3.0.1
138
- signing_key:
66
+ rubygems_version: 3.7.1
139
67
  specification_version: 4
140
68
  summary: Localization support for ActiveRecord objects
141
69
  test_files: []