模型

2012-02-19 42 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 dependendt)。

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