0

I am trying to write a method in my show.html.erb page that has two boolean conditions to the first if condition.

I have:

<% if @project.requires_educator_approval && @project.educator_approved == false %>
  <p>Approved</p>
<% elsif @project.requires_educator_approval && @project.approval_requested && @project.educator_approved == false %>
  <p>Approval requested</p>
<% elsif @project.requires_educator_approval && @project.approval_requested == false %>
  <p>Approval request pending</p>
<% elsif @project.requires_educator_approval == false %>
  <p>No approval required</p>
<% else %>
  <p>TBC</p> 
<% end %>

I think the above isn't correct, but I'm stuck for fresh ideas as to how to approach it.

I have boolean attributes in my database for each of these conditions (so I think I can use the ? to check if it's true, but is there a !? to check if it's not true?)

Does anyone have better ideas about how to go about this?

Thanks very much.

3 Answers 3

1

The logic looks good to me. For logical not, you can use !if or unless in your code. To directly answer your first question, no, you can't just append a question mark to check for true vs. false. In Rails, it's best to either just call the property on the object, or, if you want to be explicit, you can call either present? or blank?, as present? returns true if a value is set / set to true, and blank? returns true if a value is nil or false.

I personally don't like that much logic in a view, so I would make this a helper method:

# app/helpers/application_helper.rb
def approval_helper(project)
  approval_string = "TBC"

  approval_string = if project.requires_educator_approval
                      if project.approval_requested
                        if project.educator_approved
                          "Approved"
                        else
                          "Approval Requested"
                        end
                      else
                        "Approval Request Pending"
                      end
                    else
                      "No approval required."
                    end
end

Then in your view, call:

<%= approval_string(@project) %>
Sign up to request clarification or add additional context in comments.

2 Comments

Or you could use if not; unless was ported over form Perl and it's bad coding practice to even use it there. It's better to be consistent in your logic conditions than use fewer words.
True. I personally don't like unless, but I also don't like not, and, and or - I prefer their logical "equivalents" of !, &&, and ||, respectively.
0

It is better to keep logic out of the views where possible. Move the logic to the controller and create a variable for the text you want displayed.

Controller:

@approval_status = nil

if @project.requires_educator_approval && @project.educator_approved == false
  @approval_status = "Approved"
elsif @project.requires_educator_approval && @project.approval_requested && @project.educator_approved == false
  @approval_status = "Approval requested"
elsif @project.requires_educator_approval && @project.approval_requested == false
  @approval_status = "Approval request pending"
elsif @project.requires_educator_approval == false
  @approval_status = "No approval required"
else
  "TBC"
end

View:

<p><%= @approval_status %></p>

Ruby has a keyword for "if not" situations called

unless

2 Comments

I prefer to add complex logic to a helper or my model instead of my controller.
Thanks very much for the help. That looks neat and makes sense to me.
0

first make sure you have a default value set for boolean fields in your database. While not proper normalization, this helps you avoid the need to constantly check for nil?

To answer your question you can check for a not condition...

<% if @project.requires_educator_approval && [email protected]_approved %>
  <p>Approved</p>
<% elsif @project.requires_educator_approval && @project.approval_requested && ! @project.educator_approved %>
  <p>Approval requested</p>
<% elsif @project.requires_educator_approval && [email protected]_requested %>
  <p>Approval request pending</p>
<% elsif [email protected]_educator_approval %>
  <p>No approval required</p>
<% else %>
  <p>TBC</p> 
<% end %>

Having said all of that... you may want to utilize a case statement in a helper method or if its a lot of if elsif elsif... else rewrite as a "binary string" and get an integer value which you can then figure out more easily (essentially a bitmask). Here is a down and dirty way you could do it.

def change_to_string(boolean_value)
  raise ArgumentError unless boolean_value.is_a?(Boolean)
  boolean_value ? '1' : '0'
end

calc_as_integer = [
  change_to_string(@project.requires_educator_approval), 
  change_to_string(@project.approval_requested),
  change_to_string(@project.educator_approved)
].join.to_i(2)

<% if calc_as_integer == 5 %>
  <p>Approved</p>
<% elsif 6 %>
  <p>Approval requested</p>
<% elsif 4 %>
  <p>Approval request pending</p>
<% elsif 1 %>
  <p>No approval required</p>
<% else %>
  <p>TBC</p> 
<% end %>

This is a down and dirty way of doing this but with some experimenting you can handle all your combinations. Also checkout Railscast's bitmask episode.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.