has_localization_table 0.3.13 → 0.4.0

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,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- N2ZlMDQ3ZWRiY2EwYzhmZWU1YmVjYjcwNzk1ZDNlY2VkZDYwNDhjYg==
4
+ ZDVjZmEwMjUwZTk5OTMxMWJhZmQ4MmJhNTk5NTFjNDZhNjcxNDk3OQ==
5
5
  data.tar.gz: !binary |-
6
- OGFhMjlkZWU0ZTdiMzA3OGEwNTMzYzAxYjkzYTgxNmFkODVmM2RlNg==
6
+ Y2ExNzJkNWJkMTY0MmQyMDM4MmQ5Y2YzYTVlNWE5YWUwMzhkYjg1ZA==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ODQyMTUzOGY0YjRjNGY0YTY0YzVlMTZhZTQyN2EzMDhiNzZlMmZhZDZmYmE5
10
- NmMwOTAyNTMzNWY4NDRkMmZhOGMwMGVlMWJjOWMzZDEyY2ZiNzllOWU1N2Y3
11
- NWJhZWJiNGNhMGIzNGRjNmQ2MWE5ZDI1M2ZiZWZlNTBjYTU5NmM=
9
+ OTQzNGFhMThhMmZmY2NiMjliOTJlYmQ2YWVmYjM3YTYzM2E0ZDdmNTA0YzI4
10
+ OTdkODNmYzRhYjNiNGIyNTdkMGIwYzRjMTBjMzZkNmQ3MjczMTUyZmQ5NmVj
11
+ ODQyZTQ5N2JjYTcwZjYwMDgwNTY3ZTBkNDM4MWUxMmZjNzE1ZTc=
12
12
  data.tar.gz: !binary |-
13
- ODQ4MGU3OWE4ZjM5Mjk3OGE5YTJlNDU3NWYyYTg1M2Y0YTIyZmQ5M2NmYjNm
14
- MjE3ZmQyMGViMDRkMmFkMWExOWJiNGM2YTBkZDc5NDE1ZDJhYWM2MDg2ZTc1
15
- MWU4ZDFkMDhiZmJjYjIyNzI4MGQyMWE4N2EyZDllOWM5NmVmZmQ=
13
+ ZDkwZGMxODU0ODNiNjNkMzVmNGRmYzYyODBhYmUzMjgyNTViMDYxYjgxY2E2
14
+ YzM1MDY5OGNkZTVlYWFkMTYyMjdjZGI2MWMzODFlYTE4OGU3NGY2NTRlYzYz
15
+ NDcwMzViNTc5Yjg4MTgxNGNkN2QzMTUwYWEzYTBiMzA1ZDc0ODQ=
@@ -1,17 +1,21 @@
1
1
  module HasLocalizationTable
2
2
  module ActiveRecord
3
3
  module Callbacks
4
+ def self.extended(klass)
5
+ klass.send(:include, InstanceMethods)
6
+ end
7
+
4
8
  def setup_localization_callbacks!
5
9
  # Initialize string records after main record initialization
6
- after_initialize do
10
+ after_initialize(if: :add_localization_after_initialize?) do
7
11
  build_missing_localizations!
8
12
  end
9
-
13
+
10
14
  before_validation do
11
15
  reject_empty_localizations!
12
16
  build_missing_localizations!
13
17
  end
14
-
18
+
15
19
  # Reject any blank strings before saving the record
16
20
  # Validation will have happened by this point, so if there is a required string that is needed, it won't be rejected
17
21
  before_save do
@@ -19,6 +23,14 @@ module HasLocalizationTable
19
23
  end
20
24
  end
21
25
  private :setup_localization_callbacks!
26
+
27
+ module InstanceMethods
28
+ def add_localization_after_initialize?
29
+ localization_table_options.fetch(:initialize, true) && !localization_table_options.fetch(:include, false)
30
+ end
31
+
32
+ private :add_localization_after_initialize?
33
+ end
22
34
  end
23
35
  end
24
- end
36
+ end
@@ -4,52 +4,52 @@ module HasLocalizationTable
4
4
  def self.extended(klass)
5
5
  klass.send(:include, InstanceMethods)
6
6
  end
7
-
7
+
8
8
  def localization_class
9
9
  localization_table_options[:class_name].constantize
10
10
  end
11
-
11
+
12
12
  def localization_association_name
13
13
  localization_table_options[:association_name]
14
14
  end
15
-
15
+
16
16
  def localized_attributes
17
17
  # Determine which attributes of the association model should be accessible through the base class
18
18
  # ie. everything that's not a primary key, foreign key, or timestamp attribute
19
19
  association_name = self.localization_table_options[:association_name] || :strings
20
20
  association = reflect_on_association(association_name)
21
-
21
+
22
22
  attribute_names = association.klass.attribute_names
