How to show a text field based on user's selection? - ruby-on-rails

I have an array
ABC = ["A","B","C"]
<%= f.select :abc, model::ABC, :include_blank => true %>
If I select C, then I want to display an input field for "city" and "state". Otherwise, those fields should be hidden. Is there any simple way of doing this. I don't want to use jQuery or Ajax.

I don't know of a way to change what fields are being displayed without using javascript.
What you could do is always display the city and state fields, but only require them if the select menu is set to C. For example, define a validation rule that requires a field if the select menu is set to C. In your lib/ directory, make require_if_c_validator.rb
class RequireIfCValidator < ActiveModel::EachValidator
def validate_each object, attribute, value
if object.your_attribute_name == 'C' && value == nil
object.errors[attribute] < 'is required'
end
end
end
And then in your model, call it on city and state:
validate :city, :require_if_c => true
validate :state, :require_if_c => true

Related

In RoR, how do I initialize fields in my model based on a field in my model that has no underlying database column?

I’m using Rails 4.2.7. I have an attribute in my model that doesn’t have a database field underneath it
attr_accessor :division
This gets initialized when I create a new object.
my_object = MyObject.new(:name => name,
:age => get_age(data_hash),
:overall_rank => overall_rank,
:city => city,
:state => state,
:country => country,
:age_group_rank => age_group_rank,
:gender_rank => gender_rank,
:division => division)
What I would like is when this field gets set (if it is not nil), for two other fields that do have mappings in the database to get set. The other fields would be substrings of the “division” field. Where do I put that logic?
I'd probably drop the attr_accessor :division and do it by hand with:
def division=(d)
# Break up `d` as needed and assign the parts to the
# desired real attributes.
end
def division
# Combine the broken out attributes as needed and
# return the combined string.
end
With those two methods in place, the following will all call division=:
MyObject.new(:division => '...')
MyObject.create(:division => '...')
o = MyObject.find(...); o.update(:division => '...')
o = MyObject.find(...); o.division = '...'
so the division and the broken out attributes will always agree with each other.
If you try to use one of the lifecycle hooks (such as after_initialize) then things can get out of sync. Suppose division has the form 'a.b' and the broken out attributes are a and b and suppose that you're using one of the ActiveRecord hooks to break up division. Then saying:
o.division = 'x.y'
should give you o.a == 'x' but it won't because the hook won't have executed yet. Similarly, if you start with o.division == 'a.b' then
o.a = 'x'
won't give you o.division == 'x.b' so the attributes will have fallen out of sync again.
I see couple of options here
You can add it in your controller as follows
def create
if params[:example][:division]
# Set those params here
end
end
Or you can use before_save In your model
before_save :do_something
def do_something
if division
# Here!
end
end

Rails inclusion validations

