在Ruby on Rails中使用多态的替代方案

8
我目前正在编写一些内部网络应用程序,人们可以通过这些应用程序向管理员提交添加不同资源的请求。例如,请求可能包括:
  • 安装程序,用户将选择他想要安装的程序
  • 增加配额,用户只需输入他需要的磁盘空间量,或者他可以选择预定义的数量 - 1GB,10GB等...
  • 创建新的电子邮件别名,用户只需键入别名。
  • ...
我考虑只有一个UserRequests模型,其中包含对发送者的引用和两个可选属性,一个是reference_id,它将引用其他表(例如,他想要安装的程序),另一个用于自由类型字段,如电子邮件别名或配额。
所以我的问题是,根据请求的类型,模型应该包含以下内容之一:
  • 对其他表的引用
  • 整数数据
  • 字符串数据
根据请求的类型,应采取相应的行动 - 可能可以通过Rails添加电子邮件别名,但用户计算机上的应用程序将手动安装。
有人遇到过类似的问题吗?您认为为此类问题使用多态是一个好主意吗?您对如何组织表中的数据有什么建议吗?
2个回答

9

单表继承!这样你就可以让每种类型的请求具有自定义的验证,同时仍然让每个请求存在于同一个表中。

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”或其他内容,以使您的其他代码更具意义。让模型成为隐藏所有内容的小黑盒子。

这正是我一直在寻找的,你的帖子让我有了一些启发。谢谢。 - Jakub Troszok
Ian是正确的,STI非常适合你在这里的请求。关于多态性在这种情况下何时有用的示例是,如果您既有一个具有许多请求的用户,又有一个具有许多请求的程序。然后,由于多态性,它们都可以拥有许多请求,并且请求仍然可以像STI一样使用。 - Houen

2
我会使用多态关联,它允许一个模型使用单个关联属于不止一个其他模型。类似这样:
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
  • 像往常一样,Ryan Bates 在这个主题上有一个优秀的 Railscast

这很有趣,但在这种情况下,我更愿意避免为每种请求创建一个表/模型。感谢指出railcasts。 - Jakub Troszok

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接