2012-02-19 1 views
0

モデルの小文字の条件モデルCountryにはcodeという属性があり、before_saveコールバックによって自動的に小文字に変換されます。 ActiveRecord :: Baseの大きなチャンクを書き直すことなく、この動作を "マジック"メソッドに強制することは可能ですか?モデル

class Country < ActiveRecord::Base 
    attr_accessible :code 
    validates :code, :presence => true 
    validates_uniqueness_of :code, :case_sensitive => false 

    before_save do |country| 
    country.code.downcase! unless country.code.nil? 
    end 
end 

RSpecの

describe Country do 
    describe 'data normalization' 
    before :each do 
     @country = FactoryGirl.create(:country, :code => 'DE') 
    end 

    # passes 
    it 'should normalize the code to lowercase on insert' do 
     @country.code.should eq 'de' 
    end 

    # fails 
    it 'should be agnostic to uppercase finds' do 
     country = Country.find_by_code('DE') 
     country.should_not be_nil 
    end 

    # fails 
    it 'should be agnostic to uppercase finds_or_creates' do 
     country = Country.find_or_create_by_code('DE') 
     country.id.should_not be_nil # ActiveRecord Bug? 
    end 
end 

答えて

0

(質問で述べたように)私は本当にそのアプローチを嫌いaltoughこれは、私が思いついたものです。簡単な選択肢は、大文字小文字を無視するように列、テーブルまたはデータベース全体を設定することです(ただしこれはdb依存です)。

class Country < ActiveRecord::Base 
    attr_accessible :code 
    validates :code, :presence => true 
    validates_uniqueness_of :code, :case_sensitive => false 

    before_save do |country| 
    country.code.downcase! unless country.code.nil? 
    end 

    class ActiveRecord::Base 
    def self.method_missing_with_code_finders(method_id, *arguments, &block) 
     if match = (ActiveRecord::DynamicFinderMatch.match(method_id) || ActiveRecord::DynamicScopeMatch.match(method_id)) 
     attribute_names = match.attribute_names 
     if code_index = attribute_names.find_index('code') 
      arguments[code_index].downcase! 
     end 
     end 
     method_missing_without_code_finders(method_id, *arguments, &block) 
    end 

    class << self 
     alias_method_chain(:method_missing, :code_finders) 
    end 
    end 
end