2009-06-14 62 views
0

使用has_ many_多形態ActiveRecord插件處理雙面多態關係的簡單示例。我有兩個班級,「貓」和「狗」,可以有彼此的「友誼」,所以共有三類:「貓」,「狗」和「友誼」。一隻貓可以成爲狗的朋友(是的,它確實發生了!),當然還有其他貓。狗也是一樣。這裏是我的模型:如何設置has_many_polymorphs CRUD參數安然

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的路由以及來自POST參數的right_type和right_id的關係。路由觸發正確的friendships_控制器#創建方法和所產生的PARAMS是這樣的:

Parameters: { 
    "authenticity_token"=>"gG1eh2dXTuRPfPJ5eNapeDqJu7UJ5mFC/M5gJK23MB4=", 
    "left_type"=>"cats", 
    "right_type"=>"dogs", 
    "left_id"=>"3", 
    "right_id"=>"1" 
} 

對於此問題,我想「左派」和「權利」之間分隔的範圍之外的原因這樣我可以跟蹤友誼被髮布給誰(因此是「左派」和「權利」),但也許我的模型不是實現這一目標的正確方法?我誤解了has_ many_多媒體插件的用途嗎?下面是從friendships_控制器#創建行動:

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

多態關係應該做你需要的大部分,但如果你的貓和狗是豬的朋友,你想知道誰發起了友誼我以前的解決方案太簡單了。

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 

我不確定這是你要找的,但我認爲這是一個更簡單的方法,簡單總是更好。

0

我可能會選擇一個貓與狗模型,然後使用一個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找到任何「友誼」。

+0

謝謝詹姆斯,這聽起來像一個更簡單的解決方案!但是當我有兩個以上的基類時,它會不會變得有點笨拙?對於另外兩個人來說,我要添加第三堂課,比如Pigs呢?此外,這種模式不會讓我看到哪一方是這種關係的發起者(上面我的例子中的「左派」),還是我誤解了某些東西? – 2009-06-15 17:47:55