【问题标题】:How to get related records across a join table in Rails?如何在 Rails 中的连接表中获取相关记录?
【发布时间】:2013-12-12 23:15:57
【问题描述】:

在我的 Rails 应用程序中,people 可以有多个 projects,反之亦然:

# app/models/person.rb
class Person < ActiveRecord::Base
  has_many :people_projects
  has_many :projects, :through => :people_projects
end

# app/models/people_project.rb
class PeopleProject < ActiveRecord::Base 
  belongs_to :person
  belongs_to :project 
end

# app/models/project.rb
class Project < ActiveRecord::Base
  has_many :people_projects
  has_many :people, :through => :people_projects

  def self.search(person_id)
    if person_id
      where("person_id = ?", person_id) # not working because no person_id column in projects table
    else
      scoped
    end
  end
end

如何在我的ProjectsControllerindex 视图中按person_id 过滤项目,例如通过使用这样的 URL:http://localhost:3000/projects?person_id=164

我无法理解这一点。请帮忙!谢谢...

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-3 activerecord associations


    【解决方案1】:

    PersonProject 模型的关联定义不完整。您还需要定义has_many :people_projects

    # app/models/person.rb
    class Person < ActiveRecord::Base
      has_many :people_projects # <-- This line
      has_many :projects, :through => :people_projects
    end
    
    # app/models/project.rb
    class Project < ActiveRecord::Base
      has_many :people_projects # <-- This line
      has_many :people, :through => :people_projects
    end
    
    # app/models/people_project.rb
    # This is defined correctly
    class PeopleProject < ActiveRecord::Base
      belongs_to :person
      belongs_to :project
    end
    

    详情请参考The has_many :through Association

    使用此定义,您将能够使用current_user.projects 获取当前用户的所有项目,就像您已经在ProjectsController#index 中所做的那样。

    更新:

    您可以在 search 方法中使用 joinsincludes 并应用 where 条件。如下所示:

    # app/models/project.rb
    class Project < ActiveRecord::Base
      has_many :people_projects
      has_many :people, :through => :people_projects
    
      def self.search(person_id)
        if person_id
          includes([:people_projects, :people]).where("people.id = ?", person_id) 
        else
          scoped
        end
      end
    end
    

    【讨论】:

    • 您好,感谢您的帮助。我的关联定义是正确的。我只是忘记在我的 OP 中包含这两行。对于那个很抱歉。我相应地改变了我的问题。
    • @Tintin81,请参阅上面的更新。看看你评论的“不起作用”。
    • 好的,谢谢。我尝试了您的建议,但出现此错误:SQLite3::SQLException: no such column: people.person_id
    • @Tintin81,对于错误输入列名表示歉意。如更新所示,它应该是 where("people.id"... 而不是 where("people.person_id...
    • 该错误的原因是您的order by 子句。您需要指定您所追求的created_at 的表。您可以将以下内容附加到您的 AR 查询 .order('projects.id desc')
    【解决方案2】:

    projects 表中不会有 person_id,因为它是 has_manyhas_many 关系。

    简单地@person.projects 将执行一个join btw person_projects & projects 表并返回适当的项目。

    *我假设,current_user 返回一个 Person 对象。*

    另外,完成您的模型定义。他们每个人都应该列出他们与 PeopleProjects 的关系

    class Person < ActiveRecord::Base
      has_many :people_projects
      has_many :projects, :through => :people_projects
    end
    
    class Project < ActiveRecord::Base
      has_many :people_projects
      has_many :people, :through => :people_projects
    end
    

    【讨论】:

    • 非常感谢。我意识到我在原来的帖子中犯了一个错误,并在上面更正了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-21
    • 2012-03-09
    • 2022-11-18
    • 2021-02-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多