Динамические ассоциации с Rails?

Я немного запутался в определении дизайна модели для текущего проекта, над которым я работаю.

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

A team:
-> has_many soccer_players
-> has_many basketball_players
-> ...

Но это кажется повторяющимся, и у меня будет много has_many, по одному для каждого вида спорта. Мой вопрос в том, что, когда пользователь создает команду, он выбирает вид спорта, мне просто нужно определить ассоциацию. Так что, если это футбольная команда, мне просто нужно «has_many soccer_players».

Как я мог это сделать? Или, что еще лучше, как бы мне лучше смоделировать это?

Спасибо


person Hommer Smith    schedule 03.04.2013    source источник


Ответы (2)


После того, что предложил Zippie и что вы спросили в комментарии, я предлагаю немного измененную версию.

Я разобью его на фразы, а затем на рубиновые классы и ассоциации, поэтому, если вы хотите сделать его по-настоящему полиморфным,

  • В команде много игроков
  • Команда имеет много Командных Атрибутов
  • У игрока много атрибутов

Это может упростить некоторые части нашего приложения. Сама модель команды для проверки и тому подобного. Вам нужно решить, какие атрибуты являются общими, а какие динамическими, например, имя, вес, рост являются общими, потому что они есть у всех игроков, поэтому они могут быть внутри вашей модели Player, а не внутри вашей модели Attribute.

Итак, теперь у нас может быть что-то вроде:

class Team < ActiveRecord::Base
  has_many :players
  has_many :attributes, :as => :attributable
end

class Player < ActiveRecord::Base
  belongs_to :team
  has_many :attributes, :as => :attributable
  attr_accessible :name, :weight, :height
end

class Attribute < ActiveRecord::Base
  belongs_to :attributable, :polymorphic => true
  attr_accessible :name, :value
end

Что касается вашего другого вопроса

У вас будет одна таблица атрибутов, одна таблица игроков и одна таблица команд. Создание футбольной команды и игроков (футбол = футбол, да?) будет примерно таким (давайте решим, что мы уже создали команду):

player = Player.new
player.name = 'Lionel Messi'
player.attributes << Attribute.create!(:name => :playing_position, :value => :second_striker)
@team.players << player
@team.attributes << Attribute.create!(:name => :uefa_cups, :value => 4)

Ваша миграция будет выглядеть примерно так (взято непосредственно из руководств по Rails — с небольшими изменениями):

class CreateAttributes < ActiveRecord::Migration
  def change
    create_table :attributes do |t|
      t.string :name
      t.string :value
      t.references :attributable, :polymorphic => true
      t.timestamps
    end
  end
end
person gmaliar    schedule 03.04.2013
comment
мне действительно нужно проверить полиморфные ассоциации в Rails - person Zippie; 03.04.2013
comment
Гай, спасибо за ответ. Я не вижу, как это будет работать, хотя. Скажем, я хочу создать новую футбольную команду и несколько футболистов. Не могли бы вы помочь мне с этим? Кроме того, как насчет миграции, нужно ли мне столько таблиц, сколько видов спорта? Я немного смущен этим атрибутом. - person Hommer Smith; 03.04.2013
comment
То есть атрибуты нигде не определялись? Они будут созданы во время выполнения. Я имею в виду, скажем, я хотел перечислить все атрибуты, которыми обладают футболисты. Это было бы невозможно при таком подходе, верно? Кроме того, если бы я хотел получить доступ к play_position «Лионеля Месси», мне нужно было бы найти, есть ли атрибут, называемый таким образом для этого игрока, верно? Большое спасибо. - person Hommer Smith; 03.04.2013
comment
Я говорю этот комментарий, потому что вижу сбивающий с толку факт отсутствия предопределенных атрибутов для игроков определенного вида спорта. Представьте, что я хочу создать форму для вставки футболиста, какие поля я бы туда поместил? Возможно, это совершенно другой подход, но его трудно увидеть. - person Hommer Smith; 03.04.2013
comment
Это можно сделать, но вам решать, как это проверить, возможно, это может быть проверка внешнего интерфейса, возможно, у вас может быть другая таблица, в которой хранятся атрибуты каждого спортивного игрока и атрибуты команды, и вы должны их проверять. Что касается второго вопроса, вы можете атаковать его с нескольких направлений, вы можете Attribute.find_by_attributable_id_and_name(:attributable_id => Messi.id, :name => :playing_position).value ИЛИ Messi.attributes.where(:name => :playing_position).value ИЛИ Вы можете метапрограммировать внутри модели с def missing_method динамическим фильтром и делать это а-ля Ruby, сообразительно? - person gmaliar; 03.04.2013
comment
@ Парень, ну, это кажется мне действительно новым. Никогда не делал полиморфных ассоциаций. Я мог бы попробовать и посмотреть ... Спасибо - person Hommer Smith; 03.04.2013

Может быть, что-то вроде:

команда:

has_many :type_of_sports, :through => type_of_sport_on_team
has_many :players, :through => types_of_sports

type_of_sport:

has_many :teams, :through => type_of_sport_on_team
has_many :players

type_of_sport_on_team:

belongs_to :team
belongs_to :type_of_sport

игрок:

belongs_to :type_of_sport

после дополнительной информации:

Class Player < ActiveRecord::Base
     attr_accessible :name, :surname, :age
end

Class BasketballPlayer < Player
     attr_accessible :free_throw_average
end

Class SoccerPlayer < Player
     attr_accessible :penalty_scores
end
person Zippie    schedule 03.04.2013
comment
Зиппи, где мне хранить конкретную информацию об игроке в конкретном виде спорта? Я имею в виду, представьте, что для футбола я хочу хранить атрибуты_1 и атрибуты_2, а для баскетбола я хочу хранить атрибуты_3 и атрибуты_4. - person Hommer Smith; 03.04.2013
comment
используя наследование классов? наличие игрока и подкласса баскетболиста и футболиста со своими дополнительными атрибутами - person Zippie; 03.04.2013
comment
Зиппи, как бы ты смоделировал, вот мой вопрос. Это на самом деле моя главная забота в этом вопросе... - person Hommer Smith; 03.04.2013