轨,委托方法的关联。与AR可能的错误? [英] Rails association with delegate methods. possible bug with AR?

查看:153
本文介绍了轨,委托方法的关联。与AR可能的错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

隔离<一href="http://stackoverflow.com/questions/12011941/rails-nested-delegate-attributes-not-being-updated">this问题到它自己的Rails应用程序:并增加了一个混帐回购协议作为一个例子

Isolated this question into it's own rails app: and added a git repo as an example

模块:

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的测试:

Rspec Tests:

 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

前四个测试通过的第二个四失败。我想可能是有轨多态关联的错误,但我不知道如何进一步孤立它。在我的模块设计评论也AP preciated。

The first four tests pass and the second four fail. I think it might be a bug with rails polymorphic associations but I'm not sure how to isolate it further. Comments on my module design are also appreciated.

最好的, 斯科特

推荐答案

在你的code的问题是在这个地方:

The problem in your code is in this place:

class User
  #Other stuff

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

您拨打每次集合方法,你看看第一个集合在数据库中。即使你用 user.collection.meta_description =ABC然后当你调用后设置一些值因此 user.collection 这不是原因,而是同一个集合对象已经从数据库中新的查找。因此,所有未保存到数据库中的属性都没有了。您可以通过查看日志,看到这一点 - 每次调用 user.collection 你得到新的命中DB和时间也每次调用时间 user.collection .object_id 你会得到不同的值。

Every time you call collection method you look up the first collection in the database. Therefore even if you set some values by user.collection.meta_description = "abc" then later when you call user.collection it's not the same collection object cause it's been new lookup from the database. Therefore all the attributes not saved to the database are gone. You can see this by looking at logs - every time you call user.collection you get new hit to db and also every time you call user.collection.object_id you get a different value.

您可以做这样的事情修复

You can fix it by doing something like

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

这篇关于轨,委托方法的关联。与AR可能的错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