【问题标题】:How to deal with different type of users with rails?如何使用rails处理不同类型的用户?
【发布时间】:2015-03-18 11:15:14
【问题描述】:

我需要知道,是否有办法在 Rails 中使用单一模型处理不同类型的用户/客户端。

我真正需要做什么? - 我需要在我的数据库中保存不同类型的客户端。所以,我有这个迁移:

class CreateClients < ActiveRecord::Migration
  def change
    create_table :clients do |t|
      t.string :name                       # Person name if "Personal", Company name if  type "Company"
      t.string :nif                        # fillable only if type is Company
      t.string :identity_card_number       # fillable only if type is Personal
      t.integer :client_type               # Type can be Personal or Company
      t.references :company, index: true   # if type is personal, it can belong to a company
      t.timestamps null: false
    end
  end
end

然后我创建这个模型

class Client < ActiveRecord::Base
    has_many :employees, class_name: 'Client', foreign_key: 'company_id'
    belongs_to :company, class_name: 'Client'
end

注意:个人帐户可以属于或不属于公司。

根据您的经验,我这样做的方式是否正确?还有其他方法吗?

编辑:

嗨@manfergo25,

对此我还有一个问题。 “公司”和“个人”都是“客户账户”,这样,两者都必须能够购买服务。

如果我需要将客户与服务相关联,我可以这样做吗?

class Personal < Account
   has_many :services
end

class Service < ...
   belongs_to :account
end

??

【问题讨论】:

  • 你可以使用STI(Single Table Inheritance),比如class User &lt; ActiveRecord::Base,那么用户可以是class PersonalUser &lt; User或者class CompanyUser &lt; User

标签: ruby-on-rails ruby ruby-on-rails-4 associations


【解决方案1】:

正如 Sontya 所说,正确的方法是单表继承 (STI)。

  class Account < ActiveRecord::Base
  end

那么,

  class Client < Account
  end

  class Provider < Account
  end

您只需在“帐户”中添加一个类型列,以包含表示存储对象类型的字符串。

例如在控制器中你可以这样做:

account = Client.find(params[:autocomplete_client])     
params[:service][:account_id] = account.id
@service = Service.new(params[:service])

【讨论】:

  • 嗨@manfergo25,我还有一个问题。 “公司”和“个人”都是“客户账户”,这样,两者都必须能够购买服务。如果我需要将客户与服务相关联,我可以这样做吗? class Personal
  • 是的,当然。你可以做到!
  • 只是要清楚......在这种情况下,两者将共享同一个表“客户”,对吧?
  • 是的,数据库中的同一个表“帐户”。但是您可以在业务逻辑中调用“clients”,它只会返回“Client”过滤的帐户对象。我写一个例子。
【解决方案2】:

您可以使用 STI(单表继承)

class Account < ActiveRecord::Base
end

class Company < Account
    has_many :services, :dependent => :destroy
end

class Personal < Account
    has_many :services, :dependent => :destroy

end

class Service < ActiveRecord::Base
    belongs_to: personal
    belongs_to: company
end

通过上述定义,personalcompany 应该可以购买服务。 你应该可以打电话 @company.services # 会返回公司的服务数量 @personal.services#它会返回你个人的服务数量

【讨论】:

  • 在这种情况下,我只会在“Accounts”表上拥有,对吧?
【解决方案3】:

就个人而言,我认为您在问题中建议的方式就是我这样做的方式。

虽然单表继承在智能上是更好的建模——我发现 STI 在 Rails 中有点难以使用,有时甚至不可靠。并且最终可能不会提高代码的清洁度或简洁性。 STI 是一种很好的选择,如果您发现 OP 方法在允许您编写清晰简洁的代码方面效果不佳,并且似乎 STI 可以更好地工作。

但我会从没有 STI 的情况下开始,只有一个 Client 类,正如您在问题中所概述的那样。如果您稍后添加 STI,您仍然有 Client 类,您将只有 PersonalClient 和 CompanyClient 的子类。如果您愿意,以后切换到 STI 并不难,尽管它可能需要一些小的 db 架构更改。

但我认为它不会为您带来足够的好处来证明增加的复杂性是合理的,在 Rails 的一个领域,有时会有一些粗糙的边缘。

以下是有关 STI 的更多信息及其优缺点:http://eewang.github.io/blog/2013/03/12/how-and-when-to-use-single-table-inheritance-in-rails/

【讨论】:

    猜你喜欢
    • 2010-10-07
    • 1970-01-01
    • 1970-01-01
    • 2020-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多