I'm struggling to get a inclusion validation to work on a model so maybe some one could tell me what I'm missing here.
This is the model I have:
class Order < ActiveRecord::Base
ORDER_TYPES = %w{ Verkooporder Retourorder }
ORDER_TYPES.each_with_index do |meth, index|
define_method("#{meth}?") { type == index }
end
validates_inclusion_of :order_type, :in => %w{ Verkooporder Retourorder }
...
I also created a form that creates a dropdownbox using the constant array like this:
(I'm
= f.input :order_type, as: :select, collection: Order::ORDER_TYPES, label: 'Order type', include_blank: false
And I save it to my model like this:
#order.order_type = params[:order][:order_type]
So when I save my order model it always fails on validating the order_type.
Is there anybody who can point me out what I'm doing wrong?
PS: The order_type is an integer value field in my model.
The problem is that you are defining methods Verkooporder? and Retourorder?, but they're not being called from your validation because the :in is interpreting %w{ Verkooporder Retourorder} as an array of strings, i.e. [ "Verkooporder", "Retourorder"].
What you actually want to validate is that order_type is a number between 0 and the size of the ORDER_TYPES array, i.e. a string with a value between 0 and 1:
validates_inclusion_of :order_type, :in => %w{ 0 1 }
In this case you don't really need to define the boolean Verkooporder? and Retourorder? methods, unless you need them elsewhere.
UPDATE:
I realize now that your form will return order_type as a string in Order::ORDER_TYPES, which won't work with the validation above since the validation above is validating on integer-valued strings.
The way I've done this in the past is not to use an integer for order_type but a string. In that case, you can just validate with validates_inclusion_of :order_type, :in => ORDER_TYPES, and the select drop-down doesn't have to change. Is there any particular reason you're using an integer value field for order_type? Alternatively you could have the select return integer values for each order type.

Rails Admin modify list/show view to add new/customized column

I have setup the rails_admin for the admin interface of my site.
For one of the Model, I want to display an additional column.
say i have name , phone , email, image url, rank etc attributes in my Model(say Student).
Then I have to display columns : Name | Rank | Preview(additional column)
In the preview column i want to display some rendered html on the basis of attributes ( email,image,url etc.) for each 'student'.
I have found the way to include a partial for edit/update/create to provide fields/forms as per our partial. But the same implementation of including partial is failing in list/show.
So is there any way I can add the partial to show rendered content, in list/show view for a model...?
Edit: Code added
config.model Utility do
list do
field :code
field :priority
field :name
field :url
field :phone
field :logo
field :content
sort_by :priority
items_per_page 100
end
end
This shows up following columns in rails_admin
Code | Priority | Name | Url | Phone | Logo | Content
what i want is
Code | Priority | Preview
in which in Preview column i want to show a html rendering content as :
blah.html (just for e.g. html for example , here i want to render in a way it is displayed in one of pages, so it is presentable for admin view too)
<div class="blah">
<%=util.name%> <%=util.phone%> <%=util.logo%> #usage with proper divs/tags/rendering
</div >
config.model Utility do
configure :preview do
pretty_value do
util = bindings[:object]
%{<div class="blah">
#{util.name} #{util.phone} #{util.logo}
</div >}
end
children_fields [:name, :phone, :logo] # will be used for searching/filtering, first field will be used for sorting
read_only true # won't be editable in forms (alternatively, hide it in edit section)
end
list do
field :code
field :priority
field :preview
end
show do
field :code
field :priority
field :preview
end
# other sections will show all fields
end
Abstract:
Show/list don't use partials for output. Last overriding point is pretty_value.
Rails Admin calls these "virtual" field types. The easiest way is to make a method on your model, and then refer to it it in your list / show:
class ModelName < ActiveRecord::Base
def invite_link
%{invite link}.html_safe
end
rails_admin do
configure :invite_link do
visible false # so it's not on new/edit
end
list do
field :name
field :invite_link
end
show do
field :name
field :invite_link
end
end
end
class Utility < ActiveRecord::Base
def preview
name
end
end
config.model Utility do
configure :preview do
pretty_value do
util = bindings[:object]
%{<div class="blah">
#{util.name} #{util.phone} #{util.logo}
</div >}
end
children_fields [:name, :phone, :logo] # will be used for searching/filtering, first field will be used for sorting
read_only true # won't be editable in forms (alternatively, hide it in edit section)
end
list do
field :code
field :priority
field :preview
end
show do
field :code
field :priority
field :preview
end
# other sections will show all fields
end
class ModelName < ActiveRecord::Base
rails_admin do
list do
field :job_title
field :required_experiance
field :salary
field :technical_skills
field :non_technical_skills
end
create do
field :job_title, :enum do
help 'Please select Job Title'
enum do
['Business Analyst', 'Trainee Business Analyst', 'Mobile/Web Developer',
'iOS Developer', 'Graphic Designer', 'System Administrator', 'Content Writer']
end
end
field :job_type do
help 'e.g. Developer, Management'
end
field :undergraduate_degree, :enum do
help 'Please select UG Degree'
enum do
[ 'BE', 'BCA', 'B.Tech','BCs', 'BSc', 'BBA', 'BA', 'BCom', 'BSL']
end
end
field :postgraduate_degree, :enum do
help 'Please select PG Degree'
enum do
[ 'ME', 'MCA', 'M.Tech', 'MCs', 'MSc', 'MBA', 'MCM', 'MMM', 'MA', 'MCom']
end
end
field :required_experiance, :enum do
help 'Please select Year'
enum do
[ 'Select Year', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
end
end
end
end

Does Rails have a way to convert checkboxes from "on" to true?

When a controller receives the params of a checked checkbox it comes back as "on" if the box was checked. Now in my case I'm trying to store that value as a boolean, which is typically what you want to with values from checkboxes. My question is, does rails have a way to automatically convert "on" (or even exists) to true/false or do I need to do the following?
value = params[my_checkbox] && params[my_checkbox] == "on" ? true : false
You can just use:
value = !params[:my_checkbox].nil?
as the checkbox would not return any value if not checked (implied by this forum)
The best way of doing this is to create a custom setter for the field in the database, something like this:
class Person < ActiveRecord::Base
def active=(value)
value = value == 'on' ? true : false
super(value)
end
end
That way you don't have to worry about it in the controller and it's the model that knows what value it is supposed to be. When you go to the view rails automatically checks a checkbox from a boolean field. Just in case that didn't work you could also define your own getter.
This can be then used for example in conjunction with store accessor something like this:
class Person < ActiveRecord::Base
validates :active, inclusion: {in: [true, false]}
validates :remember_password, inclusion: {in: [true, false]}
store :settings,
accessors: [:active, :remember_password],
coder: JSON
def active=(value)
value = value == 'on' ? true : false
super(value)
end
def remember_password=(value)
value = value == 'on' ? true : false
super(value)
end
end
Note that the setting field in the database has to be text so you can put more stuff in it.

Getting the value from an array in the model in rails

I have a relatively simple problem. I have a model named Item which I've added a status field. The status field will only have two options (Lost or Found). So I created the following array in my Item model:
STATUS = [ [1, "Lost"], [2, "Found"]]
In my form view I added the following code which works great:
<%= collection_select :item, :status, Item::STATUS, :first, :last, {:include_blank => 'Select status'} %>
This stores the numeric id (1 or 2) of the status in the database. However, in my show view I can't figure out how to convert from the numeric id (again, 1 or 2) to the text equivalent of Lost or Found.
Any ideas on how to get this to work? Is there a better way to go about this?
Many thanks,
Tony
You can define a method in your Item model:
class Item < ActiveRecord::Base
#
def status_str
Item::STATUS.assoc(status).last
end
end
And use it:
item.status_str # => "Lost" (if status == 1)
Or you can check out enum_fu plugin:
class Item < ActiveRecord::Base
#
acts_as_enum :status, ["Lost", "Found"]
end
and then item.status gives you string value:
item.status # => "Lost"

Resources