轨,委托方法的关联。与AR可能的错误? [英] Rails association with delegate methods. possible bug with 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屋!