Can't use hash.key in a ternary if statement? - ruby-on-rails

I have a hash containing key value pairs, and I'm trying to use a ternary if but it doesn't seem to work.
<%= #positions.key? 'dashboard' %> # => true
<%= #positions.key? 'dashboard' ? 'true text' : 'no text' %> # => false
Am I not using the correct code? If this doesn't work is there a way to check if a hash key exists using a ternary if condition?

Add parenthesis around parameter:
<%= #positions.key?('dashboard') ? 'true text' : 'no text' %>

Related

if condition in haml view

I want to set a :data attr if a condition is met. In this case a user should have a role. So it's a boolean statement. Let me give an example.
- #data = 'contract-confirm'
.create_button= link_to 'Something', new_some_path(#customer), :class => 'btn btn-success', :'data' => #data ? 'contract' : nil
.clearer
So I know this might look strange but I want to set a data attribute if customer is labeled and then hook js to that data attr. That part works. What does not work is that now I'm setting the attribute always. So even in the case that customer does not have the role the js gets hooked. I know that I am not explicitly indicating at all the role here. I have a #customer.role? but I cant seem to incorporate it properply. I managed it before with an if else statement but then with a lot of duplication which I'm not so fund of. Any tips?
You can try this piece of code:
link_to 'Something', ... , :data => #customer.role? ? 'contract' : nil
haml won't include nil attributes, so it should work as you expect.
Try to replace :'data' => #data ? 'contract' : nil with :'data' => 'contract' if #data.
I checked it and next code:
- #data_present = true
= link_to 'Something', root_path, :class => 'btn', :'data' => ('test' if #data_present)
renders to:
Something
And code without - #data_present = true renders to:
Something

Better way to default Rails form instead of using ternary?

I have some code like this:
<input type="text" value="<%= params[:first_name] ? params[:first_name] : 'John' %>>
Obviously this is not ideal as it repeats params[:first_name] twice. Is there a better way to have a form default to param, but if there is no param value for it use a default value?
How about:
params[:first_name] || 'John'
Not sure why you aren't using Rails' form helpers, but I suggest you start using them. You can use :value => 'John' to set the default value of a text_field to "John":
<%= form_for #object do |f| %>
<%= f.text_field :attribute_name, :value => 'John' %>
...
<% end %>
If for some reason it's not possible to use the form helpers then you should go with shioyama's answer.
You can use ||= operator in such situations as below -
a = "Rafa"
a.empty? ? "Nadal" : a # => "Rafa"
a ||= "Nadal" # => "Rafa"
If your variable is undefined and you use ternary, NameError exception will be raised
b ? "Rafa" : b # => NameError: undefined local variable or method `b' for main:Object
However ||= operator will initialise it to "Nadal"
b ||= "Nadal" # => "Nadal"
Basically b ||= "Nadal" evaluates to b = b || "Nadal" i.e. if b already exists in the current scope use its value whatever it may be, else initialise it to "Nadal".

Rails I18n, check if translation exists?

Working on a rails 3 app where I want to check if a translation exists before outputting it, and if it doesn't exist fall back to some static text. I could do something like:
if I18n.t("some_translation.key").to_s.index("translation missing")
But I feel like there should be a better way than that. What if rails in the future changes the "translation missing" to "translation not found". Or what if for some weird reason the text contains "translation missing". Any ideas?
Based on what you've described, this should work:
I18n.t("some_translation.key", :default => "fallback text")
See the documentation for details.
You can also use
I18n.exists?(key, locale)
I18n.exists?('do_i_exist', :en)
:default is not always a solution. Use this for more advanced cases:
helpers/application.rb:
def i18n_set? key
I18n.t key, :raise => true rescue false
end
any ERB template:
<% if i18n_set? "home.#{name}.quote" %>
<div class="quote">
<blockquote><%= t "home.#{name}.quote" %></blockquote>
<cite><%= t "home.#{name}.cite" %></cite>
</div>
<% end %>
What about this ?
I18n.t('some_translation.key', :default => '').empty?
I just think it feels better, more like there is no translation
Caveat: doesn't work if you intentionally have an empty string as translation value.
use :default param:
I18n.t("some_translation.key", :default => 'some text')
sometimes you want to do more things on translations fails
v = "doesnt_exist"
begin
puts I18n.t "langs.#{v}", raise: true
rescue
...
puts "Nooo #{v} has no Translation!"
end
This is a trick but I think it may be useful sometimes...
Assuming you have this in your i18n file:
en:
key:
special_value: "Special value"
default_value: "Default value"
You may do this:
if I18n.t('key').keys.include?(:special_value)
I18n.t('key.special_value')
else
I18n.t('key.default_value')
end
# => "Special value"
if I18n.t('key').keys.include?(:unknown_value)
I18n.t('key.special_value')
else
I18n.t('key.default_value')
end
# => "Default value"
NB: This only works if you're testing anything but a root key since you're looking at the parent.
In fact, what's interesting is what you can get when requesting a parent key...
I18n.t('key')
# => {:special_value=>"Special value", :default_value=>"Default value"}
Rails 4
I was iterating over some urls of jury members. The max amount of urls were 2, and default_lang was "de". Here is the yaml that I used
de:
jury:
urls:
url0: http://www.example.com
name0: example.com
url1:
name1:
en:
jury:
urls:
url0:
name0:
url1:
name1:
Here is how I checked if there was a url given and if it did not exist for another language, it would fallback to the I18n default_lang "de". I used answer of #albandiguer which worked great.
I Hope this helps someone:
<% 2.times do |j| %>
<% if I18n.exists?("jury.urls.url#{j}", "de") &&
I18n.exists?("jury.urls.name#{j}", "de") %>
<%= "<br/>".html_safe if j == 1%>
<a href="<%= t("jury.urls.url#{j}") %>" target="_blank">
<%= t("jury.urls.name#{j}") %>
</a>
<% end %>
<% end %>
Some versions ago there is a easier way i18next documentation > API > t:
You can specify either one key as a String or multiple keys as an Array of String. The first one that resolves will be returned.
Example:
i18next.t ( ['unknown.key', 'my.key' ] ); // It will return value for 'my.key'
Also you can use Contexts. t if not found a key into a context returns the default value.

Retaining search results after submitting the search (rails)

I'd like to make it so that after users submit their search, the option they selected stays selected upon the search form's reload. Here's my code for one of these select boxes:
<div><%= f.select :tod_like, Course.tod_array, {:include_blank => true, :selected => params[:search][:tod_like], :class=>"float_and_margin"} %></div>
The key code is the
:selected => params[:search][:tod_like]
When I refresh my page, I get the following error:
You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.[]
I know I'm getting this error because there's params[:search][:tod_like] is blank. How do I set :selected so that it's blank if the user has not submitted a form, but is the submission, otherwise? I tried using a ternary operator, but that didn't work.
Thanks!
Is the params key correct?
I take it the form f is for an instance of Course so wouldn't it be something like
#course.tod_like = params[:search][:tod_like] ? params[:search][:tod_like] : ""
at the top of the function that generates the search function (you have mentioned that you've tried a ternary statement but did you replace the :selected option at the same time?
Then :selected => #course.tod_like in the select tag?
<div><%= f.select :tod_like, Course.tod_array, {:include_blank => true, :selected => #course.tod_like, :class=>"float_and_margin"} %></div>
Hmm, I ended up fixing this problem by defining a ternary operator in my courses controller, and then passing this instance variable into the appropriate view.
#tod_results = params[:search] == nil ? :blank : params[:search][:tod_like]
<div><%= f.select :tod_like, Course.tod_array, {:include_blank => true, :selected => #tod_results, :class=>"float_and_margin"} %></div>
The key difference between this code and the previous ternary operator I tried is that I'm testing to see if params[:search] is nil, not if params[:search][:tod_like] is nil. Since params[:search] is already nil, I got the "you were expecting an array, but got nil" error when I tried to use params[:search][:tod_like].
Thanks for your responses!

Proper way to write this condition

unless #client.nil?
TestMailer.snap_shot_error("test1","Errors",
{:file_name => File.basename(upload_file),:client_name => #client.client_name})
else
TestMailer.snap_shot_error("test1","Errors",
{:file_name => File.basename(upload_file))
end
def snap_shot_error(to_address,subject,options={})
# code
end
<% if #client_name %>
<%= _("There were problems with file ") + #file_name + _(" for client ") + #client_name %>
<% else %>
<%= _("There were problems with file ") + #file_name %>
<% end %>
For both of these questoin, you can use the ternary operator. It works like this
condition ? value_if_true : value_if_false
This is an expression (a sequence of values and operators that produces another value). It determines whether the condition is true or false, and evaluates to the first value (after the ? and before the :) if the condition is true, and the second value (after the :) if the condition is false.
So, for the first code example you posted, you can do this:
TestMailer.snap_shot_error("test1", "Errors",
:file_name => File.basename(upload_file),
:client_name => #client ? #client.client_name : nil)
[Note that I've remove the curly braces around the options -- in Ruby there are not necessary for the final options hash, and it is idiomatic to leave them off]
Or if for some reason you don't even want a nil :client_name in the hash, you can use the ternary operator and a merge:
TestMailer.snap_shot_error("test1", "Errors",
{:file_name => File.basename(upload_file)}.merge(
#client ? { :client_name => #client.client_name } : {}))
For the view, you can also use the ternary operator:
<%= _("There were problems with file ") + #file_name +
(#client_name ? _(" for client ") + #client_name : '' ) %>
And now that I see what you are doing with #client_name, I don't see why you said you require that it not even be in the hash. The first code example I posted, where it passes ":client_name => #client.client_name" if there is a client and passes ":client_name => nil" if there is not a client, should work just fine. There's no reason to not pass :client_name instead of just passed a nil :client_name.

Resources