2012-08-23 22 views
1

隔離this question到它自己的滑軌應用程序:和添加git repo作爲例子Rails與委託方法的關聯。 AR可能的錯誤?

模塊:

module SeoMeta 

    def self.included(base) 
    base.extend(ClassMethods) 
    base.send :include, InstanceMethods 
    end 

    module ClassMethods 

    def is_seo_meta 

     has_one :meta, 
     class_name: SeoMetum, 
     as:   :metumable, 
     dependent: :destroy, 
     autosave: true 

     delegate :browser_title,  :meta_description, :meta_author, 
       :meta_keywords,  :browser_title=, :meta_keywords=, 
       :meta_description=, :meta_author=, 
       to: :meta 

     after_save :save_meta_tags! 

     attr_accessible :browser_title, :meta_keywords, 
         :meta_description, :meta_author 

    end 

    end 

    module InstanceMethods 

    class << self 
     def included(base) 
     base.module_eval do 

      alias :original_meta_method :meta 

     end 
     end 
    end 

    def meta 
     find_meta || build_meta 
    end 

    def find_meta 
     @meta ||= ::SeoMetum.where(metumable_type: self.class.name, metumable_id: self.id).first 
    end 

    def build_meta 
     @meta ||= ::SeoMetum.new(metumable_type: self.class.name, metumable_id: self.id) 
    end 

    def save_meta_tags! 
     meta.metumable_id ||= self.id 
     meta.save 
    end 

    end 
end 

型號:

class User < ActiveRecord::Base 
    include SeoMeta 
    is_seo_meta 

    has_many :collections 
    accepts_nested_attributes_for :collections 

    def collection 
    default_collection = self.collections.first 
    default_collection ||= self.collections.create 
    default_collection 
    end 
end 

class Collection < ActiveRecord::Base 
    include SeoMeta 
    is_seo_meta 
    belongs_to :user 

end 

class SeoMetum < ActiveRecord::Base 
    attr_accessible :browser_title, :meta_author, :meta_description, :meta_keywords, 
        :metumable, :metumable_id, :metumable_type 
    belongs_to :metumable, polymorphic: true 
end 

Rspec的測試:

context "user and collection" do 
    context 'responds to' do 
     it 'meta_description' do 
     user.collection.respond_to?(:meta_description).should be_true 
     end 

     it 'browser_title' do 
     user.collection.respond_to?(:browser_title).should be_true 
     end 
    end 

    context 'individual allows us to assign to' do 
     it 'meta_description' do 
     the_collection = user.collection 
     the_collection.meta_description = 'This is my description of the user for search results.' 
     the_collection.meta_description.should == 'This is my description of the user for search results.' 
     end 

     it 'browser_title' do 
     the_collection = user.collection 
     the_collection.browser_title = 'An awesome browser title for SEO' 
     the_collection.browser_title.should == 'An awesome browser title for SEO' 
     end 
    end 


    context 'allows us to assign to' do 
     it 'meta_description' do 
     user.collection.meta_description = 'This is my description of the user for search results.' 
     user.collection.meta_description.should == 'This is my description of the user for search results.' 
     end 

     it 'browser_title' do 
     user.collection.browser_title = 'An awesome browser title for SEO' 
     user.collection.browser_title.should == 'An awesome browser title for SEO' 
     end 
    end 

    context 'allows us to update' do 
     it 'meta_description' do 
     user.collection.meta_description = 'This is my description of the user for search results.' 
     user.collection.save 

     user.collection.reload 
     user.collection.meta_description.should == 'This is my description of the user for search results.' 
     end 

     it 'browser_title' do 
     user.collection.browser_title = 'An awesome browser title for SEO' 
     user.collection.save 

     user.collection.reload 
     user.collection.browser_title.should == 'An awesome browser title for SEO' 
     end 
    end 
    end 

的前四個測試通過和本cond四失敗。我認爲這可能是一個軌道多態關聯的錯誤,但我不知道如何進一步隔離它。我的模塊設計的意見也讚賞。

最佳, 斯科特

回答

2

在你的代碼的問題是在這個地方:

class User 
    #Other stuff 

    #HERE! 
    def collection 
    default_collection = self.collections.first 
    default_collection ||= self.collections.create 
    default_collection 
    end 
end 

每次調用collection方法,你在數據庫中查找第一個集合。因此,即使您將某些值設置爲user.collection.meta_description = "abc",稍後您在調用user.collection時,它也不是同一個集合對象,因爲它是從數據庫中進行新查找的。因此所有未保存到數據庫的屬性都消失了。你可以通過查看日誌來看到這一點 - 每當你打電話給user.collection時,你會得到新的打擊數據庫,並且每次你打電話給user.collection.object_id時,你都會得到不同的價值。

你可以做這樣的事情

def collection 
    return @collection if @collection 
    default_collection = self.collections.first 
    default_collection ||= self.collections.create 
    @collection = default_collection 
end 
+0

你說得很對解決它。測試通過。謝謝!一直讓我瘋狂 – ScotterC