akm-selectable_attr_rails 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :minor: 3
3
+ :patch: 0
4
+ :major: 0
@@ -0,0 +1,7 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'selectable_attr'
3
+
4
+ module SelectableAttrRails
5
+ autoload :Helpers, 'selectable_attr_rails/helpers'
6
+ autoload :DbLoadable, 'selectable_attr_rails/db_loadable'
7
+ end
@@ -0,0 +1,65 @@
1
+ module SelectableAttrRails
2
+ module DbLoadable
3
+ def update_by(*args, &block)
4
+ options = args.last.is_a?(Hash) ? args.pop : {}
5
+ options = {:when => :first_time}.update(options)
6
+ @sql_to_update = block_given? ? block : args.first
7
+ @update_timing = options[:when]
8
+ self.extend(InstanceMethods) unless respond_to?(:update_entries)
9
+ end
10
+
11
+ module Entry
12
+ attr_accessor :name_from_db
13
+ def name
14
+ @name_from_db || super
15
+ end
16
+ end
17
+
18
+ module InstanceMethods
19
+ def entries
20
+ update_entries if must_be_updated?
21
+ @entries
22
+ end
23
+
24
+ def must_be_updated?
25
+ return false if @update_timing == :never
26
+ return true if @update_timing == :everytime
27
+ end
28
+
29
+ def update_entries
30
+ unless @original_entries
31
+ @original_entries = @entries.dup
32
+ @original_entries.each do |entry|
33
+ entry.extend(SelectableAttrRails::DbLoadable::Entry)
34
+ end
35
+ end
36
+ records = nil
37
+ if @sql_to_update.respond_to?(:call)
38
+ records = @sql_to_update.call
39
+ else
40
+ @connection ||= ActiveRecord::Base.connection
41
+ records = @connection.select_rows(@sql_to_update)
42
+ end
43
+
44
+ new_entries = []
45
+ records.each do |r|
46
+ if entry = @original_entries.detect{|entry| entry.id == r.first}
47
+ entry.name_from_db = r.last unless r.last.blank?
48
+ new_entries << entry
49
+ else
50
+ entry = SelectableAttr::Enum::Entry.new(self, r.first, "entry_#{r.first}".to_sym, r.last)
51
+ new_entries << entry
52
+ end
53
+ end
54
+ @original_entries.each do |entry|
55
+ unless new_entries.include?(entry)
56
+ entry.name_from_db = nil
57
+ new_entries << entry if entry.defined_in_code
58
+ end
59
+ end
60
+ @entries = new_entries
61
+ end
62
+ end
63
+
64
+ end
65
+ end
@@ -0,0 +1,7 @@
1
+ module SelectableAttrRails
2
+ module Helpers
3
+ autoload :SelectHelper, 'selectable_attr_rails/helpers/select_helper'
4
+ autoload :CheckBoxGroupHelper, 'selectable_attr_rails/helpers/check_box_group_helper'
5
+ autoload :RadioButtonGroupHelper, 'selectable_attr_rails/helpers/radio_button_group_helper'
6
+ end
7
+ end
@@ -0,0 +1,55 @@
1
+ module SelectableAttrRails::Helpers
2
+ class AbstractSelectionBuilder
3
+ attr_reader :entry_hash
4
+
5
+ def initialize(object, object_name, method, options, template)
6
+ @object, @object_name, @method = object, object_name, method
7
+ @base_name = @object.class.enum_base_name(method.to_s)
8
+ @template = template
9
+ @entry_hash = nil
10
+ @options = options || {}
11
+ @entry_hash_array = @options[:entry_hash_array]
12
+ end
13
+
14
+ def enum_hash_array_from_object
15
+ base_name = @object.class.enum_base_name(@method.to_s)
16
+ @object.send("#{base_name}_hash_array")
17
+ end
18
+
19
+ def enum_hash_array_from_class
20
+ base_name = @object.class.enum_base_name(@method.to_s)
21
+ @object.class.send("#{base_name}_hash_array")
22
+ end
23
+
24
+ def tag_id(tag)
25
+ result = nil
26
+ tag.scan(/ id\=\"(.*?)\"/){|s|result = s}
27
+ return result
28
+ end
29
+
30
+ def add_class_name(options, class_name)
31
+ (options ||= {}).stringify_keys!
32
+ (options['class'] ||= '') << ' ' << class_name
33
+ options
34
+ end
35
+
36
+ def camelize_keys(hash, first_letter = :lower)
37
+ result = {}
38
+ hash.each{|key, value|result[key.to_s.camelize(first_letter)] = value}
39
+ result
40
+ end
41
+
42
+ def update_options(dest, *options_array)
43
+ result = dest || {}
44
+ options_array.each do |options|
45
+ next unless options
46
+ if class_name = options.delete(:class)
47
+ add_class_name(result, class_name)
48
+ end
49
+ result.update(options)
50
+ end
51
+ result
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,63 @@
1
+ require 'selectable_attr_rails/helpers/abstract_selection_helper'
2
+ module SelectableAttrRails::Helpers
3
+ module CheckBoxGroupHelper
4
+ class Builder < SelectableAttrRails::Helpers::AbstractSelectionBuilder
5
+
6
+ def initialize(object, object_name, method, options, template)
7
+ super(object, object_name, method, options, template)
8
+ @entry_hash_array ||= enum_hash_array_from_object
9
+ @param_name = "#{@base_name}_ids"
10
+ @check_box_options = @options.delete(:check_box) || {}
11
+ end
12
+
13
+ def each(&block)
14
+ @entry_hash_array.each do |@entry_hash|
15
+ @tag_value = @entry_hash[:id].to_s.gsub(/\s/, "_").gsub(/\W/, "")
16
+ @check_box_id = "#{@object_name}_#{@param_name}_#{@tag_value}"
17
+ yield(self)
18
+ end
19
+ end
20
+
21
+ def check_box(options = nil)
22
+ options = update_options({
23
+ :id => @check_box_id, :type => 'checkbox', :value => @tag_value,
24
+ :name => "#{@object_name}[#{@param_name}][]"
25
+ }, @check_box_options, options)
26
+ options[:checked] = 'checked' if @entry_hash[:select]
27
+ @template.content_tag("input", nil, options)
28
+ end
29
+
30
+ def label(text = nil, options = nil)
31
+ @template.content_tag("label", text || @entry_hash[:name],
32
+ update_options({:for => @check_box_id}, options))
33
+ end
34
+ end
35
+
36
+ module Base
37
+ def check_box_group(object_name, method, options = nil, &block)
38
+ object = (options || {})[:object] || instance_variable_get("@#{object_name}")
39
+ builder = Builder.new(object, object_name, method, options, @template)
40
+ if block_given?
41
+ yield(builder)
42
+ return nil
43
+ else
44
+ result = ''
45
+ builder.each do
46
+ result << builder.check_box
47
+ result << '&nbsp;'
48
+ result << builder.label
49
+ result << '&nbsp;'
50
+ end
51
+ return result
52
+ end
53
+ end
54
+ end
55
+
56
+ module FormBuilder
57
+ def check_box_group(method, options = nil, &block)
58
+ @template.check_box_group(@object_name, method,
59
+ (options || {}).merge(:object => @object), &block)
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,55 @@
1
+ module SelectableAttrRails::Helpers
2
+ module RadioButtonGroupHelper
3
+ class Builder < SelectableAttrRails::Helpers::AbstractSelectionBuilder
4
+
5
+ def initialize(object, object_name, method, options, template)
6
+ super(object, object_name, method, options, template)
7
+ @entry_hash_array ||= enum_hash_array_from_class
8
+ end
9
+
10
+ def each(&block)
11
+ @entry_hash_array.each do |entry_hash|
12
+ @entry_hash = entry_hash
13
+ tag_value = @entry_hash[:id].to_s.gsub(/\s/, "_").gsub(/\W/, "").downcase
14
+ @radio_button_id = "#{@object_name}_#{@method}_#{tag_value}"
15
+ yield(self)
16
+ end
17
+ end
18
+
19
+ def radio_button(options = nil)
20
+ @template.radio_button(@object_name, @method, @entry_hash[:id],
21
+ update_options({:id => @radio_button_id}, options))
22
+ end
23
+
24
+ def label(text = nil, options = nil)
25
+ @template.content_tag("label", text || @entry_hash[:name],
26
+ update_options({:for => @radio_button_id}, options))
27
+ end
28
+ end
29
+
30
+ module Base
31
+ def radio_button_group(object_name, method, options = nil, &block)
32
+ object = (options || {})[:object] || instance_variable_get("@#{object_name}")
33
+ builder = Builder.new(object, object_name, method, options, self)
34
+ if block_given?
35
+ yield(builder)
36
+ return nil
37
+ else
38
+ result = ''
39
+ builder.each do
40
+ result << builder.radio_button
41
+ result << builder.label
42
+ end
43
+ return result
44
+ end
45
+ end
46
+ end
47
+
48
+ module FormBuilder
49
+ def radio_button_group(method, options = nil, &block)
50
+ @template.radio_button_group(@object_name, method,
51
+ (options || {}).merge(:object => @object), &block)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,72 @@
1
+ module SelectableAttrRails::Helpers
2
+ module SelectHelper
3
+ module Base
4
+ def self.included(base)
5
+ base.module_eval do
6
+ alias_method_chain :select, :attr_enumeable
7
+ end
8
+ end
9
+
10
+ # def select_with_attr_enumeable(object, method, choices, options = {}, html_options = {})
11
+ def select_with_attr_enumeable(object_name, method, *args, &block)
12
+ if args.length > 3
13
+ raise ArgumentError, "argument must be " <<
14
+ "(object, method, choices, options = {}, html_options = {}) or " <<
15
+ "(object, method, options = {}, html_options = {})"
16
+ end
17
+ return select_without_attr_enumeable(object_name, method, *args, &block) if args.length == 3
18
+ return select_without_attr_enumeable(object_name, method, *args, &block) if args.first.is_a?(Array)
19
+ options, html_options = *args
20
+ options = update_enum_select_options(options, object_name, method)
21
+ object, base_name = options[:object], options[:base_name]
22
+ return multi_enum_select(object_name, method, options, html_options, &block) if object.respond_to?("#{base_name}_hash_array")
23
+ return single_enum_select(object_name, method, options, html_options, &block) if object.class.respond_to?("#{base_name}_hash_array")
24
+ raise ArgumentError, "invaliad argument"
25
+ end
26
+
27
+ def single_enum_select(object_name, method, options = {}, html_options = {}, &block)
28
+ options = update_enum_select_options(options, object_name, method)
29
+ object = options.delete(:object)
30
+ base_name = options.delete(:base_name)
31
+ entry_hash_array = options.delete(:entry_hash_array) || object.class.send("#{base_name}_hash_array")
32
+ container = entry_hash_array.map{|hash| [hash[:name].to_s, hash[:id]]}
33
+ select_without_attr_enumeable(object_name, method, container, options, html_options || {}, &block)
34
+ end
35
+
36
+ def multi_enum_select(object_name, method, options = {}, html_options = {}, &block)
37
+ html_options = {:size => 5, :multiple => 'multiple'}.update(html_options || {})
38
+ options = update_enum_select_options(options, object_name, method)
39
+ object = options.delete(:object)
40
+ base_name = options.delete(:base_name)
41
+ entry_hash_array = options.delete(:entry_hash_array) || object.send("#{base_name}_hash_array")
42
+ container = entry_hash_array.map{|hash| [hash[:name].to_s, hash[:id].to_s]}
43
+ attr = "#{base_name}_ids"
44
+ select_without_attr_enumeable(object_name, attr, container, options, html_options, &block)
45
+ end
46
+
47
+ def update_enum_select_options(options, object_name, method)
48
+ options ||= {}
49
+ object = (options[:object] ||= instance_variable_get("@#{object_name}"))
50
+ options[:base_name] ||= object.class.enum_base_name(method.to_s)
51
+ options
52
+ end
53
+ end
54
+
55
+ module FormBuilder
56
+ def self.included(base)
57
+ base.module_eval do
58
+ alias_method_chain :select, :attr_enumeable
59
+ end
60
+ end
61
+
62
+ # def select_with_attr_enumeable(method, choices, options = {}, html_options = {}, &block)
63
+ def select_with_attr_enumeable(method, *args, &block)
64
+ options = args.first.is_a?(Array) ? (args[1] ||= {}) : (args[0] ||= {})
65
+ object = (options || {}).delete(:object) || @object || instance_variable_get(@object_name) rescue nil
66
+ options.update({:object => object})
67
+ options[:selected] = object.send(method) if object
68
+ @template.select(@object_name, method, *args, &block)
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,3 @@
1
+ module SelectableAttrRails
2
+ VERSION = '0.0.3'
3
+ end
data/spec/database.yml ADDED
@@ -0,0 +1,6 @@
1
+ sqlite:
2
+ :adapter: sqlite
3
+ :dbfile: selectable_attr_test.sqlite.db
4
+ sqlite3:
5
+ :adapter: sqlite3
6
+ :dbfile: selectable_attr_test.sqlite3.db
@@ -0,0 +1,379 @@
1
+ # -*- coding: utf-8 -*-
2
+ require File.join(File.dirname(__FILE__), 'spec_helper')
3
+
4
+ describe SelectableAttr do
5
+
6
+ def assert_product_discount(klass)
7
+ # productsテーブルのデータから安売り用の価格は
8
+ # product_type_cd毎に決められた割合をpriceにかけて求めます。
9
+ p1 = klass.new(:name => '実践Rails', :product_type_cd => '01', :price => 3000)
10
+ p1.discount_price.should == 2400
11
+ p2 = klass.new(:name => '薔薇の名前', :product_type_cd => '02', :price => 1500)
12
+ p2.discount_price.should == 300
13
+ p3 = klass.new(:name => '未来派野郎', :product_type_cd => '03', :price => 3000)
14
+ p3.discount_price.should == 1500
15
+ end
16
+
17
+ # 定数をガンガン定義した場合
18
+ # 大文字が多くて読みにくいし、関連するデータ(ここではDISCOUNT)が増える毎に定数も増えていきます。
19
+ class LegacyProduct1 < ActiveRecord::Base
20
+ set_table_name 'products'
21
+
22
+ PRODUCT_TYPE_BOOK = '01'
23
+ PRODUCT_TYPE_DVD = '02'
24
+ PRODUCT_TYPE_CD = '03'
25
+ PRODUCT_TYPE_OTHER = '09'
26
+
27
+ PRODUCT_TYPE_OPTIONS = [
28
+ ['書籍', PRODUCT_TYPE_BOOK],
29
+ ['DVD', PRODUCT_TYPE_DVD],
30
+ ['CD', PRODUCT_TYPE_CD],
31
+ ['その他', PRODUCT_TYPE_OTHER]
32
+ ]
33
+
34
+ DISCOUNT = {
35
+ PRODUCT_TYPE_BOOK => 0.8,
36
+ PRODUCT_TYPE_DVD => 0.2,
37
+ PRODUCT_TYPE_CD => 0.5,
38
+ PRODUCT_TYPE_OTHER => 1
39
+ }
40
+
41
+ def discount_price
42
+ (DISCOUNT[product_type_cd] * price).to_i
43
+ end
44
+ end
45
+
46
+ it "test_legacy_product" do
47
+ assert_product_discount(LegacyProduct1)
48
+
49
+ # 選択肢を表示するためのデータは以下のように取得できる
50
+ LegacyProduct1::PRODUCT_TYPE_OPTIONS.should ==
51
+ [['書籍', '01'], ['DVD', '02'], ['CD', '03'], ['その他', '09']]
52
+ end
53
+
54
+
55
+
56
+
57
+ # できるだけ定数定義をまとめた場合
58
+ # 結構すっきりするけど、同じことをいろんなモデルで書くかと思うと気が重い。
59
+ class LegacyProduct2 < ActiveRecord::Base
60
+ set_table_name 'products'
61
+
62
+ PRODUCT_TYPE_DEFS = [
63
+ {:id => '01', :name => '書籍', :discount => 0.8},
64
+ {:id => '02', :name => 'DVD', :discount => 0.2},
65
+ {:id => '03', :name => 'CD', :discount => 0.5},
66
+ {:id => '09', :name => 'その他', :discount => 1}
67
+ ]
68
+
69
+ PRODUCT_TYPE_OPTIONS = PRODUCT_TYPE_DEFS.map{|t| [t[:name], t[:id]]}
70
+ DISCOUNT = PRODUCT_TYPE_DEFS.inject({}){|dest, t|
71
+ dest[t[:id]] = t[:discount]; dest}
72
+
73
+ def discount_price
74
+ (DISCOUNT[product_type_cd] * price).to_i
75
+ end
76
+ end
77
+
78
+ it "test_legacy_product" do
79
+ assert_product_discount(LegacyProduct2)
80
+
81
+ # 選択肢を表示するためのデータは以下のように取得できる
82
+ LegacyProduct2::PRODUCT_TYPE_OPTIONS.should ==
83
+ [['書籍', '01'], ['DVD', '02'], ['CD', '03'], ['その他', '09']]
84
+ end
85
+
86
+ # selectable_attrを使った場合
87
+ # 定義は一カ所にまとめられて、任意の属性(ここでは:discount)も一緒に書くことができてすっきり〜
88
+ class Product1 < ActiveRecord::Base
89
+ set_table_name 'products'
90
+
91
+ selectable_attr :product_type_cd do
92
+ entry '01', :book, '書籍', :discount => 0.8
93
+ entry '02', :dvd, 'DVD', :discount => 0.2
94
+ entry '03', :cd, 'CD', :discount => 0.5
95
+ entry '09', :other, 'その他', :discount => 1
96
+ end
97
+
98
+ def discount_price
99
+ (product_type_entry[:discount] * price).to_i
100
+ end
101
+ end
102
+
103
+ it "test_product1" do
104
+ assert_product_discount(Product1)
105
+ # 選択肢を表示するためのデータは以下のように取得できる
106
+ Product1.product_type_options.should ==
107
+ [['書籍', '01'], ['DVD', '02'], ['CD', '03'], ['その他', '09']]
108
+ end
109
+
110
+
111
+ # selectable_attrが定義するインスタンスメソッドの詳細
112
+ it "test_product_type_instance_methods" do
113
+ p1 = Product1.new
114
+ p1.product_type_cd.should be_nil
115
+ p1.product_type_key.should be_nil
116
+ p1.product_type_name.should be_nil
117
+ # idを変更すると得られるキーも名称も変わります
118
+ p1.product_type_cd = '02'
119
+ p1.product_type_cd.should == '02'
120
+ p1.product_type_key.should == :dvd
121
+ p1.product_type_name.should == 'DVD'
122
+ # キーを変更すると得られるidも名称も変わります
123
+ p1.product_type_key = :book
124
+ p1.product_type_cd.should == '01'
125
+ p1.product_type_key.should == :book
126
+ p1.product_type_name.should == '書籍'
127
+ # id、キー、名称以外の任意の属性は、entryの[]メソッドで取得します。
128
+ p1.product_type_key = :cd
129
+ p1.product_type_entry[:discount].should == 0.5
130
+ end
131
+
132
+ # selectable_attrが定義するクラスメソッドの詳細
133
+ it "test_product_type_class_methods" do
134
+ # キーからid、名称を取得できます
135
+ Product1.product_type_id_by_key(:book).should == '01'
136
+ Product1.product_type_id_by_key(:dvd).should == '02'
137
+ Product1.product_type_id_by_key(:cd).should == '03'
138
+ Product1.product_type_id_by_key(:other).should == '09'
139
+ Product1.product_type_name_by_key(:book).should == '書籍'
140
+ Product1.product_type_name_by_key(:dvd).should == 'DVD'
141
+ Product1.product_type_name_by_key(:cd).should == 'CD'
142
+ Product1.product_type_name_by_key(:other).should == 'その他'
143
+ # 存在しないキーの場合はnilを返します
144
+ Product1.product_type_id_by_key(nil).should be_nil
145
+ Product1.product_type_name_by_key(nil).should be_nil
146
+ Product1.product_type_id_by_key(:unexist).should be_nil
147
+ Product1.product_type_name_by_key(:unexist).should be_nil
148
+
149
+ # idからキー、名称を取得できます
150
+ Product1.product_type_key_by_id('01').should == :book
151
+ Product1.product_type_key_by_id('02').should == :dvd
152
+ Product1.product_type_key_by_id('03').should == :cd
153
+ Product1.product_type_key_by_id('09').should == :other
154
+ Product1.product_type_name_by_id('01').should == '書籍'
155
+ Product1.product_type_name_by_id('02').should == 'DVD'
156
+ Product1.product_type_name_by_id('03').should == 'CD'
157
+ Product1.product_type_name_by_id('09').should == 'その他'
158
+ # 存在しないidの場合はnilを返します
159
+ Product1.product_type_key_by_id(nil).should be_nil
160
+ Product1.product_type_name_by_id(nil).should be_nil
161
+ Product1.product_type_key_by_id('99').should be_nil
162
+ Product1.product_type_name_by_id('99').should be_nil
163
+
164
+ # id、キー、名称の配列を取得できます
165
+ Product1.product_type_ids.should == ['01', '02', '03', '09']
166
+ Product1.product_type_keys.should == [:book, :dvd, :cd, :other]
167
+ Product1.product_type_names.should == ['書籍', 'DVD', 'CD', 'その他']
168
+ # 一部のものだけ取得することも可能です。
169
+ Product1.product_type_ids(:cd, :dvd).should == ['03', '02' ]
170
+ Product1.product_type_keys('02', '03').should == [:dvd, :cd ]
171
+ Product1.product_type_names('02', '03').should == ['DVD', 'CD']
172
+ Product1.product_type_names(:cd, :dvd).should == ['CD', 'DVD']
173
+
174
+ # select_tagなどのoption_tagsを作るための配列なんか一発っす
175
+ Product1.product_type_options.should ==
176
+ [['書籍', '01'], ['DVD', '02'], ['CD', '03'], ['その他', '09']]
177
+ end
178
+
179
+ # selectable_attrのエントリ名をDB上に保持するためのモデル
180
+ class ItemMaster < ActiveRecord::Base
181
+ end
182
+
183
+ # selectable_attrを使った場合その2
184
+ # アクセス時に毎回アクセス時にDBから項目名を取得します。
185
+ class ProductWithDB1 < ActiveRecord::Base
186
+ set_table_name 'products'
187
+
188
+ selectable_attr :product_type_cd do
189
+ update_by(
190
+ "select item_cd, name from item_masters where category_name = 'product_type_cd' order by item_no",
191
+ :when => :everytime)
192
+ entry '01', :book, '書籍', :discount => 0.8
193
+ entry '02', :dvd, 'DVD', :discount => 0.2
194
+ entry '03', :cd, 'CD', :discount => 0.5
195
+ entry '09', :other, 'その他', :discount => 1
196
+ end
197
+
198
+ def discount_price
199
+ (product_type_entry[:discount] * price).to_i
200
+ end
201
+ end
202
+
203
+ it "test_update_entry_name" do
204
+ # DBに全くデータがなくてもコードで記述してあるエントリは存在します。
205
+ ItemMaster.delete_all("category_name = 'product_type_cd'")
206
+ ProductWithDB1.product_type_entries.length.should == 4
207
+ ProductWithDB1.product_type_name_by_key(:book).should == '書籍'
208
+ ProductWithDB1.product_type_name_by_key(:dvd).should == 'DVD'
209
+ ProductWithDB1.product_type_name_by_key(:cd).should == 'CD'
210
+ ProductWithDB1.product_type_name_by_key(:other).should == 'その他'
211
+
212
+ assert_product_discount(ProductWithDB1)
213
+
214
+ # DBからエントリの名称を動的に変更できます
215
+ item_book = ItemMaster.create(:category_name => 'product_type_cd', :item_no => 1, :item_cd => '01', :name => '本')
216
+ ProductWithDB1.product_type_entries.length.should == 4
217
+ ProductWithDB1.product_type_name_by_key(:book).should == '本'
218
+ ProductWithDB1.product_type_name_by_key(:dvd).should == 'DVD'
219
+ ProductWithDB1.product_type_name_by_key(:cd).should == 'CD'
220
+ ProductWithDB1.product_type_name_by_key(:other).should == 'その他'
221
+ ProductWithDB1.product_type_options.should ==
222
+ [['本', '01'], ['DVD', '02'], ['CD', '03'], ['その他', '09']]
223
+
224
+ # DBからエントリの並び順を動的に変更できます
225
+ item_book.item_no = 4;
226
+ item_book.save!
227
+ item_other = ItemMaster.create(:category_name => 'product_type_cd', :item_no => 1, :item_cd => '09', :name => 'その他')
228
+ item_dvd = ItemMaster.create(:category_name => 'product_type_cd', :item_no => 2, :item_cd => '02') # nameは指定しなかったらデフォルトが使われます。
229
+ item_cd = ItemMaster.create(:category_name => 'product_type_cd', :item_no => 3, :item_cd => '03') # nameは指定しなかったらデフォルトが使われます。
230
+ ProductWithDB1.product_type_options.should ==
231
+ [['その他', '09'], ['DVD', '02'], ['CD', '03'], ['本', '01']]
232
+
233
+ # DBからエントリを動的に追加することも可能です。
234
+ item_toys = ItemMaster.create(:category_name => 'product_type_cd', :item_no => 5, :item_cd => '04', :name => 'おもちゃ')
235
+ ProductWithDB1.product_type_options.should ==
236
+ [['その他', '09'], ['DVD', '02'], ['CD', '03'], ['本', '01'], ['おもちゃ', '04']]
237
+ ProductWithDB1.product_type_key_by_id('04').should == :entry_04
238
+
239
+ # DBからレコードを削除してもコードで定義したentryは削除されません。
240
+ # 順番はDBからの取得順で並び替えられたものの後になります
241
+ item_dvd.destroy
242
+ ProductWithDB1.product_type_options.should ==
243
+ [['その他', '09'], ['CD', '03'], ['本', '01'], ['おもちゃ', '04'], ['DVD', '02']]
244
+
245
+ # DB上で追加したレコードを削除すると、エントリも削除されます
246
+ item_toys.destroy
247
+ ProductWithDB1.product_type_options.should ==
248
+ [['その他', '09'], ['CD', '03'], ['本', '01'], ['DVD', '02']]
249
+
250
+ # 名称を指定していたDBのレコードを削除したら元に戻ります。
251
+ item_book.destroy
252
+ ProductWithDB1.product_type_options.should ==
253
+ [['その他', '09'], ['CD', '03'], ['書籍', '01'], ['DVD', '02']]
254
+
255
+ # エントリに該当するレコードを全部削除したら、元に戻ります。
256
+ ItemMaster.delete_all("category_name = 'product_type_cd'")
257
+ ProductWithDB1.product_type_options.should ==
258
+ [['書籍', '01'], ['DVD', '02'], ['CD', '03'], ['その他', '09']]
259
+
260
+ assert_product_discount(ProductWithDB1)
261
+ end
262
+
263
+
264
+
265
+
266
+ # Q: product_type_cd の'_cd'はどこにいっちゃったの?
267
+ # A: デフォルトでは、/(_cd$|_code$|_cds$|_codes$)/ を削除したものをbase_nameとして
268
+ # 扱い、それに_keyなどを付加してメソッド名を定義します。もしこのルールを変更したい場合、
269
+ # selectable_attrを使う前に selectable_attr_name_pattern で新たなルールを指定してください。
270
+ class Product2 < ActiveRecord::Base
271
+ set_table_name 'products'
272
+ self.selectable_attr_name_pattern = /^product_|_cd$/
273
+
274
+ selectable_attr :product_type_cd do
275
+ entry '01', :book, '書籍', :discount => 0.8
276
+ entry '02', :dvd, 'DVD', :discount => 0.2
277
+ entry '03', :cd, 'CD', :discount => 0.5
278
+ entry '09', :other, 'その他', :discount => 1
279
+ end
280
+
281
+ def discount_price
282
+ (type_entry[:discount] * price).to_i
283
+ end
284
+ end
285
+
286
+ it "test_product2" do
287
+ assert_product_discount(Product2)
288
+ # 選択肢を表示するためのデータは以下のように取得できる
289
+ Product2.type_options.should ==
290
+ [['書籍', '01'], ['DVD', '02'], ['CD', '03'], ['その他', '09']]
291
+
292
+ p2 = Product2.new
293
+ p2.product_type_cd.should be_nil
294
+ p2.type_key.should be_nil
295
+ p2.type_name.should be_nil
296
+ # idを変更すると得られるキーも名称も変わります
297
+ p2.product_type_cd = '02'
298
+ p2.product_type_cd.should == '02'
299
+ p2.type_key.should == :dvd
300
+ p2.type_name.should == 'DVD'
301
+ # キーを変更すると得られるidも名称も変わります
302
+ p2.type_key = :book
303
+ p2.product_type_cd.should == '01'
304
+ p2.type_key.should == :book
305
+ p2.type_name.should == '書籍'
306
+ # id、キー、名称以外の任意の属性は、entryの[]メソッドで取得します。
307
+ p2.type_key = :cd
308
+ p2.type_entry[:discount].should == 0.5
309
+
310
+ Product2.type_id_by_key(:book).should == '01'
311
+ Product2.type_id_by_key(:dvd).should == '02'
312
+ Product2.type_name_by_key(:cd).should == 'CD'
313
+ Product2.type_name_by_key(:other).should == 'その他'
314
+ Product2.type_key_by_id('09').should == :other
315
+ Product2.type_name_by_id('01').should == '書籍'
316
+ Product2.type_keys.should == [:book, :dvd, :cd, :other]
317
+ Product2.type_names.should == ['書籍', 'DVD', 'CD', 'その他']
318
+ Product2.type_keys('02', '03').should == [:dvd, :cd]
319
+ Product2.type_names(:cd, :dvd).should == ['CD', 'DVD']
320
+ end
321
+
322
+
323
+
324
+
325
+ # Q: selectable_attrの呼び出し毎にbase_bname(って言うの?)を指定したいんだけど。
326
+ # A: base_nameオプションを指定してください。
327
+ class Product3 < ActiveRecord::Base
328
+ set_table_name 'products'
329
+
330
+ selectable_attr :product_type_cd, :base_name => 'type' do
331
+ entry '01', :book, '書籍', :discount => 0.8
332
+ entry '02', :dvd, 'DVD', :discount => 0.2
333
+ entry '03', :cd, 'CD', :discount => 0.5
334
+ entry '09', :other, 'その他', :discount => 1
335
+ end
336
+
337
+ def discount_price
338
+ (type_entry[:discount] * price).to_i
339
+ end
340
+ end
341
+
342
+ it "test_product3" do
343
+ assert_product_discount(Product3)
344
+ # 選択肢を表示するためのデータは以下のように取得できる
345
+ Product3.type_options.should ==
346
+ [['書籍', '01'], ['DVD', '02'], ['CD', '03'], ['その他', '09']]
347
+
348
+ p3 = Product3.new
349
+ p3.product_type_cd.should be_nil
350
+ p3.type_key.should be_nil
351
+ p3.type_name.should be_nil
352
+ # idを変更すると得られるキーも名称も変わります
353
+ p3.product_type_cd = '02'
354
+ p3.product_type_cd.should == '02'
355
+ p3.type_key.should == :dvd
356
+ p3.type_name.should == 'DVD'
357
+ # キーを変更すると得られるidも名称も変わります
358
+ p3.type_key = :book
359
+ p3.product_type_cd.should == '01'
360
+ p3.type_key.should == :book
361
+ p3.type_name.should == '書籍'
362
+ # id、キー、名称以外の任意の属性は、entryの[]メソッドで取得します。
363
+ p3.type_key = :cd
364
+ p3.type_entry[:discount].should == 0.5
365
+
366
+ Product3.type_id_by_key(:book).should == '01'
367
+ Product3.type_id_by_key(:dvd).should == '02'
368
+ Product3.type_name_by_key(:cd).should == 'CD'
369
+ Product3.type_name_by_key(:other).should == 'その他'
370
+ Product3.type_key_by_id('09').should == :other
371
+ Product3.type_name_by_id('01').should == '書籍'
372
+ Product3.type_keys.should == [:book, :dvd, :cd, :other]
373
+ Product3.type_names.should == ['書籍', 'DVD', 'CD', 'その他']
374
+ Product3.type_keys('02', '03').should == [:dvd, :cd]
375
+ Product3.type_names(:cd, :dvd).should == ['CD', 'DVD']
376
+ end
377
+
378
+ end
379
+
data/spec/schema.rb ADDED
@@ -0,0 +1,30 @@
1
+ ActiveRecord::Schema.define(:version => 1) do
2
+
3
+ create_table "products", :force => true do |t|
4
+ t.string "product_type_cd"
5
+ t.integer "price"
6
+ t.string "name"
7
+ t.datetime "created_at"
8
+ t.datetime "updated_at"
9
+ end
10
+
11
+ create_table "item_masters", :force => true do |t|
12
+ t.string "category_name", :limit => 20
13
+ t.integer "item_no"
14
+ t.string "item_cd", :limit => 2
15
+ t.string "name", :limit => 20
16
+ t.datetime "created_at"
17
+ t.datetime "updated_at"
18
+ end
19
+
20
+ create_table "i18n_item_masters", :force => true do |t|
21
+ t.string "locale", :limit => 5
22
+ t.string "category_name", :limit => 20
23
+ t.integer "item_no"
24
+ t.string "item_cd", :limit => 2
25
+ t.string "name", :limit => 20
26
+ t.datetime "created_at"
27
+ t.datetime "updated_at"
28
+ end
29
+
30
+ end
@@ -0,0 +1,276 @@
1
+ # -*- coding: utf-8 -*-
2
+ if defined?(I18n)
3
+ require File.join(File.dirname(__FILE__), 'test_helper')
4
+
5
+ class SelectableAttrI18nTest < Test::Unit::TestCase
6
+
7
+ def setup
8
+ I18n.backend = I18n::Backend::Simple.new
9
+ I18n.backend.store_translations 'en', :selectable_attrs => {:enum1 => {
10
+ :entry1 => 'entry one',
11
+ :entry2 => 'entry two',
12
+ :entry3 => 'entry three'
13
+ } }
14
+ I18n.backend.store_translations 'ja', :selectable_attrs => {:enum1 => {
15
+ :entry1 => 'エントリ壱',
16
+ :entry2 => 'エントリ弐',
17
+ :entry3 => 'エントリ参'
18
+ } }
19
+ end
20
+
21
+ Enum1 = SelectableAttr::Enum.new do
22
+ i18n_scope(:selectable_attrs, :enum1)
23
+ entry 1, :entry1, "エントリ1"
24
+ entry 2, :entry2, "エントリ2"
25
+ entry 3, :entry3, "エントリ3"
26
+ end
27
+
28
+ def test_enum1_i18n
29
+ I18n.locale = nil
30
+ # assert_equal nil, I18n.locale
31
+ # assert_equal "エントリ1", Enum1.name_by_key(:entry1)
32
+ # assert_equal "エントリ2", Enum1.name_by_key(:entry2)
33
+ # assert_equal "エントリ3", Enum1.name_by_key(:entry3)
34
+ # assert_equal ["エントリ1", "エントリ2", "エントリ3"], Enum1.names
35
+ assert_equal :en, I18n.locale
36
+ assert_equal "entry one", Enum1.name_by_key(:entry1)
37
+ assert_equal "entry two", Enum1.name_by_key(:entry2)
38
+ assert_equal "entry three", Enum1.name_by_key(:entry3)
39
+ assert_equal ["entry one", "entry two", "entry three"], Enum1.names
40
+
41
+ I18n.locale = 'ja'
42
+ assert_equal "エントリ壱", Enum1.name_by_key(:entry1)
43
+ assert_equal "エントリ弐", Enum1.name_by_key(:entry2)
44
+ assert_equal "エントリ参", Enum1.name_by_key(:entry3)
45
+ assert_equal ["エントリ壱", "エントリ弐", "エントリ参"], Enum1.names
46
+
47
+ I18n.locale = 'en'
48
+ assert_equal "entry one", Enum1.name_by_key(:entry1)
49
+ assert_equal "entry two", Enum1.name_by_key(:entry2)
50
+ assert_equal "entry three", Enum1.name_by_key(:entry3)
51
+ assert_equal ["entry one", "entry two", "entry three"], Enum1.names
52
+ end
53
+
54
+ class EnumBase
55
+ include ::SelectableAttr::Base
56
+ end
57
+
58
+ class SelectableAttrMock1 < EnumBase
59
+ selectable_attr :attr1, :default => 2 do
60
+ i18n_scope(:selectable_attrs, :enum1)
61
+ entry 1, :entry1, "エントリ1"
62
+ entry 2, :entry2, "エントリ2"
63
+ entry 3, :entry3, "エントリ3"
64
+ end
65
+ end
66
+
67
+ def test_attr1_i18n
68
+ I18n.default_locale = 'ja'
69
+ I18n.locale = nil
70
+ # assert_equal nil, I18n.locale
71
+ # assert_equal "エントリ1", SelectableAttrMock1.attr1_name_by_key(:entry1)
72
+ # assert_equal "エントリ2", SelectableAttrMock1.attr1_name_by_key(:entry2)
73
+ # assert_equal "エントリ3", SelectableAttrMock1.attr1_name_by_key(:entry3)
74
+ assert_equal 'ja', I18n.locale
75
+ assert_equal "エントリ壱", SelectableAttrMock1.attr1_name_by_key(:entry1)
76
+ assert_equal "エントリ弐", SelectableAttrMock1.attr1_name_by_key(:entry2)
77
+ assert_equal "エントリ参", SelectableAttrMock1.attr1_name_by_key(:entry3)
78
+ assert_equal [["エントリ壱",1], ["エントリ弐",2], ["エントリ参",3]], SelectableAttrMock1.attr1_options
79
+
80
+ I18n.locale = 'ja'
81
+ assert_equal "エントリ壱", SelectableAttrMock1.attr1_name_by_key(:entry1)
82
+ assert_equal "エントリ弐", SelectableAttrMock1.attr1_name_by_key(:entry2)
83
+ assert_equal "エントリ参", SelectableAttrMock1.attr1_name_by_key(:entry3)
84
+ assert_equal [["エントリ壱",1], ["エントリ弐",2], ["エントリ参",3]], SelectableAttrMock1.attr1_options
85
+
86
+ I18n.locale = 'en'
87
+ assert_equal "entry one", SelectableAttrMock1.attr1_name_by_key(:entry1)
88
+ assert_equal "entry two", SelectableAttrMock1.attr1_name_by_key(:entry2)
89
+ assert_equal "entry three", SelectableAttrMock1.attr1_name_by_key(:entry3)
90
+ assert_equal [["entry one",1], ["entry two",2], ["entry three",3]], SelectableAttrMock1.attr1_options
91
+ end
92
+
93
+ class SelectableAttrMock2 < EnumBase
94
+ selectable_attr :enum1, :default => 2 do
95
+ i18n_scope(:selectable_attrs, :enum1)
96
+ entry 1, :entry1, "エントリ1"
97
+ entry 2, :entry2, "エントリ2"
98
+ entry 3, :entry3, "エントリ3"
99
+ end
100
+ end
101
+
102
+ def test_enum1_i18n
103
+ I18n.default_locale = 'ja'
104
+ I18n.locale = nil
105
+ # assert_equal nil, I18n.locale
106
+ # assert_equal "エントリ1", SelectableAttrMock2.enum1_name_by_key(:entry1)
107
+ # assert_equal "エントリ2", SelectableAttrMock2.enum1_name_by_key(:entry2)
108
+ # assert_equal "エントリ3", SelectableAttrMock2.enum1_name_by_key(:entry3)
109
+ assert_equal 'ja', I18n.locale
110
+ assert_equal "エントリ壱", SelectableAttrMock2.enum1_name_by_key(:entry1)
111
+ assert_equal "エントリ弐", SelectableAttrMock2.enum1_name_by_key(:entry2)
112
+ assert_equal "エントリ参", SelectableAttrMock2.enum1_name_by_key(:entry3)
113
+ assert_equal [["エントリ壱",1], ["エントリ弐",2], ["エントリ参",3]], SelectableAttrMock2.enum1_options
114
+
115
+ I18n.locale = 'ja'
116
+ assert_equal "エントリ壱", SelectableAttrMock2.enum1_name_by_key(:entry1)
117
+ assert_equal "エントリ弐", SelectableAttrMock2.enum1_name_by_key(:entry2)
118
+ assert_equal "エントリ参", SelectableAttrMock2.enum1_name_by_key(:entry3)
119
+ assert_equal [["エントリ壱",1], ["エントリ弐",2], ["エントリ参",3]], SelectableAttrMock2.enum1_options
120
+
121
+ I18n.locale = 'en'
122
+ assert_equal "entry one", SelectableAttrMock2.enum1_name_by_key(:entry1)
123
+ assert_equal "entry two", SelectableAttrMock2.enum1_name_by_key(:entry2)
124
+ assert_equal "entry three", SelectableAttrMock2.enum1_name_by_key(:entry3)
125
+ assert_equal [["entry one",1], ["entry two",2], ["entry three",3]], SelectableAttrMock2.enum1_options
126
+ end
127
+
128
+ # i18n用のlocaleカラムを持つselectable_attrのエントリ名をDB上に保持するためのモデル
129
+ class I18nItemMaster < ActiveRecord::Base
130
+ end
131
+
132
+ # selectable_attrを使った場合その3
133
+ # アクセス時に毎回アクセス時にDBから項目名を取得します。
134
+ # 対象となる項目名はi18n対応している名称です
135
+ class ProductWithI18nDB1 < ActiveRecord::Base
136
+ set_table_name 'products'
137
+ selectable_attr :product_type_cd do
138
+ # update_byメソッドには、エントリのidと名称を返すSELECT文を指定する代わりに、
139
+ # エントリのidと名称の配列の配列を返すブロックを指定することも可能です。
140
+ update_by(:when => :everytime) do
141
+ records = I18nItemMaster.find(:all,
142
+ :conditions => [
143
+ "category_name = 'product_type_cd' and locale = ? ", I18n.locale.to_s],
144
+ :order => "item_no")
145
+ records.map{|r| [r.item_cd, r.name]}
146
+ end
147
+ entry '01', :book, '書籍', :discount => 0.8
148
+ entry '02', :dvd, 'DVD', :discount => 0.2
149
+ entry '03', :cd, 'CD', :discount => 0.5
150
+ entry '09', :other, 'その他', :discount => 1
151
+ end
152
+
153
+ end
154
+
155
+ def test_update_entry_name_with_i18n
156
+ I18n.locale = 'ja'
157
+ # DBに全くデータがなくてもコードで記述してあるエントリは存在します。
158
+ I18nItemMaster.delete_all("category_name = 'product_type_cd'")
159
+ assert_equal 4, ProductWithI18nDB1.product_type_entries.length
160
+ assert_equal '書籍', ProductWithI18nDB1.product_type_name_by_key(:book)
161
+ assert_equal 'DVD', ProductWithI18nDB1.product_type_name_by_key(:dvd)
162
+ assert_equal 'CD', ProductWithI18nDB1.product_type_name_by_key(:cd)
163
+ assert_equal 'その他', ProductWithI18nDB1.product_type_name_by_key(:other)
164
+
165
+ # assert_product_discount(ProductWithI18nDB1)
166
+
167
+ # DBからエントリの名称を動的に変更できます
168
+ item_book = I18nItemMaster.create(:locale => 'ja', :category_name => 'product_type_cd', :item_no => 1, :item_cd => '01', :name => '本')
169
+ assert_equal 4, ProductWithI18nDB1.product_type_entries.length
170
+ assert_equal '本', ProductWithI18nDB1.product_type_name_by_key(:book)
171
+ assert_equal 'DVD', ProductWithI18nDB1.product_type_name_by_key(:dvd)
172
+ assert_equal 'CD', ProductWithI18nDB1.product_type_name_by_key(:cd)
173
+ assert_equal 'その他', ProductWithI18nDB1.product_type_name_by_key(:other)
174
+ assert_equal [['本', '01'], ['DVD', '02'], ['CD', '03'], ['その他', '09']], ProductWithI18nDB1.product_type_options
175
+
176
+ # DBからエントリの並び順を動的に変更できます
177
+ item_book.item_no = 4;
178
+ item_book.save!
179
+ item_other = I18nItemMaster.create(:locale => 'ja', :category_name => 'product_type_cd', :item_no => 1, :item_cd => '09', :name => 'その他')
180
+ item_dvd = I18nItemMaster.create(:locale => 'ja', :category_name => 'product_type_cd', :item_no => 2, :item_cd => '02') # nameは指定しなかったらデフォルトが使われます。
181
+ item_cd = I18nItemMaster.create(:locale => 'ja', :category_name => 'product_type_cd', :item_no => 3, :item_cd => '03') # nameは指定しなかったらデフォルトが使われます。
182
+ assert_equal [['その他', '09'], ['DVD', '02'], ['CD', '03'], ['本', '01']], ProductWithI18nDB1.product_type_options
183
+
184
+ # DBからエントリを動的に追加することも可能です。
185
+ item_toys = I18nItemMaster.create(:locale => 'ja', :category_name => 'product_type_cd', :item_no => 5, :item_cd => '04', :name => 'おもちゃ')
186
+ assert_equal [['その他', '09'], ['DVD', '02'], ['CD', '03'], ['本', '01'], ['おもちゃ', '04']], ProductWithI18nDB1.product_type_options
187
+ assert_equal :entry_04, ProductWithI18nDB1.product_type_key_by_id('04')
188
+
189
+ # 英語名を登録
190
+ item_book = I18nItemMaster.create(:locale => 'en', :category_name => 'product_type_cd', :item_no => 4, :item_cd => '01', :name => 'Book')
191
+ item_other = I18nItemMaster.create(:locale => 'en', :category_name => 'product_type_cd', :item_no => 1, :item_cd => '09', :name => 'Others')
192
+ item_dvd = I18nItemMaster.create(:locale => 'en', :category_name => 'product_type_cd', :item_no => 2, :item_cd => '02', :name => 'DVD')
193
+ item_cd = I18nItemMaster.create(:locale => 'en', :category_name => 'product_type_cd', :item_no => 3, :item_cd => '03', :name => 'CD')
194
+ item_toys = I18nItemMaster.create(:locale => 'en', :category_name => 'product_type_cd', :item_no => 5, :item_cd => '04', :name => 'Toy')
195
+
196
+ # 英語名が登録されていてもI18n.localeが変わらなければ、日本語のまま
197
+ assert_equal [['その他', '09'], ['DVD', '02'], ['CD', '03'], ['本', '01'], ['おもちゃ', '04']], ProductWithI18nDB1.product_type_options
198
+ assert_equal :entry_04, ProductWithI18nDB1.product_type_key_by_id('04')
199
+
200
+ # I18n.localeを変更すると取得できるエントリの名称も変わります
201
+ I18n.locale = 'en'
202
+ assert_equal [['Others', '09'], ['DVD', '02'], ['CD', '03'], ['Book', '01'], ['Toy', '04']], ProductWithI18nDB1.product_type_options
203
+ assert_equal :entry_04, ProductWithI18nDB1.product_type_key_by_id('04')
204
+
205
+ I18n.locale = 'ja'
206
+ assert_equal [['その他', '09'], ['DVD', '02'], ['CD', '03'], ['本', '01'], ['おもちゃ', '04']], ProductWithI18nDB1.product_type_options
207
+ assert_equal :entry_04, ProductWithI18nDB1.product_type_key_by_id('04')
208
+
209
+ I18n.locale = 'en'
210
+ assert_equal [['Others', '09'], ['DVD', '02'], ['CD', '03'], ['Book', '01'], ['Toy', '04']], ProductWithI18nDB1.product_type_options
211
+ assert_equal :entry_04, ProductWithI18nDB1.product_type_key_by_id('04')
212
+
213
+ # DBからレコードを削除してもコードで定義したentryは削除されません。
214
+ # 順番はDBからの取得順で並び替えられたものの後になります
215
+ item_dvd.destroy
216
+ assert_equal [['Others', '09'], ['CD', '03'], ['Book', '01'], ['Toy', '04'], ['DVD', '02']], ProductWithI18nDB1.product_type_options
217
+
218
+ # DB上で追加したレコードを削除すると、エントリも削除されます
219
+ item_toys.destroy
220
+ assert_equal [['Others', '09'], ['CD', '03'], ['Book', '01'], ['DVD', '02']], ProductWithI18nDB1.product_type_options
221
+
222
+ # 名称を指定していたDBのレコードを削除したら元に戻ります。
223
+ item_book.destroy
224
+ assert_equal [['Others', '09'], ['CD', '03'], ['書籍', '01'], ['DVD', '02']], ProductWithI18nDB1.product_type_options
225
+
226
+ # エントリに該当するレコードを全部削除したら、元に戻ります。
227
+ I18nItemMaster.delete_all("category_name = 'product_type_cd'")
228
+ assert_equal [['書籍', '01'], ['DVD', '02'], ['CD', '03'], ['その他', '09']], ProductWithI18nDB1.product_type_options
229
+ end
230
+
231
+ def test_i18n_export
232
+ I18nItemMaster.delete_all("category_name = 'product_type_cd'")
233
+
234
+ I18n.locale = 'ja'
235
+ actual = SelectableAttr::Enum.i18n_export
236
+ assert_equal [:selectable_attrs], actual.keys
237
+ assert_equal true, actual[:selectable_attrs].keys.include?(:enum1)
238
+ assert_equal(
239
+ {:entry1=>"エントリ壱",
240
+ :entry2=>"エントリ弐",
241
+ :entry3=>"エントリ参"},
242
+ actual[:selectable_attrs][:enum1])
243
+
244
+ assert_equal true, actual[:selectable_attrs].keys.include?(:SelectableAttrI18nTest)
245
+ assert_equal(
246
+ {:ProductWithI18nDB1=>
247
+ {:product_type_cd=>
248
+ {:book=>"書籍", :dvd=>"DVD", :cd=>"CD", :other=>"その他"}}},
249
+ actual[:selectable_attrs][:SelectableAttrI18nTest])
250
+
251
+
252
+ I18nItemMaster.create(:locale => 'en', :category_name => 'product_type_cd', :item_no => 1, :item_cd => '09', :name => 'Others')
253
+ I18nItemMaster.create(:locale => 'en', :category_name => 'product_type_cd', :item_no => 2, :item_cd => '02', :name => 'DVD')
254
+ I18nItemMaster.create(:locale => 'en', :category_name => 'product_type_cd', :item_no => 3, :item_cd => '03', :name => 'CD')
255
+ I18nItemMaster.create(:locale => 'en', :category_name => 'product_type_cd', :item_no => 4, :item_cd => '01', :name => 'Book')
256
+ I18nItemMaster.create(:locale => 'en', :category_name => 'product_type_cd', :item_no => 5, :item_cd => '04', :name => 'Toy')
257
+
258
+ I18n.locale = 'en'
259
+ actual = SelectableAttr::Enum.i18n_export
260
+ assert_equal [:selectable_attrs], actual.keys
261
+ assert_equal true, actual[:selectable_attrs].keys.include?(:enum1)
262
+ assert_equal(
263
+ {:entry1=>"entry one",
264
+ :entry2=>"entry two",
265
+ :entry3=>"entry three"},
266
+ actual[:selectable_attrs][:enum1])
267
+ assert_equal true, actual[:selectable_attrs].keys.include?(:SelectableAttrI18nTest)
268
+ assert_equal(
269
+ {:ProductWithI18nDB1=>
270
+ {:product_type_cd=>
271
+ {:book=>"Book", :dvd=>"DVD", :cd=>"CD", :other=>"Others", :entry_04=>"Toy"}}},
272
+ actual[:selectable_attrs][:SelectableAttrI18nTest])
273
+
274
+ end
275
+ end
276
+ end
@@ -0,0 +1,30 @@
1
+ $KCODE='u'
2
+
3
+ FIXTURES_ROOT = File.join(File.dirname(__FILE__), 'fixtures') unless defined?(FIXTURES_ROOT)
4
+
5
+ require 'rubygems'
6
+ require 'active_support'
7
+ require 'active_record'
8
+ require 'active_record/fixtures'
9
+ require 'active_record/test_case'
10
+ require 'action_view'
11
+
12
+ require 'selectable_attr'
13
+
14
+ $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
15
+ require File.join(File.dirname(__FILE__), '..', 'init')
16
+
17
+ require 'yaml'
18
+ config = YAML.load(IO.read(File.join(File.dirname(__FILE__), 'database.yml')))
19
+ ActiveRecord::Base.logger = Logger.new(File.join(File.dirname(__FILE__), 'debug.log'))
20
+ ActiveRecord::Base.establish_connection(config[ENV['DB'] || 'sqlite3'])
21
+
22
+ load(File.join(File.dirname(__FILE__), 'schema.rb'))
23
+
24
+
25
+ def assert_hash(expected, actual)
26
+ keys = (expected.keys + actual.keys).uniq
27
+ keys.each do |key|
28
+ assert_equal expected[key], actual[key], "unmatch value for #{key.inspect}"
29
+ end
30
+ end
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: akm-selectable_attr_rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
+ platform: ruby
6
+ authors:
7
+ - Takeshi Akima
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-01-27 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: selectable_attr_rails makes possible to use selectable_attr in rails application
17
+ email: akima@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - VERSION.yml
26
+ - lib/selectable_attr_rails
27
+ - lib/selectable_attr_rails/db_loadable.rb
28
+ - lib/selectable_attr_rails/helpers
29
+ - lib/selectable_attr_rails/helpers/abstract_selection_helper.rb
30
+ - lib/selectable_attr_rails/helpers/check_box_group_helper.rb
31
+ - lib/selectable_attr_rails/helpers/radio_button_group_helper.rb
32
+ - lib/selectable_attr_rails/helpers/select_helper.rb
33
+ - lib/selectable_attr_rails/helpers.rb
34
+ - lib/selectable_attr_rails/version.rb
35
+ - lib/selectable_attr_rails.rb
36
+ - spec/database.yml
37
+ - spec/debug.log
38
+ - spec/fixtures
39
+ - spec/introduction_spec.rb
40
+ - spec/schema.rb
41
+ - spec/selectable_attr_i18n_test.rb
42
+ - spec/spec_helper.rb
43
+ has_rdoc: true
44
+ homepage: http://github.com/akm/selectable_attr_rails/
45
+ post_install_message:
46
+ rdoc_options:
47
+ - --inline-source
48
+ - --charset=UTF-8
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: "0"
56
+ version:
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: "0"
62
+ version:
63
+ requirements: []
64
+
65
+ rubyforge_project:
66
+ rubygems_version: 1.2.0
67
+ signing_key:
68
+ specification_version: 2
69
+ summary: selectable_attr_rails makes possible to use selectable_attr in rails application
70
+ test_files: []
71
+