<% 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!
Related
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'.
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
I want to show a post author's name; <% #post.author.name %> works unless author is nil. So I either use unless #post.author.nil? or add a author_name method that checks for nil as in <% #post.author_name %>. The latter I try to avoid.
The problem is that I may need to add/remove words depending on whether there is a value or not. For instance, "Posted on 1/2/3 by " would be the content if I simply display nil. I need to remove the " by " if author is nil.
Null object pattern is one way to avoid this. In your class:
def author
super || build_author
end
This way you will get an empty author no matter what. However, since you don't actually want to have an empty object sometimes when you do expect nil, you can use presenter of some kind.
class PostPresenter
def initialize(post)
#post = post
end
def post_author
(#post.author && #post.author.name) || 'Anonymous'
end
end
Another way is using try, as in #post.author.try(:name), if you can get used to that.
You can use try:
<%= #post.author.try(:name) %>
It will attempt to call the name method on #post.author if it is non-nil. Otherwise it will return nil, and no exception will be raised.
Answer to your second question: In principle there is nothing wrong with the following:
<% if #post.author %>
written by <%= #post.author.name %>
<% end %>
or
<%= "written by #{#post.author.name}" if #post.author %>
But if this is a recurring pattern, you might want to write a helper method for it.
# app/helpers/authors_helper.rb or app/helpers/people_helper.rb
class AuthorsHelper
def written_by(author)
"written by #{author.name}" if author
end
end
# in your views
<%= written_by(#post.author) %>
Write a method which accepts any variable and checks to see if it is nuil first, and if it is not displays it. Then you only have to write one method.
I found your question interesting as I have often come across similar situations, so I thought I'd try out making my first Rails plugin.
I'm afraid I haven't put in any tests yet but you can try it out http://github.com/reubenmallaby/acts_as_nothing (I'm using Ruby 1.9.1 so let me know if you get any problems in the comments or on Github!)
I've been a bad kid and used the following syntax in my partial templates to set default values for local variables if a value wasn't explicitly defined in the :locals hash when rendering the partial --
<% foo = default_value unless (defined? foo) %>
This seemed to work fine until recently, when (for no reason I could discern) non-passed variables started behaving as if they had been defined to nil (rather than undefined).
As has been pointed by various helpful people on SO, http://api.rubyonrails.org/classes/ActionView/Base.html says not to use
defined? foo
and instead to use
local_assigns.has_key? :foo
I'm trying to amend my ways, but that means changing a lot of templates.
Can/should I just charge ahead and make this change in all the templates? Is there any trickiness I need to watch for? How diligently do I need to test each one?
I do this:
<% some_local = default_value if local_assigns[:some_local].nil? %>
Since local_assigns is a hash, you could also use fetch with the optional default_value.
local_assigns.fetch :foo, default_value
This will return default_value if foo wasn't set.
WARNING:
Be careful with local_assigns.fetch :foo, default_value when default_value is a method, as it will be called anyway in order to pass its result to fetch.
If your default_value is a method, you can wrap it in a block: local_assigns.fetch(:foo) { default_value } to prevent its call when it's not needed.
How about
<% foo ||= default_value %>
This says "use foo if it is not nil or true. Otherwise assign default_value to foo"
I think this should be repeated here (from http://api.rubyonrails.org/classes/ActionView/Base.html):
If you need to find out whether a certain local variable has been assigned a value in a particular render call, you need to use the following pattern:
<% if local_assigns.has_key? :headline %>
Headline: <%= headline %>
<% end %>
Testing using defined? headline will not work. This is an implementation restriction.
In my case, I use:
<% variable ||= "" %>
in my partial.
I don't have idea if that is good but for my is OK
I know it's an old thread but here's my small contribution: i would use local_assigns[:foo].presence in a conditional inside the partial.
Then i set foo only when needed in the render call:
<%= render 'path/to/my_partial', always_present_local_var: "bar", foo: "baz" %>
Have a look at te official Rails guide here. Valid from RoR 3.1.0.
This is a derivative of Pablo's answer. This allows me to set a default ('full'), and in the end, 'mode' is set in both local_assigns and an actual local variable.
haml/slim:
- mode ||= local_assigns[:mode] = local_assigns.fetch(:mode, 'full')
erb:
<% mode ||= local_assigns[:mode] = local_assigns.fetch(:mode, 'full') %>
I think a better option that allows for multiple default variables:
<% options = local_assigns.reverse_merge(:include_css => true, :include_js => true) %>
<%= include_stylesheets :national_header_css if options[:include_css] %>
<%= include_javascripts :national_header_js if options[:include_js] %>
Ruby 2.5
Erb
It's possible, but you must to declare your default values in the scope.
VARIABLE the word for replacement.
# index.html.erb
...
<%= render 'some_content', VARIABLE: false %>
...
# _some_content.html.erb
...
<% VARIABLE = true if local_assigns[:VARIABLE].nil? %>
<% if VARIABLE %>
<h1>Do you see me?</h1>
<% end %>
...
More intuitive and compact:
<% some_local = default_value unless local_assigns[:some_local] %>
If you do not want to pass local variable to partial each time you call it you do this:
<% local_param = defined?(local_param) ? local_param : nil %>
This way you avoid undefined variable error. This will allow you to call your partial with/without local variables.
A helper can be created to look like this:
somearg = opt(:somearg) { :defaultvalue }
Implemented like:
module OptHelper
def opt(name, &block)
was_assigned, value = eval(
"[ local_assigns.has_key?(:#{name}), local_assigns[:#{name}] ]",
block.binding)
if was_assigned
value
else
yield
end
end
end
See my blog for details on how and why.
Note that this solution does allow you to pass nil or false as the value without it being overridden.
I would like to display a line of text only if an object called #foo is set.
In my view, I'm trying something like this:
<% if !#foo.new_record? || !#foo.nil? %>
Foo is not a new record or nil
<% end %>
But this fails, returning You have a nil object when you didn't expect it!
I'm pretty sure this happens because of the new_record? method.
How do I check if something is not a new record or nil without causing an error?
In PHP, it would be achieved by asking if(!empty($foo)) but even the empty? method in rails causes the same error to be returned.
Any ideas?
How about:
<% if !#foo.nil? && !#foo.new_record? %>
Hello!
<% end %>
First off, you need to be using AND logic rather than OR logic here, since any ActiveRecord object meets at least one the requirements of "not nil" or "not a new record".
Second, checking for nil first ensures that the second check isn't run if the first one fails. The error is thrown because you can't use #new_record? on an object that doesn't support it, so checking for nil first ensures that that method is never run on a nil.
Let me throw another answer just for fun.
unless #foo.nil? or #foo.new_record?
"Hello"
end
You might be interested in these as well:
<%= #foo.text if #foo.present? %>
or
<%= #foo.text unless #foo.blank? %>
I would check by if #foo && #foo.id. This checks that there is a #foo activerecord object and makes sure the id field is not empty. If the id field is empty, that means it's not a record in the database yet. I assume you are using id field in the table.
The simple way is
<% if !#foo.try(:new_record) %>
Hello!
<% end %>
Is there a reason why this object might be nil when it gets to the view? Sometimes adding conditional logic like this in the view can be a sign that something could be refactored and you are just masking a bigger problem.
I much prefer to use the andand gem for these checks.
if #foo.andand.id
"Hello!"
end
The call to .id will only be made on non-nil objects.