【问题标题】:Rails "undefined method for ActiveRecord_Associations_CollectionProxy"Rails“ActiveRecord_Associations_CollectionProxy 的未定义方法”
【发布时间】:2015-10-03 06:39:07
【问题描述】:

我有这个模型:

class Student < ActiveRecord::Base

    has_many :tickets
    has_many :movies, through: :tickets

end


class Movie < ActiveRecord::Base

    has_many :tickets, dependent: :destroy
    has_many :students, through: :tickets
    belongs_to :cinema

end


class Ticket < ActiveRecord::Base

    belongs_to :movie, counter_cache: true
    belongs_to :student

end


class Cinema < ActiveRecord::Base

    has_many :movies, dependent: :destroy
    has_many :students, through: :movies

    has_many :schools, dependent: :destroy
    has_many :companies, through: :yard_companies

end


class School < ActiveRecord::Base 

    belongs_to :company
    belongs_to :student
    belongs_to :cinema, counter_cache: true

end


class Teacher < ActiveRecord::Base

    belongs_to :movie, counter_cache: true
    belongs_to :company

end


class Contract < ActiveRecord::Base

    belongs_to :company
    belongs_to :student

end


class Company < ActiveRecord::Base

    has_many :teachers
    has_many :movies, through: :teachers

    has_many :contracts
    has_many :students, through: :contracts

end

如果我把它写在我的 movies_controller.rb 中:

@students = @movie.cinema.companies.students.all

我有这个错误:

#Company::ActiveRecord_Associations_CollectionProxy:0x00000007f13d88>

的未定义方法“学生”

如果我写这个:

@students = @movie.cinema.companies.find(6).students.all

它显示了我的 select_collection 中正确的学生。

如何更好地理解这个过程?

更新:

我需要这部电影的一家电影院的每个学生的collection_select。

怎么写?

【问题讨论】:

    标签: ruby-on-rails ruby postgresql ruby-on-rails-4 activerecord


    【解决方案1】:

    @students = @movie.cinema.companies.students.all 解释为什么会抛出错误

    @movie.cinema会给你电影的电影院

    @movie.cinema.companies 将为您提供该电影院的公司列表,ActiveRecord_Association_CollectionProxy

    然后,当您通过@movie.cinema.companies.students 在公司的CollectionProxy 上调用students 时,它会引发错误,因为CollectionProxy 没有这样的方法。

    @students = @movie.cinema.companies.find(6).students.all 会起作用,因为您会获得一份公司列表,然后您会从该列表中找到一家 id 为 6 的公司并列出该公司的所有学生。

    【讨论】:

    • 包含一些collect 示例可能会很有用,以了解如何真正从一系列公司中获取所有学生。
    • 我需要这部电影的一家电影院的每个学生的collection_select。怎么写?
    【解决方案2】:

    正如Nermin 所述,您正在尝试从一组子项中请求一组子项。

    您可以使用collect 来收集来自公司的学生:

    @movie.cinema.companies.collect(&:students).flatten.uniq
    

    但我认为您最好按照以下方式为 Student 模型添加范围:

    scope :for_companies, ->(_companies) {joins(:companies).where(company: _companies)}
    

    使用Student.for_companies(@movie.cinema.companies)调用

    免责声明:未经测试,但应该是一个起点!

    【讨论】:

    • 我在努力,@Matt。感谢您的宝贵答复。但是在第一个解决方案的 collection_select 中如何检索列表?我正在使用这个:&lt;%= f.collection_select(:student_id, @students, :id, :name_with_surname, options = {:include_blank =&gt; true, :prompt =&gt; true}) %&gt;
    • @JohnSam 看起来不错,但是您如何填充 @students 变量?
    • 有了这个:@students = @movie.cinema.companies.collect(&amp;:students) 在movies_controller 下def new。如何用你给我解释的.collect方法的解决方案填充集合?
    • @JohnSam 您可能需要.flatten.uniq 收集。已修改答案。试试这个,如果它失败了就发布错误。
    • 有效!因为我认为现在数组当然是扁平的。但是现在有一个问题:N+1 查询! Bullet 检测到 n+1 查询问题。怎么解决? Bullet 对我说要添加 includes(:students) 和 includes(:companies) 但在哪里:@students = @movie.cinema.companies.collect(&amp;:students).flatten.uniq?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-04
    • 2013-02-05
    • 1970-01-01
    相关资源
    最近更新 更多