使用has_ many_ polymorphs ActiveRecord插件处理双面多态关系的简单示例。我有两个班,“猫”和“狗”,可以互相“友谊”,所以共有三个类:“猫”,“狗”和“友谊”。猫可以和狗一起成为朋友(是的,确实发生了!)当然还有其他猫。狗也一样。这是我的模特:
class Cat < ActiveRecord::Base
validates_presence_of :name
end
class Dog < ActiveRecord::Base
validates_presence_of :name
end
class Friendship < ActiveRecord::Base
belongs_to :left, :polymorphic => true
belongs_to :right, :polymorphic => true
acts_as_double_polymorphic_join(
:lefts => [:cats, :dogs],
:rights => [:dogs, :cats]
)
end
我一直在努力让这个工作起来,我必须错过一些明显的东西。当我尝试创造一种新的友谊时,我得到了:
NameError (wrong constant name cats):
(eval):7:in `before_save'
app/controllers/friendships_controller.rb:45:in `create'
或
NameError (wrong constant name dogs):
(eval):7:in `before_save'
app/controllers/friendships_controller.rb:45:in `create'
这是我的schema.rb:
ActiveRecord::Schema.define(:version => 20090613051350) do
create_table "cats", :force => true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "dogs", :force => true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "friendships", :force => true do |t|
t.integer "left_id"
t.string "left_type"
t.integer "right_id"
t.string "right_type"
t.datetime "created_at"
t.datetime "updated_at"
end
end
我正在尝试通过POST来创建一个新的“友谊”,例如,/ cats / 3 /关系路由从URL获取left_ type和left_ id以及从中获取right_ type和right_ id POST参数。路由正确触发friendships_ controller的#create方法,结果参数如下所示:
Parameters: {
"authenticity_token"=>"gG1eh2dXTuRPfPJ5eNapeDqJu7UJ5mFC/M5gJK23MB4=",
"left_type"=>"cats",
"right_type"=>"dogs",
"left_id"=>"3",
"right_id"=>"1"
}
由于超出这个问题范围的原因,我希望将“左派”和“权利”分开,以便我可以跟踪友谊被张贴的对象(因此“左派”和“权利” “),但也许我的模型不是完成这个的正确方法?我是否误解了has_ many_ polymorphs插件的用途?这是来自friendships_ controller的#create动作:
def create
@friendship= Friendship.new(
:left_type => params[:left_type],
:left_id => params[:left_id],
:right_type => params[:right_type],
:right_id => params[:right_id]
)
respond_to do |format|
if @friendship.save
format.xml {
render :xml => @friendship,
:status => :created,
:location => @friendship
}
else
format.xml {
render :xml => @friendship.errors,
:status => :unprocessable_entity
}
end
end
end
最后我的routes.rb:
map.resources :friendships
map.resources :cats do |cat|
cat.resources :friendships, :path_prefix => "/:left_type/:left_id"
end
map.resources :dogs do |dog|
dog.resources :friendships, :path_prefix => "/:left_type/:left_id"
end
就像我说的那样,我花了很长时间独自尝试解决这个问题,但存在的文档要么过时,要么过于笼统,要么过于高级 - 或者在某些情况下,这三个文件同时存在。我可以告诉你,开始使用这个RoR并不容易!我知道RoR熟练程度有一些真正的好处,所以我会坚持下去,但是这些头脑中的一些人非常糟糕,我开始得到一个光头补丁。我知道有很多经验丰富的Ruby / Rails开发人员,我希望有人可以从木工中走出来,并在这里解释这件事对我们来说只是凡人。
提前致谢,
JS
答案 0 :(得分:0)
我可能会选择Cat and Dog模型,然后使用has_and_belongs_to_many关联?
class Cat < ActiveRecord::Base
has_and_belongs_to_many :dogs
end
class Dog < ActiveRecord::Base
has_and_belongs_to_many :cats
end
然后连接表看起来像这样......
create_table "cats_dogs", :id => false, :force => true do |t|
t.integer "cat_id"
t.integer "dog_id"
t.datetime "created_at"
t.datetime "updated_at"
end
你可以打电话给cat.dogs和dog.cats找到任何'友谊'。
答案 1 :(得分:0)
多态关系应该能够满足您的需要,尽管如果您的猫和狗是猪的朋友,并且您想知道是谁发起了这种友谊,我以前的解决方案太简单了。
class Animal < ActiveRecord::Base
belongs_to :creatures, :polymorphic => true
named_scope :cats, :conditions => {:creature_type => 'Cat'}
named_scope :dogs, :conditions => {:creature_type => 'Dog'}
named_scope :pigs, :conditions => {:creature_type => 'Pig'}
end
class Cat < ActiveRecord::Base
has_many :friends, :as => :creatures
end
class Dog < ActiveRecord::Base
has_many :friends, :as => :creatures
end
class Pig < ActiveRecord::Base
has_many :friends, :as => :creatures
end
这可能不是你想要的,但它可以让你打电话给cat.friends和cat.friends.dogs,cat.friends.pigs等。
您可以添加has_many
个关联,以便直接调用cat.dogs和cat.pigs。
class Cat < ActiveRecord::Base
has_many :friends, :as => :creatures
has_many :dogs, :through => :animal
has_many :pigs, :through => :animal
end
我不确定这是不是你想要的,但我认为这是一种更简单的方法,简单总是更好。