23
23
  timestamp_attrs = association.klass.new.send(:all_timestamp_attributes_in_model).map(&:to_s)
24
24
  foreign_keys = association.klass.reflect_on_all_associations.map{ |a| a.association_foreign_key }
25
25
  primary_keys = [association.klass.primary_key]
26
26
  # protected_attrs = association.klass.protected_attributes.to_a
27
-
27
+
28
28
  (attribute_names - timestamp_attrs - foreign_keys - primary_keys).map(&:to_sym)
29
29
  end
30
-
30
+
31
31
  def localized_attribute_required?(attribute)
32
32
  return false unless localization_table_options[:required] || false
33
33
  return true unless localization_table_options[:optional]
34
-
35
- !localization_table_options[:optional].include?(attribute)
34
+
35
+ !localization_table_options[:optional].include?(attribute)
36
36
  end
37
-
37
+
38
38
  module InstanceMethods
39
39
  # Helper method for getting the localization association without having to look up the name each time
40
40
  def localization_association
41
41
  association_name = localization_table_options[:association_name]
42
42
  send(association_name)
43
43
  end
44
-
44
+
45
45
  def localized_attributes
46
46
  self.class.localized_attributes
47
47
  end
48
-
48
+
49
49
  def localization_table_options
50
50
  self.class.localization_table_options
51
51
  end
52
52
  end
53
53
  end
54
54
  end
55
- end
55
+ end
@@ -1,6 +1,8 @@
1
1
  module HasLocalizationTable
2
2
  module ActiveRecord
3
3
  module Relation
4
+ RESERVED_KEYS = [:association_name, :required, :optional, :dependent, :has_one, :initialize, :include]
5
+
4
6
  def self.extended(klass)
5
7
  klass.send(:include, InstanceMethods)
6
8
  klass.send(:create_localization_associations!)
@@ -8,10 +10,10 @@ module HasLocalizationTable
8
10
  # Alias the scoping method to use the actual association name
9
11
  alias_method :"with_#{klass.localization_association_name}", :with_localizations
10
12
  end
11
-
13
+
12
14
  def with_localizations(locale = HasLocalizationTable.current_locale.id)
13
15
  lcat = localization_class.arel_table
