我遇到以下模型的一个小问题(在Rails 3.2rc1上)。所有权将项目和博客映射到用户(所有者),并且存在以不同方式处理所有权的不同类型的博客。
class User < ActiveRecord::Base
has_many :ownerships, dependent: :destroy
has_many :projects, through: :ownerships, source: :ownable, :source_type => 'Project'
has_many :site_blogs, through: :ownerships, source: :ownable, :source_type => 'SiteBlog'
end
class Ownership < ActiveRecord::Base
belongs_to :ownable, polymorphic: true
belongs_to :owner, :class_name => 'User', foreign_key: 'user_id'
end
class Project < ActiveRecord::Base
has_many :owners, through: :ownerships, as: :ownable
has_many :ownerships, as: :ownable, dependent: :destroy
end
class Blog < ActiveRecord::Base
end
class SiteBlog < Blog
has_many :owners, through: :ownerships, as: :ownable
has_many :ownerships, as: :ownable, dependent: :destroy
end
class ProjectBlog < Blog
belongs_to :project
end
到目前为止一切正常,但SiteBlog#owners
行为不端:
SiteBlog.first.owners
SiteBlog Load (0.8ms) SELECT "blogs".* FROM "blogs" WHERE "blogs"."type" IN ('SiteBlog') LIMIT 1
User Load (1.4ms) SELECT "users".* FROM "users" INNER JOIN "ownerships" ON "users"."id" = "ownerships"."user_id" WHERE "ownerships"."ownable_id" = 231145885 AND "ownerships"."ownable_type" = 'Blog'
=> []
问题是生成的SELECT的结尾:"ownable_type" = 'Blog'
。要使其工作,它应该是"ownable_type" = 'SiteBlog'
,但是,我不知道如何教AREL这样做。
有什么想法吗?
答案 0 :(得分:0)
我根据你的例子创建了一个小型rails应用程序。它工作正常。
User.create
SiteBlog.create
SiteBlog.first.owners << User.first
这会创建所有权记录
#<Ownership id: 5, ownable_id: 5, ownable_type: "Blog", user_id: 5, created_at: 2012-01-17 20:14:01", updated_at: "2012-01-17 20:14:01">
如您所见,ownable_type是“博客”,而不是“SiteBlog”。然后:
SiteBlog.first.owners
SiteBlog Load (0.3ms) SELECT "blogs".* FROM "blogs" WHERE "blogs"."type" IN ('SiteBlog') LIMIT 1
User Load (0.3ms) SELECT "users".* FROM "users" INNER JOIN "ownerships" ON "users"."id" = "ownerships"."user_id" WHERE "ownerships"."ownable_id" = 5 AND "ownerships"."ownable_type" = 'Blog'
=> [#<User id: 5, created_at: "2012-01-17 19:44:45", updated_at: "2012-01-17 19:44:45">]
所以 - 查询正在运行。
这是主要部分。查看activerecord / lib / activerecord / associations / association.rb:
def creation_attributes
attributes = {}
if reflection.macro.in?([:has_one, :has_many]) && !options[:through]
attributes[reflection.foreign_key] = owner[reflection.active_record_primary_key]
if reflection.options[:as]
attributes[reflection.type] = owner.class.base_class.name
end
end
attributes
end
具体来说,这一行告诉Rails应该写基类名称 - 即Blog,而不是SiteBlog:
attributes[reflection.type] = owner.class.base_class.name
所以 - 你的例子和Rails行为似乎都很好。