制作自我参照模型

时间:2016-12-14 06:12:32

标签: ruby-on-rails postgresql rest activerecord

所有

我仍在努力学习Rails,而且我没有太多运气找到我需要的相关答案;那就是说,我怀疑之前已经做过一些事情,因为我过去曾多次用手做过这件事。

我有一个名为tab_accounts的表,其中account_id(int)为PK。我还有一个名为mtom_account_relations的查找表。此表有两个int列(account_subject,account_associate),两者都是FK到tab_accounts.account_id。此布局的目的是允许tab_account条目之间的多对多关系。目标是创建一个端点,该端点返回帐户的详细信息以及其关联人员列表,也包括帐户。

此时我有以下内容:

模型/ account_relation.rb:

class AccountRelation < ApplicationRecord
  self.table_name = "mtom_account_relations"
  belongs_to :subject, foreign_key: "account_id", class_name: "Account"
  belongs_to :associate, foreign_key: "account_id", class_name: "Account"
end

模型/ account.rb

class Account < ApplicationRecord
  self.table_name = "tab_accounts"
  self.primary_key = "account_id"
  ...
  has_many :account_relations
  has_many :associates, :through => :account_relations
  has_many :subjects, :through => :account_relations
end

控制器/ account_controller.rb

class AccountsController < ApplicationController
  ...
  def associates
    _account_id = params[:account_id]
    @rs_account = Account
                      .select("tab_accounts.account_id, tab_accounts.screen_name, tab_accounts.friends, tab_accounts.followers")
                      .where(:tab_accounts => {account_id: _account_id})
                      .as_json[0]
    @rs_account['associates'] = Account.select("tab_accounts.account_id, tab_accounts.screen_name")
                                      .joins(:subjects)
                                      .where(:tab_accounts => {account_id: _account_id})
                                      .as_json
    render json: @rs_account
  end
end

配置/ routes.rb中:

Rails.application.routes.draw do
  ...
  get 'accounts/associates/:account_id', :to => "accounts#associates"
end

当我运行该方法时,我收到以下错误:

PG::UndefinedColumn: ERROR: column mtom_account_relations.account_id does not exist LINE 1: ..._accounts" INNER JOIN "mtom_account_relations" ON "mtom_acco... ^ : SELECT tab_accounts.account_id, tab_accounts.screen_name FROM "tab_accounts" INNER JOIN "mtom_account_relations" ON "mtom_account_relations"."account_id" = "tab_accounts"."account_id" INNER JOIN "tab_accounts" "subjects_tab_accounts" ON "subjects_tab_accounts"."account_id" = "mtom_account_relations"."account_id" WHERE "tab_accounts"."account_id" = $1
  1. 我怀疑对不存在的表的调用&#34; subject_tab_accounts&#34;正在从控制器中的.joins(:subjects)子句创建。

  2. 它认为有&#34; mtom_account_relations&#34;。&#34; account_id&#34;列。

  3. 我很感激任何可行的协助。谢谢你的关注。

1 个答案:

答案 0 :(得分:0)

考虑这个家谱树的例子。由于Person可以在parent_idchild_id列设置has_many :relationships关系,因此我们不知道在连接中使用哪个列,因此无效。

相反,我们需要根据我们加入的关系中的哪个外键设置单独的关系,然后通过此关系进行查询

class Person
  has_many :relationships_as_child,
    class_name: 'Relationship'
    foreign_key: 'child_id'
  has_many :relationships_as_parent,
    class_name: 'Relationship'
    foreign_key: 'parent_id'

  has_many :parents, 
    through: :relationships_as_child,
    source: :parent
  has_many :children, 
    through: :relationships_as_child,
    source: :child
end

class Relationship
  belongs_to :parent, class_name: 'Person'
  belongs_to :child, class_name: 'Person'
end
class AccountRelation < ApplicationRecord
  self.table_name = "mtom_account_relations"
  belongs_to :subject, 
     foreign_key: "account_id", 
     class_name: "Account"
  belongs_to :associate, foreign_key: "account_id", 
     class_name: "Account"
end

class Account < ApplicationRecord
  self.table_name = "tab_accounts"
  self.primary_key = "account_id"
  ...
  has_many :account_relations_as_subject,
    class_name: 'AccountRelation', 
    foreign_key: 'subject_id'

  has_many :account_relations_as_associate,
    class_name: 'AccountRelation',
    foreign_key: 'associate_id'

  has_many :associates, 
    through: :account_relations_as_subject,
    source: :associate

  has_many :subjects,
    through: :account_relations_as_associate,
    source: :subject
end

在学习Rails时,我非常鼓励你学会喜欢在一般命名表,主键和列时的约定。不要让自己变得更难。

说到控制器,我会这样设置:

#routes.rb
resources :accounts do
  resources :associates, only: [:index]
end

class AssociatesController
  # GET /accounts/:account_id/associates
  def index
    @account = Account.joins(:associates).find(params[:account_id])
    @associates = @account.associates
  end
end

此模型关联为RESTful资源,该资源嵌套在帐户下,并为您提供直接和传统的方式来添加更多CRUD操作。