Альтернативы использованию полиморфизма в Ruby on Rails - PullRequest
8 голосов
/ 29 мая 2009

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

  • установка программ, в этом случае пользователь выберет, какую программу он хочет установить
  • увеличение квоты, в этом случае пользователь просто введет объем дискового пространства, который ему нужен, или, возможно, он выберет предварительно определенные количества - 1 ГБ, 10 ГБ и т. Д.
  • создайте новый псевдоним электронной почты, в этом случае пользователь просто наберет псевдоним.
  • ...

Я думал о том, чтобы иметь только одну модель UserRequests со ссылкой на отправителя и два необязательных атрибута, один будет reference_id, который будет ссылаться на другие таблицы (для например программа, которую он хочет установить), а другая будет использоваться для полей свободного типа как псевдоним электронной почты или квота.

Так что моя проблема в том, что в зависимости от типа запроса модель должна содержать:

  • ссылка на другую таблицу
  • целочисленные данные
  • строковые данные

В зависимости от типа запроса должно быть выполнено данное действие - возможно, псевдоним электронной почты. можно добавить с рельсов, но приложение на компьютере пользователя будет установлено вручную.

У кого-нибудь была подобная проблема? Как вы думаете, использование полиморфизма для такого рода вещей является хорошей идеей? Есть ли у вас какие-либо предложения по организации данных в таблицах?

Ответы [ 2 ]

8 голосов
/ 29 мая 2009

Наследование в одной таблице! Таким образом, каждый тип запроса может иметь пользовательские проверки, при этом каждый запрос остается в одной таблице.

class CreateUserRequests < ActiveRecord::Migration
  def self.up
    create_table :user_requests do |t|
      t.string :string_data, :type
      t.integer :user_id, :integer_data
      t.timestamps
    end
  end
  def self.down
    drop_table :user_requests
  end
end


class UserRequest < ActiveRecord::Base
  belongs_to :user
end

class EmailAliasRequest < UserRequest
  validates_presence_of :string_data
  validates_format_of :string_data, :with => EMAIL_REGEX
end

class ProgramInstallRequest < UserRequest
  belongs_to :program, :class_name => "Program", :foreign_key => "integer_data"
  validates_presence_of :integer_data
end

class QuotaIncreaseRequest < UserRequest
  validates_presence_of :string_data
  validates_inclusion_of :string_data, :in => %w( 1GB 5GB 10GB 15GB )
end

И, конечно же, псевдонимы от ваших string_data и integer_data до email или еще много чего, чтобы ваш другой код имел немного большее значение. Пусть модель будет маленьким черным ящиком, который скрывает все это.

2 голосов
/ 29 мая 2009

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

class AdminRequest < ActiveRecord::Base
  belongs_to :user
  belongs_to :requestable, :polymorphic => true
end

class EmailAlias < ActiveRecord::Base
  has_many :admin_requests, :as => :requestable
end

class ProgramInstall < ActiveRecord::Base
  has_many :admin_requests, :as => :requestable
end

class QuotaIncrease < ActiveRecord::Base
  has_many :admin_requests, :as => :requestable
end
  • Как всегда, у Райана Бейтса есть превосходный Railscast на эту тему.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...