Как заново установить параметры CRUD has_many_polymorphs - PullRequest
0 голосов
/ 15 июня 2009

Работа над простым примером двусторонних полиморфных отношений с использованием плагина 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'

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

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

И наконец мои маршруты. 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

Ответы [ 2 ]

0 голосов
/ 16 июня 2009

Полиморфные отношения должны делать большую часть того, что вам нужно, хотя, если ваши кошки и собаки дружат со свиньями, и вы хотите знать, кто инициировал дружбу, мое предыдущее решение слишком упрощенное.

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 голосов
/ 15 июня 2009

Я бы, наверное, выбрал модель 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, чтобы найти «друзей».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...