14
-
16
+
15
17
  scoped.joins(
16
18
  arel_table.join(lcat, Arel::Nodes::OuterJoin).
17
19
  on(lcat[:"#{self.name.underscore}_id"].eq(arel_table[self.primary_key]).and(lcat[HasLocalizationTable.locale_foreign_key].eq(locale))).
@@ -37,7 +39,7 @@ module HasLocalizationTable
37
39
  association_name = localization_association_name.to_s.singularize.to_sym
38
40
  association_name = :localization if localized_attributes.include?(association_name)
39
41
 
40
- has_one_options = localization_table_options.except(:association_name, :required, :optional, :dependent, :has_one).
42
+ has_one_options = localization_table_options.except(*RESERVED_KEYS).
41
43
  merge({ conditions: Proc.new { "#{table_name}.#{foreign_key} = #{HasLocalizationTable.current_locale.id}"} })
42
44
 
43
45
  self.has_one association_name, has_one_options
@@ -46,18 +48,22 @@ module HasLocalizationTable
46
48
 
47
49
  # Collect all localizations for the object
48
50
  def create_has_many_association
49
- self.has_many localization_association_name, localization_table_options.except(:association_name, :required, :optional, :has_one).reverse_merge(autosave: true) do
51
+ self.has_many localization_association_name, localization_table_options.except(*RESERVED_KEYS).reverse_merge(autosave: true) do
50
52
  def for_locale(locale)
51
53
  # where(HasLocalizationTable.locale_foreign_key => locale).first
52
54
  select{ |s| s.send(HasLocalizationTable.locale_foreign_key) == locale }.first
53
55
  end
54
56
  end
57
+
58
+ if localization_table_options.fetch(:include, false)
59
+ self.default_scope -> { includes(localization_association_name) }
60
+ end
55
61
  end
56
62
 
57
63
  public
58
64
 
59
65
  module InstanceMethods
60
- # Add localization objects for any available locale that doesn't have one
66
+ # Add localization objects for any available locale that doesn't have one
61
67
  def build_missing_localizations!
62
68
  return unless HasLocalizationTable.all_locales.any?
63
69
 
@@ -66,11 +72,11 @@ module HasLocalizationTable
66
72
  unless localization_association.detect{ |str| str.send(HasLocalizationTable.locale_foreign_key) == locale.id }
67
73
  localization_association.build(HasLocalizationTable.locale_foreign_key => locale.id)
68
74
  end
69
-
75
+
70
76
  localization_association.sort_by!{ |l| locale_ids.index(l.send(HasLocalizationTable.locale_foreign_key)) || 0 }
71
77
  end
72
78
  end
73
-
79
+
74
80
  # Remove localization objects that are not filled in
75
81
  def reject_empty_localizations!
76
82
  localization_association.reject! { |l| !l.persisted? and localized_attributes.all?{ |attr| l.send(attr).blank? } }
@@ -78,4 +84,4 @@ module HasLocalizationTable
78
84
  end
79
85
  end
80
86
  end
81
- end
87
+ end
@@ -1,3 +1,3 @@
1
1
  module HasLocalizationTable
2
- VERSION = "0.3.13"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ describe HasLocalizationTable do
4
+ before do
5
+ # Configure HLT
6
+ HasLocalizationTable.configure do |c|
7
+ c.primary_locale = Locale.first
8
+ c.current_locale = Locale.first
9
+ c.all_locales = Locale.all
10
+ end
11
+
12
+ Object.send(:remove_const, :Article) rescue nil
13
+ Article = Class.new(ActiveRecord::Base)
14
+ Article.has_localization_table
15
+ end
16
+
17
+ let(:article) { Article.create!(name: "Test", description: "Description") }
18
+
19
+ it 'should initialize the localizations association on initialize' do
20
+ a = Article.new
21
+ a.localizations.wont_be_empty
22
+ end
23
+
24
+ it 'should initialize the localizations association on initialize for an existing object' do
25
+ a = Article.find(article.id)
26
+ a.localizations.wont_be_empty
27
+ end
28
+
29
+ it 'should not initialize the association on initialize if initialize: false is given in config' do
30
+ Article.has_localization_table initialize: false
31
+ a = Article.new
32
+ a.localizations.must_be_empty
33
+ end
34
+
35
+ it 'should not initialize the association for an existing object if initialize: false is given in config' do
36
+ Article.has_localization_table initialize: false
37
+ a = Article.find(article.id)
38
+ refute(a.localizations.loaded?)
39
+ end
40
+
41
+ it 'should not initialize the association on initialize if include: true is given in config' do
42
+ Article.has_localization_table include: true
43
+ a = Article.new
44
+ a.localizations.must_be_empty
45
+ end
46
+
47
+ it 'should load associations if include: true is given' do
48
+ Article.has_localization_table include: true
49
+ assert Article.find(article.id).localizations.loaded?
50
+ end
51
+ end
@@ -5,7 +5,7 @@ describe HasLocalizationTable do
5
5
  before do
6
6
  # Configure HLT
7
7
  HasLocalizationTable.configure do |c|
8
- c.primary_locale = Locale.first
8
+ c.primary_locale = Locale.first
9
9
  c.current_locale = Locale.first
10
10
  c.all_locales = Locale.all
11
11
  end
@@ -91,4 +91,26 @@ describe HasLocalizationTable do
91
91
  conditions.call.must_equal "article_localizations.locale_id = 3"
92
92
  end
93
93
  end
94
- end
94
+
95
+ it 'should add a default scope if include: true is given' do
96
+ Article.stub :localization_table_options, { include: true } do
97
+ Article.default_scopes.must_be_empty
98
+ Article.send(:extend, HasLocalizationTable::ActiveRecord::Relation)
99
+ Article.default_scopes.size.must_equal(1)
100
+ end
101
+ end
102
+
103
+ it 'should not add a default scope if include: false is given' do
104
+ Article.stub :localization_table_options, { include: false } do
105
+ Article.send(:extend, HasLocalizationTable::ActiveRecord::Relation)
106
+ Article.default_scopes.must_be_empty
107
+ end
108
+ end
109
+
110
+ it 'should not add a default scope if include: is not given' do
111
+ Article.stub :localization_table_options, { } do
112
+ Article.send(:extend, HasLocalizationTable::ActiveRecord::Relation)
113
+ Article.default_scopes.must_be_empty
114
+ end
115
+ end
116
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: has_localization_table
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.13
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Vandersluis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-04 00:00:00.000000000 Z
11
+ date: 2016-03-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  type: :runtime
@@ -106,6 +106,7 @@ files:
106
106
  - lib/has_localization_table/config.rb
107
107
  - lib/has_localization_table/version.rb
108
108
  - spec/active_record/attributes_spec.rb
109
+ - spec/active_record/callbacks_spec.rb
109
110
  - spec/active_record/finder_method_spec.rb
110
111
  - spec/active_record/ordered_by_spec.rb
111
112
  - spec/active_record/relation_spec.rb
@@ -140,6 +141,7 @@ summary: Sets up associations and attribute methods for AR models that have a re
140
141
  table to contain user-created data in multiple languages.
141
142
  test_files:
142
143
  - spec/active_record/attributes_spec.rb
144
+ - spec/active_record/callbacks_spec.rb
143
145
  - spec/active_record/finder_method_spec.rb
144
146
  - spec/active_record/ordered_by_spec.rb
145
147
  - spec/active_record/relation_spec.rb