akm-selectable_attr_rails 0.3.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.
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
+