has_localization_table 0.4.0 → 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/.rspec +1 -0
- data/.travis.yml +11 -0
- data/README.md +3 -0
- data/has_localization_table.gemspec +4 -3
- data/lib/has_localization_table/active_record/attributes.rb +35 -18
- data/lib/has_localization_table/active_record/attributes/cache.rb +35 -0
- data/lib/has_localization_table/active_record/callbacks.rb +0 -17
- data/lib/has_localization_table/active_record/meta_methods.rb +13 -2
- data/lib/has_localization_table/active_record/relation.rb +20 -6
- data/lib/has_localization_table/version.rb +1 -1
- data/spec/active_record/attributes_spec.rb +108 -28
- data/spec/active_record/callbacks_spec.rb +0 -28
- data/spec/has_localization_table_spec.rb +2 -2
- data/spec/support/setup.rb +2 -2
- metadata +13 -10
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ODMwMzhkMGY3Mjg1MzZiZjBkMDJjNDk1ZjFkNjk2Y2Y2N2MxODg1Nw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
N2VmZWRhMmQyMjIxNDVhMTVlZTc4ZDk0YWQzNmMzZjcyYzVlNjA5Mw==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
NzFhMjg3NmE1OTcwMzZhNmI2ZDgzNDRhNzk0Njg0MmZlNzVjMTQ0Nzg0YTNj
|
10
|
+
NTdjZTI2OGNkYjU1MzI0NmE4YjI4Y2JiNjhmYjk3MjkxM2EwNTMxZmM4MDli
|
11
|
+
MmIxNjk5ODE0MzI4ZGY5MzJlOTkyZTk5NmIzMDlmYTg4NzQzZDg=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ODgyYzU3Y2U3MTExMjg5MjQ5N2NiNDMwMzdhNjMwOGRjMzhjMGRmY2E2N2E0
|
14
|
+
OWE5MGIzYzczZjIzODkzNTA4ZTFmMGY4YWVmYWUzNDBjZDk5YWFiYjllNjhh
|
15
|
+
OTRlMzA1YzA1YjliZDQwOTIyM2U5MDEwZjUyZmJiY2Y0M2RmYzM=
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
# HasLocalizationTable
|
2
2
|
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/has_localization_table.svg)](https://badge.fury.io/rb/has_localization_table)
|
4
|
+
[![Build Status](https://travis-ci.org/dvandersluis/has_localization_table.svg?branch=master)](https://travis-ci.org/dvandersluis/has_localization_table)
|
5
|
+
|
3
6
|
ActiveRecord plugin which adds setup and convenience methods for working with a relational localization table for user-driven data.
|
4
7
|
|
5
8
|
Adds accessors to retrieve localized attributes using the current locale, in order to avoid having to collect the correct object each time a value is needed. Localized attribute values are also cached for the current locale.
|
@@ -14,9 +14,10 @@ Gem::Specification.new do |gem|
|
|
14
14
|
gem.name = "has_localization_table"
|
15
15
|
gem.require_paths = ["lib"]
|
16
16
|
gem.version = HasLocalizationTable::VERSION
|
17
|
-
|
18
|
-
gem.add_dependency 'activesupport',
|
19
|
-
gem.add_dependency 'activerecord',
|
17
|
+
|
18
|
+
gem.add_dependency 'activesupport', '~> 3.0'
|
19
|
+
gem.add_dependency 'activerecord', '~> 3.0'
|
20
|
+
|
20
21
|
gem.add_development_dependency 'minitest'
|
21
22
|
gem.add_development_dependency 'sqlite3'
|
22
23
|
gem.add_development_dependency 'rake'
|
@@ -1,11 +1,15 @@
|
|
1
1
|
module HasLocalizationTable
|
2
2
|
module ActiveRecord
|
3
3
|
module Attributes
|
4
|
+
LOCALIZED_ATTRIBUTE_REGEX = /\A(?<name>[a-z0-9_]+)(?<suffix>=|_changed\?)?\Z/i
|
5
|
+
|
6
|
+
autoload :Cache, 'has_localization_table/active_record/attributes/cache'
|
7
|
+
|
4
8
|
def read_localized_attribute(attribute, locale = HasLocalizationTable.current_locale, options = {})
|
5
9
|
locale ||= HasLocalizationTable.current_locale
|
6
10
|
|
7
|
-
|
8
|
-
attr =
|
11
|
+
localized_attribute_cache.get(attribute, locale) do
|
12
|
+
attr = localization_for(locale).send(attribute) rescue ''
|
9
13
|
attr ||= '' # if the attribute somehow is nil, change it to a blank string so we're always dealing with strings
|
10
14
|
|
11
15
|
fallback = options.fetch(:fallback, HasLocalizationTable.config.fallback_locale)
|
@@ -19,46 +23,59 @@ module HasLocalizationTable
|
|
19
23
|
attr
|
20
24
|
end
|
21
25
|
end
|
22
|
-
|
26
|
+
|
23
27
|
def write_localized_attribute(attribute, value, locale = HasLocalizationTable.current_locale)
|
24
28
|
value = value.to_s
|
25
|
-
localization =
|
29
|
+
localization = localization_for(locale) ||
|
26
30
|
localization_association.build(HasLocalizationTable.locale_foreign_key => locale.id)
|
27
|
-
|
31
|
+
|
28
32
|
localization.send(:"#{attribute}=", value)
|
29
|
-
|
33
|
+
value.blank? ? localized_attribute_cache.clear(attribute, locale) : localized_attribute_cache.set(attribute, locale, value)
|
30
34
|
end
|
31
|
-
|
35
|
+
|
32
36
|
# Define attribute getters and setters
|
33
37
|
def method_missing(name, *args, &block)
|
34
|
-
|
35
|
-
|
36
|
-
|
38
|
+
match = name.to_s.match(LOCALIZED_ATTRIBUTE_REGEX)
|
39
|
+
|
40
|
+
if match
|
41
|
+
if localized_attributes.include?(match[:name].to_sym)
|
42
|
+
if match[:suffix].nil? # No equals sign -- not a setter
|
37
43
|
# Try to load a string for the given locale
|
38
44
|
# If that fails, try for the primary locale
|
39
45
|
raise ArgumentError, "wrong number of arguments (#{args.size} for 0 or 1)" unless args.size.between?(0, 1)
|
40
46
|
options = args.extract_options!
|
41
47
|
return read_localized_attribute($1, args.first, options) || read_localized_attribute($1, HasLocalizationTable.primary_locale, options)
|
42
|
-
|
48
|
+
elsif match[:suffix] == '='
|
43
49
|
raise ArgumentError, "wrong number of arguments (#{args.size} for 1)" unless args.size == 1
|
44
50
|
return write_localized_attribute($1, args.first)
|
51
|
+
elsif current_localization.respond_to?(name).inspect
|
52
|
+
return localized_attribute_changed?(name.to_s.sub(/_changed\?/, ''))
|
45
53
|
end
|
46
54
|
end
|
47
55
|
end
|
48
|
-
|
56
|
+
|
49
57
|
super
|
50
58
|
end
|
51
|
-
|
59
|
+
|
52
60
|
def respond_to?(*args)
|
53
|
-
|
61
|
+
match = args.first.to_s.match(LOCALIZED_ATTRIBUTE_REGEX)
|
62
|
+
return true if match && localized_attributes.include?(match[:name].to_sym)
|
54
63
|
super
|
55
64
|
end
|
56
|
-
|
65
|
+
|
66
|
+
def reset_localized_attribute_cache
|
67
|
+
localized_attribute_cache.reset
|
68
|
+
end
|
69
|
+
|
57
70
|
private
|
58
71
|
|
59
|
-
def
|
60
|
-
@localization_attribute_cache ||=
|
72
|
+
def localized_attribute_cache
|
73
|
+
@localization_attribute_cache ||= Cache.new(self)
|
74
|
+
end
|
75
|
+
|
76
|
+
def localized_attribute_changed?(attr)
|
77
|
+
current_localization.send("#{attr}_changed?")
|
61
78
|
end
|
62
79
|
end
|
63
80
|
end
|
64
|
-
end
|
81
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module HasLocalizationTable
|
2
|
+
module ActiveRecord
|
3
|
+
module Attributes
|
4
|
+
class Cache < Hash
|
5
|
+
attr_reader :klass
|
6
|
+
|
7
|
+
def initialize(klass)
|
8
|
+
@klass = klass
|
9
|
+
reset
|
10
|
+
end
|
11
|
+
|
12
|
+
def get(attr, locale)
|
13
|
+
clear(attr, locale) if changed?(attr, locale)
|
14
|
+
self[attr.to_sym][locale.id] ||= yield
|
15
|
+
end
|
16
|
+
|
17
|
+
def set(attr, locale, value)
|
18
|
+
self[attr.to_sym][locale.id] = value
|
19
|
+
end
|
20
|
+
|
21
|
+
def clear(attr, locale)
|
22
|
+
self[attr.to_sym].delete(locale.id)
|
23
|
+
end
|
24
|
+
|
25
|
+
def reset
|
26
|
+
replace(klass.localized_attributes.inject({}) { |memo, attr| memo[attr] = {}; memo })
|
27
|
+
end
|
28
|
+
|
29
|
+
def changed?(attr, locale)
|
30
|
+
klass.localization_for(locale).send(attr) != self[attr.to_sym][locale.id]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -1,16 +1,7 @@
|
|
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
|
-
|
8
4
|
def setup_localization_callbacks!
|
9
|
-
# Initialize string records after main record initialization
|
10
|
-
after_initialize(if: :add_localization_after_initialize?) do
|
11
|
-
build_missing_localizations!
|
12
|
-
end
|
13
|
-
|
14
5
|
before_validation do
|
15
6
|
reject_empty_localizations!
|
16
7
|
build_missing_localizations!
|
@@ -23,14 +14,6 @@ module HasLocalizationTable
|
|
23
14
|
end
|
24
15
|
end
|
25
16
|
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
|
34
17
|
end
|
35
18
|
end
|
36
19
|
end
|
@@ -38,8 +38,11 @@ module HasLocalizationTable
|
|
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
|
-
|
42
|
-
|
41
|
+
send(localization_association_name)
|
42
|
+
end
|
43
|
+
|
44
|
+
def localization_association_name
|
45
|
+
localization_table_options[:association_name]
|
43
46
|
end
|
44
47
|
|
45
48
|
def localized_attributes
|
@@ -49,6 +52,14 @@ module HasLocalizationTable
|
|
49
52
|
def localization_table_options
|
50
53
|
self.class.localization_table_options
|
51
54
|
end
|
55
|
+
|
56
|
+
def localization_for(locale)
|
57
|
+
localization_association.detect{ |a| a.send(HasLocalizationTable.locale_foreign_key) == locale.id }
|
58
|
+
end
|
59
|
+
|
60
|
+
def current_localization
|
61
|
+
localization_for(HasLocalizationTable.current_locale)
|
62
|
+
end
|
52
63
|
end
|
53
64
|
end
|
54
65
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module HasLocalizationTable
|
2
2
|
module ActiveRecord
|
3
3
|
module Relation
|
4
|
-
RESERVED_KEYS = [:association_name, :required, :optional, :dependent, :has_one, :
|
4
|
+
RESERVED_KEYS = [:association_name, :required, :optional, :dependent, :has_one, :include, :build_missing]
|
5
5
|
|
6
6
|
def self.extended(klass)
|
7
7
|
klass.send(:include, InstanceMethods)
|
@@ -40,7 +40,7 @@ module HasLocalizationTable
|
|
40
40
|
association_name = :localization if localized_attributes.include?(association_name)
|
41
41
|
|
42
42
|
has_one_options = localization_table_options.except(*RESERVED_KEYS).
|
43
|
-
merge(
|
43
|
+
merge(conditions: -> { "#{table_name}.#{foreign_key} = #{HasLocalizationTable.current_locale.id}" })
|
44
44
|
|
45
45
|
self.has_one association_name, has_one_options
|
46
46
|
self.has_one(:localization, has_one_options) unless association_name == :localization
|
@@ -58,6 +58,18 @@ module HasLocalizationTable
|
|
58
58
|
if localization_table_options.fetch(:include, false)
|
59
59
|
self.default_scope -> { includes(localization_association_name) }
|
60
60
|
end
|
61
|
+
|
62
|
+
override_association_getter
|
63
|
+
end
|
64
|
+
|
65
|
+
def override_association_getter(name = localization_association_name)
|
66
|
+
# Update the association getter to build missing localizations
|
67
|
+
# This works better than an after_initialize because it allows for strings to not be loaded
|
68
|
+
# until they are used, and also repopulates if necessary
|
69
|
+
define_method(name) do |build_missing = localization_table_options.fetch(:build_missing, true), force_reload = false|
|
70
|
+
build_missing_localizations! if build_missing
|
71
|
+
super(force_reload)
|
72
|
+
end
|
61
73
|
end
|
62
74
|
|
63
75
|
public
|
@@ -68,13 +80,15 @@ module HasLocalizationTable
|
|
68
80
|
return unless HasLocalizationTable.all_locales.any?
|
69
81
|
|
70
82
|
locale_ids = HasLocalizationTable.all_locales.map(&:id)
|
83
|
+
assoc = association(localization_association_name).reader
|
84
|
+
|
71
85
|
HasLocalizationTable.all_locales.each do |locale|
|
72
|
-
unless
|
73
|
-
|
86
|
+
unless assoc.detect{ |record| record.send(HasLocalizationTable.locale_foreign_key) == locale.id }
|
87
|
+
assoc.build(HasLocalizationTable.locale_foreign_key => locale.id)
|
74
88
|
end
|
75
|
-
|
76
|
-
localization_association.sort_by!{ |l| locale_ids.index(l.send(HasLocalizationTable.locale_foreign_key)) || 0 }
|
77
89
|
end
|
90
|
+
|
91
|
+
assoc.sort_by!{ |l| locale_ids.index(l.send(HasLocalizationTable.locale_foreign_key)) || 0 }
|
78
92
|
end
|
79
93
|
|
80
94
|
# Remove localization objects that are not filled in
|
@@ -4,7 +4,7 @@ describe HasLocalizationTable do
|
|
4
4
|
before do
|
5
5
|
# Configure HLT
|
6
6
|
HasLocalizationTable.configure do |c|
|
7
|
-
c.primary_locale = Locale.first
|
7
|
+
c.primary_locale = Locale.first
|
8
8
|
c.current_locale = Locale.first
|
9
9
|
c.all_locales = -> { Locale.all }
|
10
10
|
end
|
@@ -15,17 +15,17 @@ describe HasLocalizationTable do
|
|
15
15
|
end
|
16
16
|
|
17
17
|
let(:a) { Article.new(name: "Test", description: "Description") }
|
18
|
-
|
18
|
+
|
19
19
|
it "should set localized attributes" do
|
20
20
|
a.localizations.first.name.must_equal "Test"
|
21
21
|
a.localizations.first.description.must_equal "Description"
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
it "should create accessor methods" do
|
25
25
|
a.name.must_equal "Test"
|
26
26
|
a.description.must_equal "Description"
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
it "should save localized attributes" do
|
30
30
|
a.save!
|
31
31
|
a.reload
|
@@ -38,7 +38,7 @@ describe HasLocalizationTable do
|
|
38
38
|
a.update_attributes!(name: "Test 2")
|
39
39
|
Article.find(a.id).name.must_equal "Test 2"
|
40
40
|
end
|
41
|
-
|
41
|
+
|
42
42
|
it "should create mutator methods" do
|
43
43
|
a.name = "Changed"
|
44
44
|
a.description = "Changed Description"
|
@@ -47,31 +47,31 @@ describe HasLocalizationTable do
|
|
47
47
|
a.localizations.first.name.must_equal "Changed"
|
48
48
|
a.localizations.first.description.must_equal "Changed Description"
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
51
|
it "should use the current locale when setting" do
|
52
52
|
a
|
53
53
|
|
54
54
|
HasLocalizationTable.configure do |c|
|
55
55
|
c.current_locale = Locale.last
|
56
56
|
end
|
57
|
-
|
57
|
+
|
58
58
|
a.name = "French Name"
|
59
59
|
a.description = "French Description"
|
60
|
-
|
60
|
+
|
61
61
|
eng = a.localizations.detect{ |s| s.locale_id == Locale.first.id }
|
62
62
|
fre = a.localizations.detect{ |s| s.locale_id == Locale.last.id }
|
63
|
-
|
63
|
+
|
64
64
|
eng.name.must_equal "Test"
|
65
65
|
eng.description.must_equal "Description"
|
66
66
|
fre.name.must_equal "French Name"
|
67
67
|
fre.description.must_equal "French Description"
|
68
68
|
end
|
69
|
-
|
69
|
+
|
70
70
|
it "should return the correct value when the current locale changes" do
|
71
71
|
Locale.class_eval { cattr_accessor :current }
|
72
72
|
eng = Locale.find_by_name("English")
|
73
73
|
fre = Locale.find_by_name("French")
|
74
|
-
|
74
|
+
|
75
75
|
HasLocalizationTable.configure do |c|
|
76
76
|
c.current_locale = ->{ Locale.current }
|
77
77
|
end
|
@@ -79,58 +79,58 @@ describe HasLocalizationTable do
|
|
79
79
|
Locale.current = eng
|
80
80
|
a.name = "English Name"
|
81
81
|
a.description = "English Description"
|
82
|
-
|
82
|
+
|
83
83
|
Locale.current = fre
|
84
84
|
a.name = "French Name"
|
85
85
|
a.description = "French Description"
|
86
|
-
|
86
|
+
|
87
87
|
Locale.current = eng
|
88
88
|
a.name.must_equal "English Name"
|
89
89
|
a.description.must_equal "English Description"
|
90
|
-
|
90
|
+
|
91
91
|
Locale.current = fre
|
92
92
|
a.name.must_equal "French Name"
|
93
93
|
a.description.must_equal "French Description"
|
94
94
|
end
|
95
|
-
|
95
|
+
|
96
96
|
it "should return the correct locale's value even if the cache is empty" do
|
97
97
|
Locale.class_eval { cattr_accessor :current }
|
98
|
-
Locale.current =
|
98
|
+
Locale.current = Locale.find_by_name("English")
|
99
99
|
fre = Locale.find_by_name("French")
|
100
|
-
|
100
|
+
|
101
101
|
HasLocalizationTable.configure do |c|
|
102
102
|
c.current_locale = ->{ Locale.current }
|
103
103
|
end
|
104
104
|
|
105
105
|
a.localizations.last.attributes = { name: "French Name", description: "French Description" }
|
106
|
-
|
107
|
-
# Force empty cache
|
108
|
-
a.
|
106
|
+
|
107
|
+
# Force empty cache
|
108
|
+
a.reset_localized_attribute_cache
|
109
109
|
|
110
110
|
Locale.current = fre
|
111
111
|
a.name.must_equal "French Name"
|
112
112
|
a.description.must_equal "French Description"
|
113
113
|
end
|
114
|
-
|
114
|
+
|
115
115
|
it "should return the correct locale's value even if a language was added" do
|
116
116
|
Locale.class_eval { cattr_accessor :current }
|
117
117
|
Locale.current = eng = Locale.find_by_name("English")
|
118
118
|
fre = Locale.find_by_name("French")
|
119
|
-
|
119
|
+
|
120
120
|
HasLocalizationTable.configure do |c|
|
121
121
|
c.current_locale = ->{ Locale.current }
|
122
122
|
c.all_locales = [eng]
|
123
123
|
end
|
124
|
-
|
124
|
+
|
125
125
|
Object.send(:remove_const, :Article) rescue nil
|
126
126
|
Article = Class.new(ActiveRecord::Base)
|
127
127
|
Article.has_localization_table
|
128
|
-
|
128
|
+
|
129
129
|
aa = Article.create!(name: "Name", description: "Description")
|
130
|
-
|
131
|
-
|
130
|
+
ArticleLocalization.create!(article: aa, locale: fre, name: "French Name", description: "French Description")
|
131
|
+
|
132
132
|
aa.reload
|
133
|
-
|
133
|
+
|
134
134
|
Locale.current = fre
|
135
135
|
aa.name.must_equal "French Name"
|
136
136
|
aa.description.must_equal "French Description"
|
@@ -219,4 +219,84 @@ describe HasLocalizationTable do
|
|
219
219
|
end
|
220
220
|
end
|
221
221
|
end
|
222
|
-
|
222
|
+
|
223
|
+
it 'should build missing localizations when accessing the association' do
|
224
|
+
HasLocalizationTable.config.all_locales = [Locale.first]
|
225
|
+
|
226
|
+
a = Article.new
|
227
|
+
a.localizations.size.must_equal 1
|
228
|
+
end
|
229
|
+
|
230
|
+
it 'should build missing localizations when there is more than 1 locale' do
|
231
|
+
a = Article.new
|
232
|
+
a.localizations.size.must_equal 2
|
233
|
+
end
|
234
|
+
|
235
|
+
it 'should not build localizations when they already exist' do
|
236
|
+
a = Article.new
|
237
|
+
l1 = ArticleLocalization.new(locale_id: Locale.first.id, name: 'Name')
|
238
|
+
l2 = ArticleLocalization.new(locale_id: Locale.last.id, name: 'Nom')
|
239
|
+
a.localizations = [l1, l2]
|
240
|
+
a.localizations.must_equal [l1, l2]
|
241
|
+
a.localizations.first.name.must_equal 'Name'
|
242
|
+
end
|
243
|
+
|
244
|
+
it 'should add missing localizations if some exist' do
|
245
|
+
a = Article.new
|
246
|
+
a.localizations = [ArticleLocalization.new(locale_id: Locale.first.id, name: 'Name')]
|
247
|
+
a.association(:localizations).reader.size.must_equal 1
|
248
|
+
a.localizations.size.must_equal 2
|
249
|
+
a.localizations.first.name.must_equal 'Name'
|
250
|
+
end
|
251
|
+
|
252
|
+
it 'should not build missing localizations if asked not to' do
|
253
|
+
a = Article.new
|
254
|
+
a.localizations(false).must_be_empty
|
255
|
+
end
|
256
|
+
|
257
|
+
it 'should not build missing localizations if the options disable it' do
|
258
|
+
Article.has_localization_table build_missing: false
|
259
|
+
a = Article.new
|
260
|
+
a.localizations.must_be_empty
|
261
|
+
end
|
262
|
+
|
263
|
+
it 'should build missing localizations if the options disable it but the method requests it' do
|
264
|
+
Article.has_localization_table build_missing: false
|
265
|
+
a = Article.new
|
266
|
+
a.localizations(true).wont_be_empty
|
267
|
+
end
|
268
|
+
|
269
|
+
it 'should update the main model when the string is directly updated' do
|
270
|
+
Article.has_localization_table
|
271
|
+
a = Article.new
|
272
|
+
|
273
|
+
string = a.localizations.first
|
274
|
+
string.name = 'New Name'
|
275
|
+
a.name.must_equal 'New Name'
|
276
|
+
end
|
277
|
+
|
278
|
+
it 'should allow successive changes' do
|
279
|
+
Article.has_localization_table
|
280
|
+
a = Article.new
|
281
|
+
|
282
|
+
string = a.localizations.first
|
283
|
+
string.name = 'New Name'
|
284
|
+
a.name.must_equal 'New Name'
|
285
|
+
|
286
|
+
string.name = 'Another Name'
|
287
|
+
a.name.must_equal 'Another Name'
|
288
|
+
end
|
289
|
+
|
290
|
+
it 'should report if the attribute changed' do
|
291
|
+
Article.has_localization_table
|
292
|
+
a = Article.create!(name: 'Name')
|
293
|
+
a.name = 'New Name'
|
294
|
+
assert a.name_changed?
|
295
|
+
end
|
296
|
+
|
297
|
+
it 'should not report that the attribute has changed if it has not' do
|
298
|
+
Article.has_localization_table
|
299
|
+
a = Article.create!(name: 'Name')
|
300
|
+
refute a.name_changed?
|
301
|
+
end
|
302
|
+
end
|
@@ -16,34 +16,6 @@ describe HasLocalizationTable do
|
|
16
16
|
|
17
17
|
let(:article) { Article.create!(name: "Test", description: "Description") }
|
18
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
19
|
it 'should load associations if include: true is given' do
|
48
20
|
Article.has_localization_table include: true
|
49
21
|
assert Article.find(article.id).localizations.loaded?
|
data/spec/support/setup.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
|
3
3
|
ActiveRecord::Migration.tap do |m|
|
4
4
|
m.create_table :articles do |t|
|
5
|
-
t.timestamps
|
5
|
+
t.timestamps null: false
|
6
6
|
end
|
7
7
|
|
8
8
|
m.create_table :locales do |t|
|
@@ -25,4 +25,4 @@ Locale.create!(name: "French")
|
|
25
25
|
ArticleLocalization = Class.new(ActiveRecord::Base) do
|
26
26
|
belongs_to :article
|
27
27
|
belongs_to :locale
|
28
|
-
end
|
28
|
+
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.4.
|
4
|
+
version: 0.4.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Vandersluis
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-04-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
type: :runtime
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
name: activesupport
|
17
17
|
requirement: !ruby/object:Gem::Requirement
|
18
18
|
requirements:
|
19
|
-
- -
|
19
|
+
- - ~>
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 3.0
|
21
|
+
version: '3.0'
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ~>
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 3.0
|
26
|
+
version: '3.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
type: :runtime
|
29
29
|
prerelease: false
|
30
30
|
name: activerecord
|
31
31
|
requirement: !ruby/object:Gem::Requirement
|
32
32
|
requirements:
|
33
|
-
- -
|
33
|
+
- - ~>
|
34
34
|
- !ruby/object:Gem::Version
|
35
|
-
version: 3.0
|
35
|
+
version: '3.0'
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ~>
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 3.0
|
40
|
+
version: '3.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
type: :development
|
43
43
|
prerelease: false
|
@@ -89,6 +89,8 @@ extensions: []
|
|
89
89
|
extra_rdoc_files: []
|
90
90
|
files:
|
91
91
|
- .gitignore
|
92
|
+
- .rspec
|
93
|
+
- .travis.yml
|
92
94
|
- Gemfile
|
93
95
|
- LICENSE
|
94
96
|
- README.md
|
@@ -97,6 +99,7 @@ files:
|
|
97
99
|
- lib/has_localization_table.rb
|
98
100
|
- lib/has_localization_table/active_record.rb
|
99
101
|
- lib/has_localization_table/active_record/attributes.rb
|
102
|
+
- lib/has_localization_table/active_record/attributes/cache.rb
|
100
103
|
- lib/has_localization_table/active_record/callbacks.rb
|
101
104
|
- lib/has_localization_table/active_record/finder_methods.rb
|
102
105
|
- lib/has_localization_table/active_record/meta_methods.rb
|