Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

selectable_attrからrails依存部分を分けて別のgemにしました。

  • Loading branch information...
commit a1d0175b1870b997d9787744780b1aacd6e9c97e 1 parent 4e80635
akm2000 authored
View
1  .gitignore
@@ -0,0 +1 @@
+/selectable_attr_test.sqlite3.db
View
20 MIT-LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2008 Takeshi AKIMA
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
View
13 README
@@ -0,0 +1,13 @@
+SelectableAttrRails
+==============
+
+Introduction goes here.
+
+
+Example
+=======
+
+Example goes here.
+
+
+Copyright (c) 2008 Takeshi AKIMA, released under the MIT license
View
22 Rakefile
@@ -0,0 +1,22 @@
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+
+desc 'Default: run unit tests.'
+task :default => :test
+
+desc 'Test the selectable_attr plugin.'
+Rake::TestTask.new(:test) do |t|
+ t.libs << 'lib'
+ t.pattern = 'test/**/*_test.rb'
+ t.verbose = true
+end
+
+desc 'Generate documentation for the selectable_attr plugin.'
+Rake::RDocTask.new(:rdoc) do |rdoc|
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = 'SelectableAttr'
+ rdoc.options << '--line-numbers' << '--inline-source'
+ rdoc.rdoc_files.include('README')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
View
23 init.rb
@@ -0,0 +1,23 @@
+require 'selectable_attr'
+
+module SelectableAttr
+ class Enum
+ include SelectableAttr::DbLoadable
+ end
+end
+
+class ActiveRecord::Base
+ include SelectableAttr::Base
+end
+
+class ActionView::Base
+ include SelectableAttr::Helpers::SelectHelper::Base
+ include SelectableAttr::Helpers::CheckBoxGroupHelper::Base
+ include SelectableAttr::Helpers::RadioButtonGroupHelper::Base
+end
+
+class ActionView::Helpers::FormBuilder
+ include SelectableAttr::Helpers::SelectHelper::FormBuilder
+ include SelectableAttr::Helpers::CheckBoxGroupHelper::FormBuilder
+ include SelectableAttr::Helpers::RadioButtonGroupHelper::FormBuilder
+end
View
1  install.rb
@@ -0,0 +1 @@
+# Install hook code here
View
7 lib/selectable_attr_rails.rb
@@ -0,0 +1,7 @@
+# -*- coding: utf-8 -*-
+require 'selectable_attr'
+
+module SelectableAttrRails
+ autoload :Helpers, 'selectable_attr_rails/helpers'
+ autoload :DbLoadable, 'selectable_attr_rails/db_loadable'
+end
View
65 lib/selectable_attr_rails/db_loadable.rb
@@ -0,0 +1,65 @@
+module SelectableAttrRails
+ module DbLoadable
+ def update_by(*args, &block)
+ options = args.last.is_a?(Hash) ? args.pop : {}
+ options = {:when => :first_time}.update(options)
+ @sql_to_update = block_given? ? block : args.first
+ @update_timing = options[:when]
+ self.extend(InstanceMethods) unless respond_to?(:update_entries)
+ end
+
+ module Entry
+ attr_accessor :name_from_db
+ def name
+ @name_from_db || super
+ end
+ end
+
+ module InstanceMethods
+ def entries
+ update_entries if must_be_updated?
+ @entries
+ end
+
+ def must_be_updated?
+ return false if @update_timing == :never
+ return true if @update_timing == :everytime
+ end
+
+ def update_entries
+ unless @original_entries
+ @original_entries = @entries.dup
+ @original_entries.each do |entry|
+ entry.extend(SelectableAttr::DbLoadable::Entry)
+ end
+ end
+ records = nil
+ if @sql_to_update.respond_to?(:call)
+ records = @sql_to_update.call
+ else
+ @connection ||= ActiveRecord::Base.connection
+ records = @connection.select_rows(@sql_to_update)
+ end
+
+ new_entries = []
+ records.each do |r|
+ if entry = @original_entries.detect{|entry| entry.id == r.first}
+ entry.name_from_db = r.last unless r.last.blank?
+ new_entries << entry
+ else
+ entry = SelectableAttr::Enum::Entry.new(self, r.first, "entry_#{r.first}".to_sym, r.last)
+ new_entries << entry
+ end
+ end
+ @original_entries.each do |entry|
+ unless new_entries.include?(entry)
+ entry.name_from_db = nil
+ new_entries << entry if entry.defined_in_code
+ end
+ end
+ @entries = new_entries
+ end
+ end
+
+ end
+end
View
7 lib/selectable_attr_rails/helpers.rb
@@ -0,0 +1,7 @@
+module SelectableAttrRails
+ module Helpers
+ autoload :SelectHelper, 'selectable_attr_rails/helpers/select_helper'
+ autoload :CheckBoxGroupHelper, 'selectable_attr_rails/helpers/check_box_group_helper'
+ autoload :RadioButtonGroupHelper, 'selectable_attr_rails/helpers/radio_button_group_helper'
+ end
+end
View
55 lib/selectable_attr_rails/helpers/abstract_selection_helper.rb
@@ -0,0 +1,55 @@
+module SelectableAttrRails::Helpers
+ class AbstractSelectionBuilder
+ attr_reader :entry_hash
+
+ def initialize(object, object_name, method, options, template)
+ @object, @object_name, @method = object, object_name, method
+ @base_name = @object.class.enum_base_name(method.to_s)
+ @template = template
+ @entry_hash = nil
+ @options = options || {}
+ @entry_hash_array = @options[:entry_hash_array]
+ end
+
+ def enum_hash_array_from_object
+ base_name = @object.class.enum_base_name(@method.to_s)
+ @object.send("#{base_name}_hash_array")
+ end
+
+ def enum_hash_array_from_class
+ base_name = @object.class.enum_base_name(@method.to_s)
+ @object.class.send("#{base_name}_hash_array")
+ end
+
+ def tag_id(tag)
+ result = nil
+ tag.scan(/ id\=\"(.*?)\"/){|s|result = s}
+ return result
+ end
+
+ def add_class_name(options, class_name)
+ (options ||= {}).stringify_keys!
+ (options['class'] ||= '') << ' ' << class_name
+ options
+ end
+
+ def camelize_keys(hash, first_letter = :lower)
+ result = {}
+ hash.each{|key, value|result[key.to_s.camelize(first_letter)] = value}
+ result
+ end
+
+ def update_options(dest, *options_array)
+ result = dest || {}
+ options_array.each do |options|
+ next unless options
+ if class_name = options.delete(:class)
+ add_class_name(result, class_name)
+ end
+ result.update(options)
+ end
+ result
+ end
+
+ end
+end
View
63 lib/selectable_attr_rails/helpers/check_box_group_helper.rb
@@ -0,0 +1,63 @@
+require 'selectable_attr_rails/helpers/abstract_selection_helper'
+module SelectableAttrRails::Helpers
+ module CheckBoxGroupHelper
+ class Builder < SelectableAttrRails::Helpers::AbstractSelectionBuilder
+
+ def initialize(object, object_name, method, options, template)
+ super(object, object_name, method, options, template)
+ @entry_hash_array ||= enum_hash_array_from_object
+ @param_name = "#{@base_name}_ids"
+ @check_box_options = @options.delete(:check_box) || {}
+ end
+
+ def each(&block)
+ @entry_hash_array.each do |@entry_hash|
+ @tag_value = @entry_hash[:id].to_s.gsub(/\s/, "_").gsub(/\W/, "")
+ @check_box_id = "#{@object_name}_#{@param_name}_#{@tag_value}"
+ yield(self)
+ end
+ end
+
+ def check_box(options = nil)
+ options = update_options({
+ :id => @check_box_id, :type => 'checkbox', :value => @tag_value,
+ :name => "#{@object_name}[#{@param_name}][]"
+ }, @check_box_options, options)
+ options[:checked] = 'checked' if @entry_hash[:select]
+ @template.content_tag("input", nil, options)
+ end
+
+ def label(text = nil, options = nil)
+ @template.content_tag("label", text || @entry_hash[:name],
+ update_options({:for => @check_box_id}, options))
+ end
+ end
+
+ module Base
+ def check_box_group(object_name, method, options = nil, &block)
+ object = (options || {})[:object] || instance_variable_get("@#{object_name}")
+ builder = Builder.new(object, object_name, method, options, @template)
+ if block_given?
+ yield(builder)
+ return nil
+ else
+ result = ''
+ builder.each do
+ result << builder.check_box
+ result << '&nbsp;'
+ result << builder.label
+ result << '&nbsp;'
+ end
+ return result
+ end
+ end
+ end
+
+ module FormBuilder
+ def check_box_group(method, options = nil, &block)
+ @template.check_box_group(@object_name, method,
+ (options || {}).merge(:object => @object), &block)
+ end
+ end
+ end
+end
View
55 lib/selectable_attr_rails/helpers/radio_button_group_helper.rb
@@ -0,0 +1,55 @@
+module SelectableAttrRails::Helpers
+ module RadioButtonGroupHelper
+ class Builder < SelectableAttrRails::Helpers::AbstractSelectionBuilder
+
+ def initialize(object, object_name, method, options, template)
+ super(object, object_name, method, options, template)
+ @entry_hash_array ||= enum_hash_array_from_class
+ end
+
+ def each(&block)
+ @entry_hash_array.each do |entry_hash|
+ @entry_hash = entry_hash
+ tag_value = @entry_hash[:id].to_s.gsub(/\s/, "_").gsub(/\W/, "").downcase
+ @radio_button_id = "#{@object_name}_#{@method}_#{tag_value}"
+ yield(self)
+ end
+ end
+
+ def radio_button(options = nil)
+ @template.radio_button(@object_name, @method, @entry_hash[:id],
+ update_options({:id => @radio_button_id}, options))
+ end
+
+ def label(text = nil, options = nil)
+ @template.content_tag("label", text || @entry_hash[:name],
+ update_options({:for => @radio_button_id}, options))
+ end
+ end
+
+ module Base
+ def radio_button_group(object_name, method, options = nil, &block)
+ object = (options || {})[:object] || instance_variable_get("@#{object_name}")
+ builder = Builder.new(object, object_name, method, options, self)
+ if block_given?
+ yield(builder)
+ return nil
+ else
+ result = ''
+ builder.each do
+ result << builder.radio_button
+ result << builder.label
+ end
+ return result
+ end
+ end
+ end
+
+ module FormBuilder
+ def radio_button_group(method, options = nil, &block)
+ @template.radio_button_group(@object_name, method,
+ (options || {}).merge(:object => @object), &block)
+ end
+ end
+ end
+end
View
72 lib/selectable_attr_rails/helpers/select_helper.rb
@@ -0,0 +1,72 @@
+module SelectableAttrRails::Helpers
+ module SelectHelper
+ module Base
+ def self.included(base)
+ base.module_eval do
+ alias_method_chain :select, :attr_enumeable
+ end
+ end
+
+ # def select_with_attr_enumeable(object, method, choices, options = {}, html_options = {})
+ def select_with_attr_enumeable(object_name, method, *args, &block)
+ if args.length > 3
+ raise ArgumentError, "argument must be " <<
+ "(object, method, choices, options = {}, html_options = {}) or " <<
+ "(object, method, options = {}, html_options = {})"
+ end
+ return select_without_attr_enumeable(object_name, method, *args, &block) if args.length == 3
+ return select_without_attr_enumeable(object_name, method, *args, &block) if args.first.is_a?(Array)
+ options, html_options = *args
+ options = update_enum_select_options(options, object_name, method)
+ object, base_name = options[:object], options[:base_name]
+ return multi_enum_select(object_name, method, options, html_options, &block) if object.respond_to?("#{base_name}_hash_array")
+ return single_enum_select(object_name, method, options, html_options, &block) if object.class.respond_to?("#{base_name}_hash_array")
+ raise ArgumentError, "invaliad argument"
+ end
+
+ def single_enum_select(object_name, method, options = {}, html_options = {}, &block)
+ options = update_enum_select_options(options, object_name, method)
+ object = options.delete(:object)
+ base_name = options.delete(:base_name)
+ entry_hash_array = options.delete(:entry_hash_array) || object.class.send("#{base_name}_hash_array")
+ container = entry_hash_array.map{|hash| [hash[:name].to_s, hash[:id]]}
+ select_without_attr_enumeable(object_name, method, container, options, html_options || {}, &block)
+ end
+
+ def multi_enum_select(object_name, method, options = {}, html_options = {}, &block)
+ html_options = {:size => 5, :multiple => 'multiple'}.update(html_options || {})
+ options = update_enum_select_options(options, object_name, method)
+ object = options.delete(:object)
+ base_name = options.delete(:base_name)
+ entry_hash_array = options.delete(:entry_hash_array) || object.send("#{base_name}_hash_array")
+ container = entry_hash_array.map{|hash| [hash[:name].to_s, hash[:id].to_s]}
+ attr = "#{base_name}_ids"
+ select_without_attr_enumeable(object_name, attr, container, options, html_options, &block)
+ end
+
+ def update_enum_select_options(options, object_name, method)
+ options ||= {}
+ object = (options[:object] ||= instance_variable_get("@#{object_name}"))
+ options[:base_name] ||= object.class.enum_base_name(method.to_s)
+ options
+ end
+ end
+
+ module FormBuilder
+ def self.included(base)
+ base.module_eval do
+ alias_method_chain :select, :attr_enumeable
+ end
+ end
+
+ # def select_with_attr_enumeable(method, choices, options = {}, html_options = {}, &block)
+ def select_with_attr_enumeable(method, *args, &block)
+ options = args.first.is_a?(Array) ? (args[1] ||= {}) : (args[0] ||= {})
+ object = (options || {}).delete(:object) || @object || instance_variable_get(@object_name) rescue nil
+ options.update({:object => object})
+ options[:selected] = object.send(method) if object
+ @template.select(@object_name, method, *args, &block)
+ end
+ end
+ end
+end
View
3  lib/selectable_attr_rails/version.rb
@@ -0,0 +1,3 @@
+module SelectableAttrRails
+ VERSION = '0.0.3'
+end
View
27 selectable_attr_rails.gemspec
@@ -0,0 +1,27 @@
+require 'rake'
+require File.join(File.dirname(__FILE__), 'lib', 'selectable_attr_rails', 'version')
+
+Gem::Specification.new do |spec|
+ spec.name = "selectable_attr_rails"
+ spec.version = SelectableAttrRails::VERSION
+ spec.platform = "ruby"
+ spec.summary = "selectable_attr_rails makes possible to use selectable_attr in rails application"
+ spec.author = "Takeshi Akima"
+ spec.email = "akima@gmail.com"
+ spec.homepage = "http://d.hatena.ne.jp/akm"
+ spec.rubyforge_project = "rubybizcommons"
+ spec.has_rdoc = false
+
+ spec.add_dependency("activerecord", ">= 2.1.0")
+ spec.add_dependency("selectable_attr", SelectableAttrRails::VERSION)
+
+ spec.files = FileList['Rakefile', 'bin/*', '*.rb', '{lib,test}/**/*.{rb}', 'tasks/**/*.{rake}'].to_a
+ spec.require_path = "lib"
+ spec.requirements = ["none"]
+ # spec.autorequire = 'selectable_attr_rails' # autorequire is deprecated
+
+ # bin_files = FileList['bin/*'].to_a.map{|file| file.gsub(/^bin\//, '')}
+ # spec.executables = bin_files
+
+ # spec.default_executable = 'some_executable.sh'
+end
View
18 tasks/selectable_attr_tasks.rake
@@ -0,0 +1,18 @@
+require 'yaml'
+require 'yaml_waml'
+
+namespace :i18n do
+ namespace :selectable_attr do
+ task :load_all_models => :environment do
+ Dir.glob(File.join(RAILS_ROOT, 'app', 'models', '**', '*.rb')) do |file_name|
+ require file_name
+ end
+ end
+
+ desc "Export i18n resources for selectable_attr entries"
+ task :export => :"i18n:selectable_attr:load_all_models" do
+ obj = {I18n.locale => SelectableAttr::Enum.i18n_export}
+ puts YAML.dump(obj)
+ end
+ end
+end
View
6 test/database.yml
@@ -0,0 +1,6 @@
+sqlite:
+ :adapter: sqlite
+ :dbfile: selectable_attr_test.sqlite.db
+sqlite3:
+ :adapter: sqlite3
+ :dbfile: selectable_attr_test.sqlite3.db
View
0  test/fixtures/.gitignore
No changes.
View
371 test/introduction_test.rb
@@ -0,0 +1,371 @@
+# -*- coding: utf-8 -*-
+require File.join(File.dirname(__FILE__), 'test_helper')
+
+class IntroductionTest < Test::Unit::TestCase
+
+ def assert_product_discount(klass)
+ # productsテーブルのデータから安売り用の価格は
+ # product_type_cd毎に決められた割合をpriceにかけて求めます。
+ p1 = klass.new(:name => '実践Rails', :product_type_cd => '01', :price => 3000)
+ assert_equal 2400, p1.discount_price
+ p2 = klass.new(:name => '薔薇の名前', :product_type_cd => '02', :price => 1500)
+ assert_equal 300, p2.discount_price
+ p3 = klass.new(:name => '未来派野郎', :product_type_cd => '03', :price => 3000)
+ assert_equal 1500, p3.discount_price
+ end
+
+ # 定数をガンガン定義した場合
+ # 大文字が多くて読みにくいし、関連するデータ(ここではDISCOUNT)が増える毎に定数も増えていきます。
+ class LegacyProduct1 < ActiveRecord::Base
+ set_table_name 'products'
+
+ PRODUCT_TYPE_BOOK = '01'
+ PRODUCT_TYPE_DVD = '02'
+ PRODUCT_TYPE_CD = '03'
+ PRODUCT_TYPE_OTHER = '09'
+
+ PRODUCT_TYPE_OPTIONS = [
+ ['書籍', PRODUCT_TYPE_BOOK],
+ ['DVD', PRODUCT_TYPE_DVD],
+ ['CD', PRODUCT_TYPE_CD],
+ ['その他', PRODUCT_TYPE_OTHER]
+ ]
+
+ DISCOUNT = {
+ PRODUCT_TYPE_BOOK => 0.8,
+ PRODUCT_TYPE_DVD => 0.2,
+ PRODUCT_TYPE_CD => 0.5,
+ PRODUCT_TYPE_OTHER => 1
+ }
+
+ def discount_price
+ (DISCOUNT[product_type_cd] * price).to_i
+ end
+ end
+
+ def test_legacy_product
+ assert_product_discount(LegacyProduct1)
+
+ # 選択肢を表示するためのデータは以下のように取得できる
+ assert_equal([['書籍', '01'], ['DVD', '02'], ['CD', '03'], ['その他', '09']],
+ LegacyProduct1::PRODUCT_TYPE_OPTIONS)
+ end
+
+
+
+
+ # できるだけ定数定義をまとめた場合
+ # 結構すっきりするけど、同じことをいろんなモデルで書くかと思うと気が重い。
+ class LegacyProduct2 < ActiveRecord::Base
+ set_table_name 'products'
+
+ PRODUCT_TYPE_DEFS = [
+ {:id => '01', :name => '書籍', :discount => 0.8},
+ {:id => '02', :name => 'DVD', :discount => 0.2},
+ {:id => '03', :name => 'CD', :discount => 0.5},
+ {:id => '09', :name => 'その他', :discount => 1}
+ ]
+
+ PRODUCT_TYPE_OPTIONS = PRODUCT_TYPE_DEFS.map{|t| [t[:name], t[:id]]}
+ DISCOUNT = PRODUCT_TYPE_DEFS.inject({}){|dest, t|
+ dest[t[:id]] = t[:discount]; dest}
+
+ def discount_price
+ (DISCOUNT[product_type_cd] * price).to_i
+ end
+ end
+
+ def test_legacy_product
+ assert_product_discount(LegacyProduct2)
+
+ # 選択肢を表示するためのデータは以下のように取得できる
+ assert_equal([['書籍', '01'], ['DVD', '02'], ['CD', '03'], ['その他', '09']],
+ LegacyProduct2::PRODUCT_TYPE_OPTIONS)
+ end
+
+ # selectable_attrを使った場合
+ # 定義は一カ所にまとめられて、任意の属性(ここでは:discount)も一緒に書くことができてすっきり〜
+ class Product1 < ActiveRecord::Base
+ set_table_name 'products'
+
+ selectable_attr :product_type_cd do
+ entry '01', :book, '書籍', :discount => 0.8
+ entry '02', :dvd, 'DVD', :discount => 0.2
+ entry '03', :cd, 'CD', :discount => 0.5
+ entry '09', :other, 'その他', :discount => 1
+ end
+
+ def discount_price
+ (product_type_entry[:discount] * price).to_i
+ end
+ end
+
+ def test_product1
+ assert_product_discount(Product1)
+ # 選択肢を表示するためのデータは以下のように取得できる
+ assert_equal([['書籍', '01'], ['DVD', '02'], ['CD', '03'], ['その他', '09']],
+ Product1.product_type_options)
+ end
+
+
+ # selectable_attrが定義するインスタンスメソッドの詳細
+ def test_product_type_instance_methods
+ p1 = Product1.new
+ assert_equal nil, p1.product_type_cd
+ assert_equal nil, p1.product_type_key
+ assert_equal nil, p1.product_type_name
+ # idを変更すると得られるキーも名称も変わります
+ p1.product_type_cd = '02'
+ assert_equal '02', p1.product_type_cd
+ assert_equal :dvd, p1.product_type_key
+ assert_equal 'DVD', p1.product_type_name
+ # キーを変更すると得られるidも名称も変わります
+ p1.product_type_key = :book
+ assert_equal '01', p1.product_type_cd
+ assert_equal :book, p1.product_type_key
+ assert_equal '書籍', p1.product_type_name
+ # id、キー、名称以外の任意の属性は、entryの[]メソッドで取得します。
+ p1.product_type_key = :cd
+ assert_equal 0.5, p1.product_type_entry[:discount]
+ end
+
+ # selectable_attrが定義するクラスメソッドの詳細
+ def test_product_type_class_methods
+ # キーからid、名称を取得できます
+ assert_equal '01', Product1.product_type_id_by_key(:book)
+ assert_equal '02', Product1.product_type_id_by_key(:dvd)
+ assert_equal '03', Product1.product_type_id_by_key(:cd)
+ assert_equal '09', Product1.product_type_id_by_key(:other)
+ assert_equal '書籍', Product1.product_type_name_by_key(:book)
+ assert_equal 'DVD', Product1.product_type_name_by_key(:dvd)
+ assert_equal 'CD', Product1.product_type_name_by_key(:cd)
+ assert_equal 'その他', Product1.product_type_name_by_key(:other)
+ # 存在しないキーの場合はnilを返します
+ assert_equal nil, Product1.product_type_id_by_key(nil)
+ assert_equal nil, Product1.product_type_name_by_key(nil)
+ assert_equal nil, Product1.product_type_id_by_key(:unexist)
+ assert_equal nil, Product1.product_type_name_by_key(:unexist)
+
+ # idからキー、名称を取得できます
+ assert_equal :book, Product1.product_type_key_by_id('01')
+ assert_equal :dvd, Product1.product_type_key_by_id('02')
+ assert_equal :cd, Product1.product_type_key_by_id('03')
+ assert_equal :other, Product1.product_type_key_by_id('09')
+ assert_equal '書籍', Product1.product_type_name_by_id('01')
+ assert_equal 'DVD', Product1.product_type_name_by_id('02')
+ assert_equal 'CD', Product1.product_type_name_by_id('03')
+ assert_equal 'その他', Product1.product_type_name_by_id('09')
+ # 存在しないidの場合はnilを返します
+ assert_equal nil, Product1.product_type_key_by_id(nil)
+ assert_equal nil, Product1.product_type_name_by_id(nil)
+ assert_equal nil, Product1.product_type_key_by_id('99')
+ assert_equal nil, Product1.product_type_name_by_id('99')
+
+ # id、キー、名称の配列を取得できます
+ assert_equal ['01', '02', '03', '09'], Product1.product_type_ids
+ assert_equal [:book, :dvd, :cd, :other], Product1.product_type_keys
+ assert_equal ['書籍', 'DVD', 'CD', 'その他'], Product1.product_type_names
+ # 一部のものだけ取得することも可能です。
+ assert_equal ['03', '02'], Product1.product_type_ids(:cd, :dvd)
+ assert_equal [:dvd, :cd], Product1.product_type_keys('02', '03')
+ assert_equal ['DVD', 'CD'], Product1.product_type_names('02', '03')
+ assert_equal ['CD', 'DVD'], Product1.product_type_names(:cd, :dvd)
+
+ # select_tagなどのoption_tagsを作るための配列なんか一発っす
+ assert_equal([['書籍', '01'], ['DVD', '02'], ['CD', '03'], ['その他', '09']],
+ Product1.product_type_options)
+ end
+
+ # selectable_attrのエントリ名をDB上に保持するためのモデル
+ class ItemMaster < ActiveRecord::Base
+ end
+
+ # selectable_attrを使った場合その2
+ # アクセス時に毎回アクセス時にDBから項目名を取得します。
+ class ProductWithDB1 < ActiveRecord::Base
+ set_table_name 'products'
+
+ selectable_attr :product_type_cd do
+ update_by(
+ "select item_cd, name from item_masters where category_name = 'product_type_cd' order by item_no",
+ :when => :everytime)
+ entry '01', :book, '書籍', :discount => 0.8
+ entry '02', :dvd, 'DVD', :discount => 0.2
+ entry '03', :cd, 'CD', :discount => 0.5
+ entry '09', :other, 'その他', :discount => 1
+ end
+
+ def discount_price
+ (product_type_entry[:discount] * price).to_i
+ end
+ end
+
+ def test_update_entry_name
+ # DBに全くデータがなくてもコードで記述してあるエントリは存在します。
+ ItemMaster.delete_all("category_name = 'product_type_cd'")
+ assert_equal 4, ProductWithDB1.product_type_entries.length
+ assert_equal '書籍', ProductWithDB1.product_type_name_by_key(:book)
+ assert_equal 'DVD', ProductWithDB1.product_type_name_by_key(:dvd)
+ assert_equal 'CD', ProductWithDB1.product_type_name_by_key(:cd)
+ assert_equal 'その他', ProductWithDB1.product_type_name_by_key(:other)
+
+ assert_product_discount(ProductWithDB1)
+
+ # DBからエントリの名称を動的に変更できます
+ item_book = ItemMaster.create(:category_name => 'product_type_cd', :item_no => 1, :item_cd => '01', :name => '')
+ assert_equal 4, ProductWithDB1.product_type_entries.length
+ assert_equal '', ProductWithDB1.product_type_name_by_key(:book)
+ assert_equal 'DVD', ProductWithDB1.product_type_name_by_key(:dvd)
+ assert_equal 'CD', ProductWithDB1.product_type_name_by_key(:cd)
+ assert_equal 'その他', ProductWithDB1.product_type_name_by_key(:other)
+ assert_equal [['', '01'], ['DVD', '02'], ['CD', '03'], ['その他', '09']], ProductWithDB1.product_type_options
+
+ # DBからエントリの並び順を動的に変更できます
+ item_book.item_no = 4;
+ item_book.save!
+ item_other = ItemMaster.create(:category_name => 'product_type_cd', :item_no => 1, :item_cd => '09', :name => 'その他')
+ item_dvd = ItemMaster.create(:category_name => 'product_type_cd', :item_no => 2, :item_cd => '02') # nameは指定しなかったらデフォルトが使われます。
+ item_cd = ItemMaster.create(:category_name => 'product_type_cd', :item_no => 3, :item_cd => '03') # nameは指定しなかったらデフォルトが使われます。
+ assert_equal [['その他', '09'], ['DVD', '02'], ['CD', '03'], ['', '01']], ProductWithDB1.product_type_options
+
+ # DBからエントリを動的に追加することも可能です。
+ item_toys = ItemMaster.create(:category_name => 'product_type_cd', :item_no => 5, :item_cd => '04', :name => 'おもちゃ')
+ assert_equal [['その他', '09'], ['DVD', '02'], ['CD', '03'], ['', '01'], ['おもちゃ', '04']], ProductWithDB1.product_type_options
+ assert_equal :entry_04, ProductWithDB1.product_type_key_by_id('04')
+
+ # DBからレコードを削除してもコードで定義したentryは削除されません。
+ # 順番はDBからの取得順で並び替えられたものの後になります
+ item_dvd.destroy
+ assert_equal [['その他', '09'], ['CD', '03'], ['', '01'], ['おもちゃ', '04'], ['DVD', '02']], ProductWithDB1.product_type_options
+
+ # DB上で追加したレコードを削除すると、エントリも削除されます
+ item_toys.destroy
+ assert_equal [['その他', '09'], ['CD', '03'], ['', '01'], ['DVD', '02']], ProductWithDB1.product_type_options
+
+ # 名称を指定していたDBのレコードを削除したら元に戻ります。
+ item_book.destroy
+ assert_equal [['その他', '09'], ['CD', '03'], ['書籍', '01'], ['DVD', '02']], ProductWithDB1.product_type_options
+
+ # エントリに該当するレコードを全部削除したら、元に戻ります。
+ ItemMaster.delete_all("category_name = 'product_type_cd'")
+ assert_equal [['書籍', '01'], ['DVD', '02'], ['CD', '03'], ['その他', '09']], ProductWithDB1.product_type_options
+ assert_product_discount(ProductWithDB1)
+ end
+
+
+
+
+ # Q: product_type_cd の'_cd'はどこにいっちゃったの?
+ # A: デフォルトでは、/(_cd$|_code$|_cds$|_codes$)/ を削除したものをbase_nameとして
+ # 扱い、それに_keyなどを付加してメソッド名を定義します。もしこのルールを変更したい場合、
+ # selectable_attrを使う前に selectable_attr_name_pattern で新たなルールを指定してください。
+ class Product2 < ActiveRecord::Base
+ set_table_name 'products'
+ self.selectable_attr_name_pattern = /^product_|_cd$/
+
+ selectable_attr :product_type_cd do
+ entry '01', :book, '書籍', :discount => 0.8
+ entry '02', :dvd, 'DVD', :discount => 0.2
+ entry '03', :cd, 'CD', :discount => 0.5
+ entry '09', :other, 'その他', :discount => 1
+ end
+
+ def discount_price
+ (type_entry[:discount] * price).to_i
+ end
+ end
+
+ def test_product2
+ assert_product_discount(Product2)
+ # 選択肢を表示するためのデータは以下のように取得できる
+ assert_equal([['書籍', '01'], ['DVD', '02'], ['CD', '03'], ['その他', '09']],
+ Product2.type_options)
+
+ p2 = Product2.new
+ assert_equal nil, p2.product_type_cd
+ assert_equal nil, p2.type_key
+ assert_equal nil, p2.type_name
+ # idを変更すると得られるキーも名称も変わります
+ p2.product_type_cd = '02'
+ assert_equal '02', p2.product_type_cd
+ assert_equal :dvd, p2.type_key
+ assert_equal 'DVD', p2.type_name
+ # キーを変更すると得られるidも名称も変わります
+ p2.type_key = :book
+ assert_equal '01', p2.product_type_cd
+ assert_equal :book, p2.type_key
+ assert_equal '書籍', p2.type_name
+ # id、キー、名称以外の任意の属性は、entryの[]メソッドで取得します。
+ p2.type_key = :cd
+ assert_equal 0.5, p2.type_entry[:discount]
+
+ assert_equal '01', Product2.type_id_by_key(:book)
+ assert_equal '02', Product2.type_id_by_key(:dvd)
+ assert_equal 'CD', Product2.type_name_by_key(:cd)
+ assert_equal 'その他', Product2.type_name_by_key(:other)
+ assert_equal :other, Product2.type_key_by_id('09')
+ assert_equal '書籍', Product2.type_name_by_id('01')
+ assert_equal [:book, :dvd, :cd, :other], Product2.type_keys
+ assert_equal ['書籍', 'DVD', 'CD', 'その他'], Product2.type_names
+ assert_equal [:dvd, :cd], Product2.type_keys('02', '03')
+ assert_equal ['CD', 'DVD'], Product2.type_names(:cd, :dvd)
+ end
+
+
+
+
+ # Q: selectable_attrの呼び出し毎にbase_bname(って言うの?)を指定したいんだけど。
+ # A: base_nameオプションを指定してください。
+ class Product3 < ActiveRecord::Base
+ set_table_name 'products'
+
+ selectable_attr :product_type_cd, :base_name => 'type' do
+ entry '01', :book, '書籍', :discount => 0.8
+ entry '02', :dvd, 'DVD', :discount => 0.2
+ entry '03', :cd, 'CD', :discount => 0.5
+ entry '09', :other, 'その他', :discount => 1
+ end
+
+ def discount_price
+ (type_entry[:discount] * price).to_i
+ end
+ end
+
+ def test_product3
+ assert_product_discount(Product3)
+ # 選択肢を表示するためのデータは以下のように取得できる
+ assert_equal([['書籍', '01'], ['DVD', '02'], ['CD', '03'], ['その他', '09']],
+ Product3.type_options)
+
+ p3 = Product3.new
+ assert_equal nil, p3.product_type_cd
+ assert_equal nil, p3.type_key
+ assert_equal nil, p3.type_name
+ # idを変更すると得られるキーも名称も変わります
+ p3.product_type_cd = '02'
+ assert_equal '02', p3.product_type_cd
+ assert_equal :dvd, p3.type_key
+ assert_equal 'DVD', p3.type_name
+ # キーを変更すると得られるidも名称も変わります
+ p3.type_key = :book
+ assert_equal '01', p3.product_type_cd
+ assert_equal :book, p3.type_key
+ assert_equal '書籍', p3.type_name
+ # id、キー、名称以外の任意の属性は、entryの[]メソッドで取得します。
+ p3.type_key = :cd
+ assert_equal 0.5, p3.type_entry[:discount]
+
+ assert_equal '01', Product3.type_id_by_key(:book)
+ assert_equal '02', Product3.type_id_by_key(:dvd)
+ assert_equal 'CD', Product3.type_name_by_key(:cd)
+ assert_equal 'その他', Product3.type_name_by_key(:other)
+ assert_equal :other, Product3.type_key_by_id('09')
+ assert_equal '書籍', Product3.type_name_by_id('01')
+ assert_equal [:book, :dvd, :cd, :other], Product3.type_keys
+ assert_equal ['書籍', 'DVD', 'CD', 'その他'], Product3.type_names
+ assert_equal [:dvd, :cd], Product3.type_keys('02', '03')
+ assert_equal ['CD', 'DVD'], Product3.type_names(:cd, :dvd)
+ end
+
+end
+
View
30 test/schema.rb
@@ -0,0 +1,30 @@
+ActiveRecord::Schema.define(:version => 1) do
+
+ create_table "products", :force => true do |t|
+ t.string "product_type_cd"
+ t.integer "price"
+ t.string "name"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ end
+
+ create_table "item_masters", :force => true do |t|
+ t.string "category_name", :limit => 20
+ t.integer "item_no"
+ t.string "item_cd", :limit => 2
+ t.string "name", :limit => 20
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ end
+
+ create_table "i18n_item_masters", :force => true do |t|
+ t.string "locale", :limit => 5
+ t.string "category_name", :limit => 20
+ t.integer "item_no"
+ t.string "item_cd", :limit => 2
+ t.string "name", :limit => 20
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ end
+
+end
View
276 test/selectable_attr_i18n_test.rb
@@ -0,0 +1,276 @@
+# -*- coding: utf-8 -*-
+if defined?(I18n)
+ require File.join(File.dirname(__FILE__), 'test_helper')
+
+ class SelectableAttrI18nTest < Test::Unit::TestCase
+
+ def setup
+ I18n.backend = I18n::Backend::Simple.new
+ I18n.backend.store_translations 'en', :selectable_attrs => {:enum1 => {
+ :entry1 => 'entry one',
+ :entry2 => 'entry two',
+ :entry3 => 'entry three'
+ } }
+ I18n.backend.store_translations 'ja', :selectable_attrs => {:enum1 => {
+ :entry1 => 'エントリ壱',
+ :entry2 => 'エントリ弐',
+ :entry3 => 'エントリ参'
+ } }
+ end
+
+ Enum1 = SelectableAttr::Enum.new do
+ i18n_scope(:selectable_attrs, :enum1)
+ entry 1, :entry1, "エントリ1"
+ entry 2, :entry2, "エントリ2"
+ entry 3, :entry3, "エントリ3"
+ end
+
+ def test_enum1_i18n
+ I18n.locale = nil
+ # assert_equal nil, I18n.locale
+ # assert_equal "エントリ1", Enum1.name_by_key(:entry1)
+ # assert_equal "エントリ2", Enum1.name_by_key(:entry2)
+ # assert_equal "エントリ3", Enum1.name_by_key(:entry3)
+ # assert_equal ["エントリ1", "エントリ2", "エントリ3"], Enum1.names
+ assert_equal :en, I18n.locale
+ assert_equal "entry one", Enum1.name_by_key(:entry1)
+ assert_equal "entry two", Enum1.name_by_key(:entry2)
+ assert_equal "entry three", Enum1.name_by_key(:entry3)
+ assert_equal ["entry one", "entry two", "entry three"], Enum1.names
+
+ I18n.locale = 'ja'
+ assert_equal "エントリ壱", Enum1.name_by_key(:entry1)
+ assert_equal "エントリ弐", Enum1.name_by_key(:entry2)
+ assert_equal "エントリ参", Enum1.name_by_key(:entry3)
+ assert_equal ["エントリ壱", "エントリ弐", "エントリ参"], Enum1.names
+
+ I18n.locale = 'en'
+ assert_equal "entry one", Enum1.name_by_key(:entry1)
+ assert_equal "entry two", Enum1.name_by_key(:entry2)
+ assert_equal "entry three", Enum1.name_by_key(:entry3)
+ assert_equal ["entry one", "entry two", "entry three"], Enum1.names
+ end
+
+ class EnumBase
+ include ::SelectableAttr::Base
+ end
+
+ class SelectableAttrMock1 < EnumBase
+ selectable_attr :attr1, :default => 2 do
+ i18n_scope(:selectable_attrs, :enum1)
+ entry 1, :entry1, "エントリ1"
+ entry 2, :entry2, "エントリ2"
+ entry 3, :entry3, "エントリ3"
+ end
+ end
+
+ def test_attr1_i18n
+ I18n.default_locale = 'ja'
+ I18n.locale = nil
+ # assert_equal nil, I18n.locale
+ # assert_equal "エントリ1", SelectableAttrMock1.attr1_name_by_key(:entry1)
+ # assert_equal "エントリ2", SelectableAttrMock1.attr1_name_by_key(:entry2)
+ # assert_equal "エントリ3", SelectableAttrMock1.attr1_name_by_key(:entry3)
+ assert_equal 'ja', I18n.locale
+ assert_equal "エントリ壱", SelectableAttrMock1.attr1_name_by_key(:entry1)
+ assert_equal "エントリ弐", SelectableAttrMock1.attr1_name_by_key(:entry2)
+ assert_equal "エントリ参", SelectableAttrMock1.attr1_name_by_key(:entry3)
+ assert_equal [["エントリ壱",1], ["エントリ弐",2], ["エントリ参",3]], SelectableAttrMock1.attr1_options
+
+ I18n.locale = 'ja'
+ assert_equal "エントリ壱", SelectableAttrMock1.attr1_name_by_key(:entry1)
+ assert_equal "エントリ弐", SelectableAttrMock1.attr1_name_by_key(:entry2)
+ assert_equal "エントリ参", SelectableAttrMock1.attr1_name_by_key(:entry3)
+ assert_equal [["エントリ壱",1], ["エントリ弐",2], ["エントリ参",3]], SelectableAttrMock1.attr1_options
+
+ I18n.locale = 'en'
+ assert_equal "entry one", SelectableAttrMock1.attr1_name_by_key(:entry1)
+ assert_equal "entry two", SelectableAttrMock1.attr1_name_by_key(:entry2)
+ assert_equal "entry three", SelectableAttrMock1.attr1_name_by_key(:entry3)
+ assert_equal [["entry one",1], ["entry two",2], ["entry three",3]], SelectableAttrMock1.attr1_options
+ end
+
+ class SelectableAttrMock2 < EnumBase
+ selectable_attr :enum1, :default => 2 do
+ i18n_scope(:selectable_attrs, :enum1)
+ entry 1, :entry1, "エントリ1"
+ entry 2, :entry2, "エントリ2"
+ entry 3, :entry3, "エントリ3"
+ end
+ end
+
+ def test_enum1_i18n
+ I18n.default_locale = 'ja'
+ I18n.locale = nil
+ # assert_equal nil, I18n.locale
+ # assert_equal "エントリ1", SelectableAttrMock2.enum1_name_by_key(:entry1)
+ # assert_equal "エントリ2", SelectableAttrMock2.enum1_name_by_key(:entry2)
+ # assert_equal "エントリ3", SelectableAttrMock2.enum1_name_by_key(:entry3)
+ assert_equal 'ja', I18n.locale
+ assert_equal "エントリ壱", SelectableAttrMock2.enum1_name_by_key(:entry1)
+ assert_equal "エントリ弐", SelectableAttrMock2.enum1_name_by_key(:entry2)
+ assert_equal "エントリ参", SelectableAttrMock2.enum1_name_by_key(:entry3)
+ assert_equal [["エントリ壱",1], ["エントリ弐",2], ["エントリ参",3]], SelectableAttrMock2.enum1_options
+
+ I18n.locale = 'ja'
+ assert_equal "エントリ壱", SelectableAttrMock2.enum1_name_by_key(:entry1)
+ assert_equal "エントリ弐", SelectableAttrMock2.enum1_name_by_key(:entry2)
+ assert_equal "エントリ参", SelectableAttrMock2.enum1_name_by_key(:entry3)
+ assert_equal [["エントリ壱",1], ["エントリ弐",2], ["エントリ参",3]], SelectableAttrMock2.enum1_options
+
+ I18n.locale = 'en'
+ assert_equal "entry one", SelectableAttrMock2.enum1_name_by_key(:entry1)
+ assert_equal "entry two", SelectableAttrMock2.enum1_name_by_key(:entry2)
+ assert_equal "entry three", SelectableAttrMock2.enum1_name_by_key(:entry3)
+ assert_equal [["entry one",1], ["entry two",2], ["entry three",3]], SelectableAttrMock2.enum1_options
+ end
+
+ # i18n用のlocaleカラムを持つselectable_attrのエントリ名をDB上に保持するためのモデル
+ class I18nItemMaster < ActiveRecord::Base
+ end
+
+ # selectable_attrを使った場合その3
+ # アクセス時に毎回アクセス時にDBから項目名を取得します。
+ # 対象となる項目名はi18n対応している名称です
+ class ProductWithI18nDB1 < ActiveRecord::Base
+ set_table_name 'products'
+ selectable_attr :product_type_cd do
+ # update_byメソッドには、エントリのidと名称を返すSELECT文を指定する代わりに、
+ # エントリのidと名称の配列の配列を返すブロックを指定することも可能です。
+ update_by(:when => :everytime) do
+ records = I18nItemMaster.find(:all,
+ :conditions => [
+ "category_name = 'product_type_cd' and locale = ? ", I18n.locale.to_s],
+ :order => "item_no")
+ records.map{|r| [r.item_cd, r.name]}
+ end
+ entry '01', :book, '書籍', :discount => 0.8
+ entry '02', :dvd, 'DVD', :discount => 0.2
+ entry '03', :cd, 'CD', :discount => 0.5
+ entry '09', :other, 'その他', :discount => 1
+ end
+
+ end
+
+ def test_update_entry_name_with_i18n
+ I18n.locale = 'ja'
+ # DBに全くデータがなくてもコードで記述してあるエントリは存在します。
+ I18nItemMaster.delete_all("category_name = 'product_type_cd'")
+ assert_equal 4, ProductWithI18nDB1.product_type_entries.length
+ assert_equal '書籍', ProductWithI18nDB1.product_type_name_by_key(:book)
+ assert_equal 'DVD', ProductWithI18nDB1.product_type_name_by_key(:dvd)
+ assert_equal 'CD', ProductWithI18nDB1.product_type_name_by_key(:cd)
+ assert_equal 'その他', ProductWithI18nDB1.product_type_name_by_key(:other)
+
+ # assert_product_discount(ProductWithI18nDB1)
+
+ # DBからエントリの名称を動的に変更できます
+ item_book = I18nItemMaster.create(:locale => 'ja', :category_name => 'product_type_cd', :item_no => 1, :item_cd => '01', :name => '')
+ assert_equal 4, ProductWithI18nDB1.product_type_entries.length
+ assert_equal '', ProductWithI18nDB1.product_type_name_by_key(:book)
+ assert_equal 'DVD', ProductWithI18nDB1.product_type_name_by_key(:dvd)
+ assert_equal 'CD', ProductWithI18nDB1.product_type_name_by_key(:cd)
+ assert_equal 'その他', ProductWithI18nDB1.product_type_name_by_key(:other)
+ assert_equal [['', '01'], ['DVD', '02'], ['CD', '03'], ['その他', '09']], ProductWithI18nDB1.product_type_options
+
+ # DBからエントリの並び順を動的に変更できます
+ item_book.item_no = 4;
+ item_book.save!
+ item_other = I18nItemMaster.create(:locale => 'ja', :category_name => 'product_type_cd', :item_no => 1, :item_cd => '09', :name => 'その他')
+ item_dvd = I18nItemMaster.create(:locale => 'ja', :category_name => 'product_type_cd', :item_no => 2, :item_cd => '02') # nameは指定しなかったらデフォルトが使われます。
+ item_cd = I18nItemMaster.create(:locale => 'ja', :category_name => 'product_type_cd', :item_no => 3, :item_cd => '03') # nameは指定しなかったらデフォルトが使われます。
+ assert_equal [['その他', '09'], ['DVD', '02'], ['CD', '03'], ['', '01']], ProductWithI18nDB1.product_type_options
+
+ # DBからエントリを動的に追加することも可能です。
+ item_toys = I18nItemMaster.create(:locale => 'ja', :category_name => 'product_type_cd', :item_no => 5, :item_cd => '04', :name => 'おもちゃ')
+ assert_equal [['その他', '09'], ['DVD', '02'], ['CD', '03'], ['', '01'], ['おもちゃ', '04']], ProductWithI18nDB1.product_type_options
+ assert_equal :entry_04, ProductWithI18nDB1.product_type_key_by_id('04')
+
+ # 英語名を登録
+ item_book = I18nItemMaster.create(:locale => 'en', :category_name => 'product_type_cd', :item_no => 4, :item_cd => '01', :name => 'Book')
+ item_other = I18nItemMaster.create(:locale => 'en', :category_name => 'product_type_cd', :item_no => 1, :item_cd => '09', :name => 'Others')
+ item_dvd = I18nItemMaster.create(:locale => 'en', :category_name => 'product_type_cd', :item_no => 2, :item_cd => '02', :name => 'DVD')
+ item_cd = I18nItemMaster.create(:locale => 'en', :category_name => 'product_type_cd', :item_no => 3, :item_cd => '03', :name => 'CD')
+ item_toys = I18nItemMaster.create(:locale => 'en', :category_name => 'product_type_cd', :item_no => 5, :item_cd => '04', :name => 'Toy')
+
+ # 英語名が登録されていてもI18n.localeが変わらなければ、日本語のまま
+ assert_equal [['その他', '09'], ['DVD', '02'], ['CD', '03'], ['', '01'], ['おもちゃ', '04']], ProductWithI18nDB1.product_type_options
+ assert_equal :entry_04, ProductWithI18nDB1.product_type_key_by_id('04')
+
+ # I18n.localeを変更すると取得できるエントリの名称も変わります
+ I18n.locale = 'en'
+ assert_equal [['Others', '09'], ['DVD', '02'], ['CD', '03'], ['Book', '01'], ['Toy', '04']], ProductWithI18nDB1.product_type_options
+ assert_equal :entry_04, ProductWithI18nDB1.product_type_key_by_id('04')
+
+ I18n.locale = 'ja'
+ assert_equal [['その他', '09'], ['DVD', '02'], ['CD', '03'], ['', '01'], ['おもちゃ', '04']], ProductWithI18nDB1.product_type_options
+ assert_equal :entry_04, ProductWithI18nDB1.product_type_key_by_id('04')
+
+ I18n.locale = 'en'
+ assert_equal [['Others', '09'], ['DVD', '02'], ['CD', '03'], ['Book', '01'], ['Toy', '04']], ProductWithI18nDB1.product_type_options
+ assert_equal :entry_04, ProductWithI18nDB1.product_type_key_by_id('04')
+
+ # DBからレコードを削除してもコードで定義したentryは削除されません。
+ # 順番はDBからの取得順で並び替えられたものの後になります
+ item_dvd.destroy
+ assert_equal [['Others', '09'], ['CD', '03'], ['Book', '01'], ['Toy', '04'], ['DVD', '02']], ProductWithI18nDB1.product_type_options
+
+ # DB上で追加したレコードを削除すると、エントリも削除されます
+ item_toys.destroy
+ assert_equal [['Others', '09'], ['CD', '03'], ['Book', '01'], ['DVD', '02']], ProductWithI18nDB1.product_type_options
+
+ # 名称を指定していたDBのレコードを削除したら元に戻ります。
+ item_book.destroy
+ assert_equal [['Others', '09'], ['CD', '03'], ['書籍', '01'], ['DVD', '02']], ProductWithI18nDB1.product_type_options
+
+ # エントリに該当するレコードを全部削除したら、元に戻ります。
+ I18nItemMaster.delete_all("category_name = 'product_type_cd'")
+ assert_equal [['書籍', '01'], ['DVD', '02'], ['CD', '03'], ['その他', '09']], ProductWithI18nDB1.product_type_options
+ end
+
+ def test_i18n_export
+ I18nItemMaster.delete_all("category_name = 'product_type_cd'")
+
+ I18n.locale = 'ja'
+ actual = SelectableAttr::Enum.i18n_export
+ assert_equal [:selectable_attrs], actual.keys
+ assert_equal true, actual[:selectable_attrs].keys.include?(:enum1)
+ assert_equal(
+ {:entry1=>"エントリ壱",
+ :entry2=>"エントリ弐",
+ :entry3=>"エントリ参"},
+ actual[:selectable_attrs][:enum1])
+
+ assert_equal true, actual[:selectable_attrs].keys.include?(:SelectableAttrI18nTest)
+ assert_equal(
+ {:ProductWithI18nDB1=>
+ {:product_type_cd=>
+ {:book=>"書籍", :dvd=>"DVD", :cd=>"CD", :other=>"その他"}}},
+ actual[:selectable_attrs][:SelectableAttrI18nTest])
+
+
+ I18nItemMaster.create(:locale => 'en', :category_name => 'product_type_cd', :item_no => 1, :item_cd => '09', :name => 'Others')
+ I18nItemMaster.create(:locale => 'en', :category_name => 'product_type_cd', :item_no => 2, :item_cd => '02', :name => 'DVD')
+ I18nItemMaster.create(:locale => 'en', :category_name => 'product_type_cd', :item_no => 3, :item_cd => '03', :name => 'CD')
+ I18nItemMaster.create(:locale => 'en', :category_name => 'product_type_cd', :item_no => 4, :item_cd => '01', :name => 'Book')
+ I18nItemMaster.create(:locale => 'en', :category_name => 'product_type_cd', :item_no => 5, :item_cd => '04', :name => 'Toy')
+
+ I18n.locale = 'en'
+ actual = SelectableAttr::Enum.i18n_export
+ assert_equal [:selectable_attrs], actual.keys
+ assert_equal true, actual[:selectable_attrs].keys.include?(:enum1)
+ assert_equal(
+ {:entry1=>"entry one",
+ :entry2=>"entry two",
+ :entry3=>"entry three"},
+ actual[:selectable_attrs][:enum1])
+ assert_equal true, actual[:selectable_attrs].keys.include?(:SelectableAttrI18nTest)
+ assert_equal(
+ {:ProductWithI18nDB1=>
+ {:product_type_cd=>
+ {:book=>"Book", :dvd=>"DVD", :cd=>"CD", :other=>"Others", :entry_04=>"Toy"}}},
+ actual[:selectable_attrs][:SelectableAttrI18nTest])
+
+ end
+ end
+end
View
2  test/test_all.rb
@@ -0,0 +1,2 @@
+require File.join(File.dirname(__FILE__), 'test_helper')
+Test::Unit::AutoRunner.run(true, File.dirname(__FILE__), ['--pattern=/.*?_test\.rb\Z/'])
View
32 test/test_helper.rb
@@ -0,0 +1,32 @@
+$KCODE='u'
+require 'test/unit'
+
+FIXTURES_ROOT = File.join(File.dirname(__FILE__), 'fixtures') unless defined?(FIXTURES_ROOT)
+
+require 'rubygems'
+require 'active_support'
+require 'active_record'
+require 'active_record/fixtures'
+require 'active_record/test_case'
+require 'action_view'
+
+$LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
+require File.join(File.dirname(__FILE__), '..', 'init')
+
+require 'yaml'
+config = YAML.load(IO.read(File.join(File.dirname(__FILE__), 'database.yml')))
+ActiveRecord::Base.logger = Logger.new(File.join(File.dirname(__FILE__), 'debug.log'))
+ActiveRecord::Base.establish_connection(config[ENV['DB'] || 'sqlite3'])
+
+load(File.join(File.dirname(__FILE__), 'schema.rb'))
+
+
+class Test::Unit::TestCase
+
+ def assert_hash(expected, actual)
+ keys = (expected.keys + actual.keys).uniq
+ keys.each do |key|
+ assert_equal expected[key], actual[key], "unmatch value for #{key.inspect}"
+ end
+ end
+end
View
1  uninstall.rb
@@ -0,0 +1 @@
+# Uninstall hook code here
Please sign in to comment.
Something went wrong with that request. Please try again.