Reputation: 366
This seems like a common but tricky problem, but I wasn't able to find any clue on how to solve this online. I have 2 tables, userprofile and programs. Each userprofile has_many :programs
and programs 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
My problem is, I want to show the heading ("Programs") only if userprofile.programs is not empty and if each of the program_name, program_role and program_year is not empty.
When I use an iterator, I can do a check on the program_name, program_role, program_year. But the "Program" heading prints multiple times (depending on the number programs that the user has fully filled in).
<% @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 %>
But when I move the heading out of the loop, I am not sure how to do checks:
<% 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 %>
This will result in a undefined method 'program_name'
error. I thought taking the heading out of the iteration and somehow accessing the program_name, program_role, program_year would solve the problem but I'm not sure how to achieve that properly.
I also tried mapping from (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 %>
Which seemed to work, except when all the arrays are, for example: ["","",""] or [nil, nil,nil]. The "Program" heading still shows up when it should be hidden.
Any suggestions would help. Thank you!
Upvotes: 0
Views: 56
Reputation: 5623
For an effecient query, you should do:
@userprofile.programs.where.not(program_name: nil, program_role: nil, program_year: nil)
The query is not all encompassing though as empty strings will still be included, but you can filter that by adding an extra logic to your model.
#models/program.rb
...
def displayable?
program_name.present? && program_role.present? && program_year.present?
end
...
Then in your view, you should be able to do
<% programs.each do |program| %>
<% if program.displayable? %>
<%= program.program_name %><br />
<%= program.program_role %><br />
<%= program.program_year %>
<% end %>
<% end %>
UPDATE
As @Éric-côté pointed out, you should be able to do:
scope :displayable_programs, -> { where.not(program_name: nil, program_role: nil, program_year: nil) }
With this approach, in your view, you would do:
<% 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 %>
Also following your previous approach, you could use a kind of tracker, e.g,
<% 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 %>
Upvotes: 1