Rails 如何在不使用迭代的情况下访问 belongs_to table

Rails how to access belongs_to table without using iteration

这似乎是一个常见但棘手的问题,但我无法找到有关如何在线解决此问题的任何线索。我有 2 个表,用户配置文件和程序。每个 userprofile has_many :programsprograms belongs_to :userprofile

Userprofile.rb

class Userprofile < ActiveRecord::Base
  attr_accessible :user_id, :programs_attributes
  has_many :programs

  accepts_nested_attributes_for :programs

Program.rb

class Program < ActiveRecord::Base
    attr_accessible :userprofile_id, :program_name, :program_role, :program_year

    belongs_to :userprofile
end

我的问题是,只有当 userprofile.programs 不为空并且 program_name、program_role 和 program_year 不为空。

当我使用迭代器时,我可以检查 program_name、program_role、program_year。但是 "Program" 标题会打印多次(取决于用户已完全填写的数字程序)。

<% @userprofile.programs.each do |program| %> 
  <% if program.blank? || program.program_name.blank? || program.program_role.blank? || program.program_year.blank? %>
  <% else %>
    <h3>Program </h3> <br />
    <%= program.program_name %><br />
    <%= program.program_role %><br /> 
    <%= program.program_year %>
   <% end %>
 <% end %>

但是当我将标题移出循环时,我不确定如何进行检查:

<% if @userprofile.programs.blank? || @userprofile.programs.program_name.blank? %>
<% else %>
  <h3>Program </h3> <br />
  <% @userprofile.programs.each do |program| %> 

    <%= program.program_name %><br />
    <%= program.program_role %><br /> 
    <%= program.program_year %>

  <% end %>
<% end %>

这将导致 undefined method 'program_name' 错误。我认为从迭代中取出标题并以某种方式访问​​ program_name、program_role、program_year 会解决问题,但我不确定如何正确实现。

我也试过从 (how to access fields in belongs_to association in rails)

映射
<%= @program_names = @userprofile.programs.map(&:program_name) %>
<%= @program_years = @userprofile.programs.map(&:program_year) %>
<%= @program_roles = @userprofile.programs.map(&:program_role) %>

  <% if @userprofile.programs.blank? || @program_names.empty? || @program_years.empty? || @program_roles.blank? %>
    <% else %>

      <h3>Program </h3> <br />

       <% @userprofile.programs.each do |program| %> 

         <% if program.program_name.blank? %>
         <% else %>

           <%= program.program_name %><br />
           <%= program.program_role %><br /> 
           <%= program.program_year %>
         <% end %>
       <% end %>
     <% end %>

这似乎有效,除非所有数组都是,例如:["","",""] 或 [nil, nil,nil]。 "Program" 标题在应该隐藏时仍然显示。

任何建议都会有所帮助。谢谢!

为了高效查询,您应该这样做:

@userprofile.programs.where.not(program_name: nil, program_role: nil, program_year: nil)

尽管仍会包含空字符串,但查询并未包含所有内容,但您可以通过向模型添加额外的逻辑来对其进行过滤。

#models/program.rb
...
def displayable?
  program_name.present? && program_role.present? && program_year.present?
end
...

那么在你看来,你应该可以做到

<% programs.each do |program| %>
   <% if program.displayable? %>
      <%= program.program_name %><br />
      <%= program.program_role %><br /> 
      <%= program.program_year %>
   <% end %>
<% end %>

更新

正如@Éric-côté 指出的那样,您应该能够做到:

scope :displayable_programs, -> { where.not(program_name: nil, program_role: nil, program_year: nil) }

使用这种方法,在您看来,您可以:

<% programs = @userprofile.programs.displayable_programs %>
<% if programs.exists? %>
    <h3>Program </h3> <br />
    <% programs.each do |program| %>
       <% if program.displayable? %>
          <%= program.program_name %><br />
          <%= program.program_role %><br /> 
          <%= program.program_year %>
       <% end %>
    <% end %>
<% end %>

同样按照您之前的方法,您可以使用一种跟踪器,例如

<% program_shown = false %>
<% @userprofile.programs.each do |program| %> 
  <% if program.blank? || program.program_name.blank? || program.program_role.blank? || program.program_year.blank? %>
  <% else %>
    <% unless program_shown %>
      <h3>Program </h3> <br />
    <% program_shown = true %>
    <% end %>
    <%= program.program_name %><br />
    <%= program.program_role %><br /> 
    <%= program.program_year %>
   <% end %>
 <% end %>