How to implement Yes/No instead of Boolean for certain cases in Rails?
Locales
I recommend using Rails locales. These enable you to define language text for any of your variables. For example, your app can say "Yes"/"No" for English speakers, and "Oui"/"Non" for French speakers.
Locales are also fast, flexible, and easy to change because they are independent of your typical source code. You can see how locales will lead to very good separation between your source code logic versus the text that you render.
Example:
#./config/locales/en.yml
en:
TrueClass: "Yes"
FalseClass: "No"
#./app/views/items/index.html.erb
The value is <%= translate(myboolean.class) %>
The translate method can be abbreviated like this <%= t myboolean.class %>
Helpers
You will likely see other people coding it like this using a helper:
#./app/helpers/application.rb
def yesno(x)
x ? "Yes" : "No"
end
# ./app/views/items/index.html.erb
<%= yesno(myboolean) %>
Or like this using a constant:
#./app/helpers/application.rb
YESNO = {true: "Yes", false: "No"}
# ./app/views/items/index.html.erb
<%= YESNO[myboolean] %>
These are both quick-and-dirty PHP-like solutions. There are better ways to do it.
Monkey Patching
You asked about this question: Rails (or Ruby): Yes/No instead of True/False.
# ./app/lib/extensions/true_class.rb
class TrueClass
def yesno
"Yes"
end
end
# ./app/views/items/index.html.erb
<%= myboolean.yesno %>
This is called "monkey patching" a Ruby class. In general it's not a good idea for doing what you're trying to do. Why not? Because it breaks an existing Ruby class to force that method into all of your code. This may be OK in rare cases (IMHO) but definitely not for monkey patching view text into a logic class (again IMHO).
How about a migration data type?
You have the right general idea about creating your own migration data type, yet it may be overkill for your case because a boolean is such a typical one-to-one match for a yes/no. When would you want to create your own type? For example if you wanted to store the yes/no using different database primitive types, such as a using a bit flag in one database vs. a string enum in another database.
Decorators
A decorator is a general concept for any app. In Rails, a decorator is a way to add view logic to an existing model or class.
The Rails locales are essentially decorators.
For more advanced needs, there's a good decorator gem called "Draper" which is easy to use. Using decorators tends to help view code be well organized, well namespaced, and easier to test.
Rails (or Ruby): Yes/No instead of True/False
No such built-in helper exists, but it's trivially easy to implement:
class TrueClass
def yesno
"Yes"
end
end
class FalseClass
def yesno
"No"
end
end
Show booleans in Active Admin as 'Yes' and 'No'
Here, this works, it gives you a tick and cross, but appears to be easy to modify.
https://gist.github.com/2574969
You'll need to restart your rails server for this to work, as it modifies the active_admin.rb initialiser.
Of course it creates a class, which is what you want to avoid, but in the absence of anything else, this does work.
Rails model - change true to yes
You can fetch and override the is_value
method on the returned records. This would be ok if you are only fetching the records for display purposes and you know that is_value
won't be used in any other context.
module TrueToYes
def is_value
super ? "Yes" : "No" # Assuming is_value on MyModel is a boolean
end
end
# For a collection
decorated_models = MyModel.all.map{|model| model.extend(TrueToYes) }
decorated_models.first.is_value # => 'Yes'
# Single Record
my_model = MyModel.first
my_model.is_value # => true
my_model.extend(TrueToYes)
my_model.is_value # => 'Yes'
Replace output of true and false in a view with Rails
<%= @attribute ? 'Yes' : 'No' %>
A nice place to put this might be in the model, so
class Whatever < ActiveRecord::Base
def something_yn
attribute ? 'Yes' : 'No'
end
end
And then in the view:
<%= @instance.something_yn %>
CSV export changing a boolean column from true/false to yes/no
I was able to do this by replacing
d.attributes.values_at(*DataPoint.data_point_columns)
with:
def to_csv(data)
CSV.generate do |csv|
csv << DataPoint.data_point_columns
data.all.each do |d|
percentage = d.percentage ? "Yes" : "No"
csv << [d.id, d.category, d.subcategory, percentage]
end
end
end
def data_point_columns
["id", "category", "subcategory", "percentage"]
end
Rails how to use a select list for a boolean field?
In Rails, false is considered blank. You can try on your rails console:
You should remove the presence validation, and set the field to default to false. Or, since it's a boolean, consider true as true, and false or nil as false.
Displaying boolean values from database in the view with Rails
This can be achieved by using a helper. The first argument after the "?" is the true case; the false case follows the ":".
The example below uses glyphicons, since you mentioned wanting a check mark, but you could insert "Yes" and "No" or any string or html you desire.
def bool_to_glyph(value)
value ? "<span class='glyphicon glyphicon-ok' aria-hidden='true'></span>".html_safe : "<span class='glyphicon glyphicon-remove' aria-hidden='true'></span>".html_safe"
end
To display the result, invoke in your view as
<%= bool_to_glyph(table_boolean_value) %>
Note: For a simple string display, like "yes" and "no" you do not need to invoke html_safe.
value ? "yes" : "no"
Edited: Helper methods
Helper methods are included under app/helpers/[modelnameplural]_helper.rb
module ExamplesHelper
def bool_to_glyph(value)
value ? "<span class='glyphicon glyphicon-ok' aria-hidden='true'></span>".html_safe : "<span class='glyphicon glyphicon-remove' aria-hidden='true'></span>".html_safe"
end
end
If you want the helper to be available to all controllers, add the method to the application_helper.rb.
Correct way to check against boolean values in Rails
Different databases store booleans in different ways. Mysql stores them as 0
or 1
. These are translated into false
and true
by rails. Generally you you treat them as booleans in your ruby code.
This code
if is_admin == true
is redundant. you might as well just say
if is_admin
since the result will be the same either way.
Related Topics
How to Best Handle Per-Model Database Connections with Activerecord
Deploy a Shell Script with Ruby Gem and Install in Bin Directory
Rails 4 Devise 3.1.1 Actioncontroller::Unknownformat in Devise::Registrationscontroller#New
How to Override Gemfile for Local Development
Rails Generate Error: No Such File or Directory - Getcwd
Regular Expression Matching Emoji in MAC Os X/Ios
Ruby on Rails: Search Form - Multiple Search Fields
Bundle Install/Error in Installing Libv8 (3.3.10.4) on Rails (Running on Lion)
How to Increment/Decrement a Character in Ruby for All Possible Values
Understanding Precedence of Assignment and Logical Operator in Ruby
Programmatically Derive a Regular Expression from a String
How to Shorten a Uuid to a Specific Length
Semifixed: Missing 'Secret_Key_Base' for 'Production' Environment
Get an Array from a Rails Form
Can Someone Please Explain Class << Self to Me