Rails 4:推荐模型协会

Rails 4: Referral Model Associations

我正在创建一个 referral 模型,它将能够 link 2 个客户,一个被推荐,一个被推荐。我已经有了 client 模型,但我想知道设置 referral 模型的正确方法,以便我可以查询:

Client.find(x).referrals
# returns all referrals where referrer has the client's id

Client.find(x).referred_by
# returns client that referred this client

为同一个 table 设置两个关联是 ActiveRecord 中最棘手的关联之一。关键是为每个外键列设置不同的关联。

所以让我们从连接开始 table:

# This is a Rails 5 migration - don't copy paste it
# You'll have to generate one for rails 4
class CreateReferrals < ActiveRecord::Migration[5.0]
  def change
    create_table :referrals do |t|
      t.belongs_to :referrer_id, foreign_key: false
      t.belongs_to :referred_id, foreign_key: false
      # Since the table for the foreign key cannot be automatically derived you need to add them manually
      add_foreign_key :referrals, :clients, column: :referrer_id
      add_foreign_key :referrals, :clients, column: :referred_id
      t.timestamps
    end
  end
end

让我们设置推荐关联:

class Referral < < ActiveRecord::Base
  belongs_to :referrer, class_name: 'Client'
  belongs_to :referred, class_name: 'Client'
end

这里还没有什么时髦的。 class_name: 'Client' 告诉 ActiveRecord (AR) table 关联指向哪个,因为它不能从关联的名称派生。现在让我们在客户端上创建反向关联:

class Client < ActiveRecord::Base
  has_many :referrals, class_name: 'Referral', 
    foreign_key: 'referrer_id'
  has_many :referrals_as_referred, class_name: 'Referral', 
    foreign_key: 'referred_id'
end

要将关联添加到被推荐的其他客户或客户的推荐者,请使用间接关联:

class Client < ActiveRecord::Base
  # ...
  # clients reffered by this client
  has_many :referred_clients, 
        through: :referrals,
        source: :referred
  has_many :referrers, 
        through: :referrals_as_referred,
        source: :referrer
end
  • through: :referrals 告诉 AR 通过名为 :referrals.
  • 的协会加入
  • source: :referred 表示要使用的联接 table 上的关联。

你可以为此使用自联想。在客户端模型上,添加 referrals_id 列。客户端模型中的关联是这样的:

class Client < ActiveRecord::Base
  has_many :referrals, class_name: "Client", foreign_key: :referrals_id
  belongs_to :referred_by, class_name: "Client", foreign_key: :referrals_id
end

假设您在表中有这两条记录。

[{  
   "id":1,
   "name":"Admin",
   "referrals_id": nil,
 },
 {  
   "id":2,
   "name":"Client",
   "referrals_id":1,
 }]

现在您可以查询推荐人 returns 所有推荐人具有客户 ID 的推荐人

Client.find(1).referrals

这将生成一个 SQL 像 :

`SELECT "clients".* FROM "clients" WHERE "clients"."referrals_id" = ?  [["referrals_id", 1]]`

对于 referred_by 将 returns 推荐此客户的客户

Client.find(2).referred_by

这将生成 SQL 如:

SELECT  "clients".* FROM "clients" WHERE "clients"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]