2009-06-14 2 views
0

Работа над простым примером двухсторонних полиморфных отношений с использованием плагина Active_Readord has_ ​​many_ polymorphs. У меня есть два класса: «кошки» и «собаки», которые могут иметь «дружеские отношения» друг с другом, поэтому три класса во всех: «кошки», «собаки» и «дружба». Кошка может дружить с собакой (да, это происходит!) И, конечно же, с другими кошками. То же самое касается собак. Вот мои модели:Как настроить параметры CRUD has_many_polymorphs

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/отношений с маршрутом, который получает left_ type и left_ id из URL-адреса, а правый тип и правый_ идентификатор из параметров POST. Маршрутизации запускает метод #create из friendships_ контроллера правильно и результирующие PARAMS выглядеть следующим образом:

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

По причинам, которые выходят за рамки этого вопроса я хочу разделить между «левыми» и «права» в таким образом, что я могу следить за тем, к кому была ПОЛЬЗОВАНА дружба (отсюда «левые» и «права»), но, возможно, моя модель не является правильным способом для этого? Я неправильно понял цель плагина has_ ​​many_ polymorphs? Здесь действие #create от 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, поэтому я буду упорствовать, но некоторые из этих headscratchers настолько плохи, что я начинаю получать лысину. Я знаю, что там много опытных разработчиков 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

Спасибо, Джеймс, это звучит намного проще! Но не станет ли он становиться немного неуклюжим, если у меня будет более двух базовых классов? Что я должен был добавить третьего класса, скажем, свиней, к двум другим? Кроме того, эта модель не позволит мне увидеть, какая сторона была инициатором отношений («левые» в моем примере выше), или я что-то не понимаю? –

Смежные вопросы