Ruby on Rails - has_many на основе "вида" - PullRequest
2 голосов
/ 04 декабря 2010

Я новичок в Ruby on Rails, поэтому я не так много знаю об ассоциации моделей. Но вот моя проблема:

У меня есть ресурс проекта, который имеет has_many: items. У каждого элемента есть имя и вид (тип определяет тип элемента). Я хочу создавать различные ассоциации на основе "доброго" значения ... как это:

class Item < ActiveRecord::Base
  belongs_to :project, :dependent => :destroy

  has_many :sports, :class_name => 'NormalSport' # if kind = 'normal_sport'
  has_many :sports, :class_name => 'SuperSport' # if kind = 'super_sport'
  has_many :sheep # if kind = 'sheep'
  has_many :drinks # if kind = 'drink'
end

Таким образом, это означает, что предмет может быть "normal_sport", "super_sport", "sheep" или "drink". Поэтому, если предмет представляет собой normal_sport, я бы хотел сказать (что-то вроде):

Project.first.items.first.sports.all

А затем «спорт» переходит в класс «NormalSport».

Но, возможно, это НЕПРАВИЛЬНЫЙ способ сделать это. Я искал полиморфные ассоциации ... но не похоже, что это такая ассоциация. Что это за ассоциация? Где «Предмет» - это просто некая «модель среднего человека»?

Спасибо! (и извините за мой плохой английский)

С наилучшими пожеланиями Александр


Спасибо вам обоим за ответ. Но похоже, что не нравятся маршруты. Если я скажу что-то вроде (в частичном элементе, который зацикливает все элементы для проекта):

<%= link_to 'Destroy', [@project, item], :confirm => 'Are you sure?', :method => :delete %>

Он не ведет себя так, как хочет. Если это элемент SuperSport, используется URL:

/projects/1/super_sport/4

А если это «овечья» позиция, она переходит к

/projects/1/sheep/5

Как я могу сказать, что они ВСЕ должны перейти к:

/projects/:project_id/items/:item_id

Все они используют ItemsController. Было бы хорошо, если бы они все могли использовать этот маршрут. Я пытался с этим взломать:

class Item < ActiveRecord::Base
  belongs_to :project
  validates_uniqueness_of :type, :scope => :project_id

  # Hack.
  def self.model_name
    name = 'item'
    name.instance_eval do
      def plural;   pluralize;   end
      def singular; singularize; end
    end
    return name
  end
end

Но тогда проверка нарушается. Я надеюсь, вы понимаете мою проблему!

Ответы [ 2 ]

4 голосов
/ 05 декабря 2010

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

class Sport < ActiveRecord::Base
  belongs_to :item
end

class NormalSport < Sport
end

class SuperSport < Sport
end

class Item < ActiveRecord::Base
  has_many :sports
  has_many :normal_sports
  has_many :super_sports
end

Используя правильный класс, Rails автоматически отфильтрует для вас таблицу sports. Если использование разных классов затруднительно, вы также можете использовать базовый класс Sport и фильтровать поле type вручную.

1 голос
/ 04 декабря 2010

Если полиморфные ассоциации не отвечают вашим потребностям, вы также можете обратиться к наследованию одной таблицы (STI).

Другим подходом будет определение областей для выбора дочерних моделей.

...