has_localization_table 0.3.13 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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