ruby, how to structure an if block with AND & OR - ruby-on-rails

Right now I have the following:
<% if !#thread.nil? && #thread.name == 'X' || #thread.name == 'Y' %>
....
The problem here is that I believe regardless if !#thread.nil?, #thread.name is still be called which is causing errors.
What's the right way to write this so it's like:
<% if !#thread.nil? && #thread.name == ('X' || 'Y') %>
Some type of contained in a list? for the thread.name?
Thanks

if !#thread.nil? && ['x','Y'].include?(#thread.name)

if #thread.present? and ['X', 'Y'].include?(#thread.name)
Edit: More info on #present?.

The try method could make this code more clearer. Take a look at this http://everydayrails.com/2011/04/28/rails-try-method.html.

['x', 'Y'].include?(#thread.try(:name))
or
['x', 'Y'].include? #thread.try :name

Related

Ruby On Rails, code in each loop in view

I have a little problem...
My View:
--html---
<% #things each do |thing| %>
<% other = #others.find_by(:ID == thing.ID)%>---->it runs just once. Why?
<div>
<p>thing.ID</p> ---------------> This is correct.
<p>other.NAME</p> -------------> But it isn't. It is always same (fisrt value..).
</div>
<%end%>
--html--
I like this, that the other.NAME changes too. Thanks for the help!
You have == when you need =>
:ID == thing.ID is evaluated to false, which leads to:
#others.find_by(false) which happens to return the first record every time.
Also, your naming of attributes is not standard - by rails convention they should be small letters: other.name
you can used following query to find 'other'
other = #others.find_by_ID(thing.ID)
if record not found it will return 'nil' and not 'record not found' error.
You can used
other.try(:NAME)
other.name will give error if 'other = nil'.

Can you use dirty attributes methods with current_user in rails?

I am trying to detect whether a user changes there first name or last name. I was wondering if you can use current_user with dirty attributes? I was thinking along the lines of
<% if current_user.first_name.changed? == true || current_user.last_name.changed? == true %>
<h4>Name Changed</h4>
<% end %>
I get this error
undefined method `changed?' for "john":String
Does anyone know of a way of doing this? might be missing something obvious. Thanks
-John
Not .changed?,it is _changed?
<% if current_user.first_name_changed? == true || current_user.last_name_changed? == true %>
<h4>Name Changed</h4>
<% end %>
See here

RAILS or in if statement

I'm not sure how to use the OR in a view IF statement.
This doesn't work:
<% if current_user.employee.emptype.typename == "ADMIN" or "TECH" %>
Thanks!
Write something like this :
<% if current_user.employee.emptype.typename == "ADMIN" || current_user.employee.emptype.typename == "TECH" %>
Or better
<% if ['TECH', 'ADMIN'].include?(current_user.employee.emptype.typename) %>
Be careful with OR and AND keywords, they don't have same operators priority than && and ||
You can do this one of two ways. I prefer the first method.
<% if current_user.employee.emptype.typename.in?(["ADMIN", "TECH"]) %>
...or...
<% if current_user.employee.emptype.typename == "ADMIN" || current_user.employee.emptype.typename == "TECH" %>
That won't work, and it has nothing to do with views. In Ruby, all strings evaluate to true in if statements.
You have to check both values against the type name, like so:
if current_user.employee.emptype.type_name == "ADMIN" || current_user.employee.emptype.type_name == "TECH"
or check if it's contained within an array of valid types:
if ["ADMIN", "TECH"].include?(current_user.employee.emptype.type_name)
Please also see this article for a comparison of || and or in Ruby.

How do I check if a variable is defined in rails?

<% if dashboard_pane_counter.remainder(3) == 0 %>
do something
<% end>
If dasboard_pane_counter wasn't defined, how can I get this to evaluate to false rather than throw an exception?
<% if defined?(:dashboard_pane_counter) && dashboard_pane_counter.remainder(3) == 0 %>
# do_something here, this assumes that dashboard_pane_counter is defined, but not nil
<% end %>
When using rails and instance variables, nil has a try method defined, so you can do:
<% if #dashboard_pane_counter.try(:remainder(3)) == 0 %>
#do something
<% end %>
so if the instance variable is not defined, try(:anything) will return nil and therefore evaluate to false. And nil == 0 is false
local_assigns can be used for that, since this question is from a few years ago, I verified that it exists in previous versions of rails
<% if local_assigns[:dashboard_pane_counter]
&& dashboard_pane_counter.remainder(3) == 0%>
<% end %>
It's in the notes here
http://apidock.com/rails/ActionController/Base/render
Posting this answer for beginner coders like myself. This question can be answered simply using two steps (or one if using &&). It is a longer and less pretty answer but helps new coders to understand what they are doing and uses a very simple technique that is not present in any of the other answers yet. The trick is to use an instance (#) variable, it will not work with a local variable:
if #foo
"bar"
end
If #foo is defined it will be return "bar", otherwise not (with no error). Therefore in two steps:
if #dashboard_pane_counter
if #dashboard_plane_counter.remainder(3) == 0
do something
end
end
Another way, with a neat gem, is 'andand.'
https://github.com/raganwald/andand
Insted of
if !var.nil?
I would use
unless var.nil?
Thats much better ruby code!

Add a selected class to links depending on id

My question is very similar to this one : Changing Current Tab in Rails
I am trying to add a 'selected' class to my link regarding the id of my portfolios controller’s show action
Here is what I've tried:
<ul>
<% for portfolio in #portfolios %>
<li class="<%= controller.class == PortfoliosController and controller.action_name == 'show' and controller.params[:id] == portfolio.id ? 'selected' : '' %>"><%= link_to portfolio.name, portfolio %></li>
<% end %>
</ul>
But it seems that the following:
controller.params[:id] == portfolio.id
doesn't match correctly and I don't understand why..
Thanks for your help!
Beware: params are always strings.
So :
controller.params[:id].to_i == portfolio.id
SideNote: extract this kind of logic in helpers, it's much cleaner.
You might be comparing string and numerical values, which in Ruby are not considered equivalent. A conversion of one of or the other might help. In fact, if you roll this up in a helper method, it might make it a lot easier to follow:
def class_for_porfolio_entry(portfolio)
controller.class == PortfoliosController and
controller.action_name == 'show' and
controller.params[:id].to_i == portfolio.id ?
'selected' :
''
end
You've got a whole lot going on there, so you might want to look at ways of reducing the complexity, for instance using params instead:
def class_for_porfolio_entry(portfolio)
params[:controller] == 'portfolios' and
params[:action] == 'show' and
params[:id].to_i == portfolio.id ?
'selected' :
''
end
This could be simplified further if you had a boolean flag set in your controller that is later used as required, avoiding hard-coding something like this:
def class_for_porfolio_entry(portfolio)
if (#show_selected_portfolio and #portfolio.id == portfolio.id)
'selected'
else
''
end
end
This presumes you have an instance variable #portfolio, which is usually the case in any controller's show method, and that you will set #show_selected_portfolio to true in any controller method where this logic applies.

Resources