如何用rails处理不同类型的用户?

时间:2015-03-18 11:15:15

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

我需要知道,如果有一种方法可以使用单一模型处理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

...

3 个答案:

答案 0 :(得分:1)

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

  class Account < ActiveRecord::Base
  end

然后,

  class Client < Account
  end

  class Provider < Account
  end

您只需在&#39;帐户&#39;中添加类型列包含表示存储对象类型的字符串。

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

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

答案 1 :(得分:1)

您可以使用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#它会返回个人服务的数量

答案 2 :(得分:0)

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

虽然单表继承在理论上更好的建模 - 我发现STI有点难以使用,有时在Rails中不可靠。无论如何,最终可能无法提高代码的清洁度或简洁性。 STI是一个很好的选择,如果你发现OP方法不能很好地工作,只要你能写出清晰简洁的代码,看起来STI可以更好地解决。

但是我开始没有STI,只有一个Client类,正如你在问题中所概述的那样。如果您以后添加STI,您仍然拥有Client类,您只需拥有PersonalClient和CompanyClient的子类。如果您愿意,稍后切换到STI并不困难,尽管它可能需要一些次要的数据库架构更改。

但我不认为它会让你获得足够的好处来证明增加的复杂性,在Rails的某个领域有时会有一些粗糙的边缘。

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