First question: how to validate a model relation and mark it in form when validation failed.
I have a subject model:
class Subject < ActiveRecord::Base
belongs_to :semester
validates_presence_of :semester
end
In my view (form):
<%= select_tag :semester, options_from_collection_for_select(#semesters,"id","name") %>
The validates_presence_of works fine. But when the validation fails (user forgot to enter semester ). The semester input is not marked in red.
Second question: how to validate an input field.
In my view, I also have a university input field, but model subject has no relationship with university, no field university in subject table. So how to validate it and mark it in red.
Thanks in advance.
If you want to get the fields with error displayed in red "out of the box", you must use a form builder. The code will looks like f.select ... instead of using select_tag.
With the form builder, the fields with errors are created inside a <div class="field_with_errors">...</div>. The css file generated by scaffolding displays these fields in red; if you're not using it, you must add the css rules to your css.
# app/models/subject.rb
class Subject < ActiveRecord::Base
belongs_to :semester
validates :semester, :university, presence: true # new syntax http://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validates
end
# app/views/subjects/_form.html.erb
<%= form_for #subject do |f| %>
Semestr: <%= f.collection_select :semester_id, Semestr.all, :id, :name, prompt: true %>
University: <%= f.text_field :univercity %>
<% end %>
For more information about building forms in rails (with validations enabled) you could find there http://api.rubyonrails.org/classes/ActionView/Helpers/FormBuilder.html
Those "red errors" that you hope for are probably coming from a form helper gem like formtastic, feel free to check that out.
I have literally no idea what your second question is asking, but if you're looking for a custom validation. Check out the rails docs on them for help.
If you'd like more help, (please) edit your question to be more clear (thanks)
Related
I have a form and I have made some inputs required. After submitting the form that value will be sent to an API. I know that the validations are put into model file but since I do not have a database, how can I use the rails validation?
Right now I am validating the code inside a controller using if else.
if !params[:groups][:name].blank? && !params[:groups][:make].blank? && !params[:groups][:model].blank? && !params[:groups][:firmware].blank?
This does the work but it is not very elegant.
Take a look at ActiveModel, it lets you do "model things" without the database. There were some limitations that made me not use it in the end (I think related to associations) but for simple stuff it's great (and it's a part of how ActiveRecord works.
Example code from docs
class Person
include ActiveModel::Model
attr_accessor :name, :age
validates :name, :age, presence: true
end
this is easy. On the form input fields that you NEED, add required: true For example:
<%= form.for #something do |f| %>
<%= f.text_field :title, placeholder: 'Title', required: true %>
<% end %>
The user gets an error if the required fields are not filled out correctlty.
Is this what you mean?
Justin
EDIT
I guess I would look at using the gem
client_side_validations
Let us know how you go
I have a class Rfsestimation shown below:
class Rfsestimation < ActiveRecord::Base
has_one :rfstaskset
has_one :rfsnote
enum request_type: [:front_end, :back_end, :front_end_and_back_end]
enum band_type: [:Simple, :Medium, :High, :Complex, :VComplex, :Outside_AD]
**accepts_nested_attributes_for :rfstaskset**
**accepts_nested_attributes_for :rfsnote**
validates_presence_of :number, :name, :date_of_estimation, :request_type_id, :band_id, :hours_per_day, :estimated_start_date, :estimated_end_date, :message => "Should be present"
validates_numericality_of :number
end
Please see the two lines for association above marked in bold. I am attempting to create the associated objects, Rfsnote and Rfstask through fields_for shown in below form:
<%= f.fields_for :rfstaskset do |rfs_task| %>
However the fields which are supposed to appear do not appear as expected. But if i use rfstasksets, as below, the form fields appear as expected.
What might be the reason for this?
<%= f.fields_for :rfstasksets do |rfs_task| %>
I think you are not building the associated object in your controller.
You new action need to look like this:
def new
#rfsestimation = Rfsestimation.new
#rfsestimation.build_rfstaskset
end
I am trying to use collection_select tag for the default _form.html.erb using a concern/module, I need to set a hash including some department names.
Here is my app/models/concerns/SetDepartment.rb
module Set_Department
extend ActiveSupport :: Concern
def department
department {
1=>"Amatitlán",
2=>"Chinautla",
3=>"Chuarrancho"
}
end
end
Here is the model where I want to call the department method:
class Aplicante < ActiveRecord::Base
include SetDepartment
validates :titulo_id, :primer_nombre,
:primer_apellido, :dpi, :direccion_linea_1,:zona, :department_id, :username,
presence: true
validates :dpi,:username, uniqueness: true
has_secure_password
end
Now, I need to include this hash in a collection_select tag on my app/views/applicants/_form.html.erb
#...
<div class="field">
<%= f.label :department_id %><br>
<%= f.collection_select :department_id, Aplicante.department, Aplicante.department %>
</div>
#...
Obviously, this does not work but I can not think on anything else.
I have searched through the internet but I just get tough explinations and none of them involves a module... is it even possible?
Solved!
I was using the wrong method..
We can not use a collection_select helper with a hash, instead, we need to use the regular select method.
Collection_select is used when you have two models and you want to combine their different values in a drop down menu.
Information about how to use the select tag with a hash here:
http://apidock.com/rails/ActionView/Helpers/FormTagHelper/select_tag
I have a Product model with many Versions:
class Product < ActiveRecord::Base
attr_accessible :name, :versions_attributes
has_many :versions
accepts_nested_attributes_for :versions, allow_destroy: true
end
class Version < ActiveRecord::Base
attr_accessible :available_q, :kind, :product_id
belongs_to :product
end
I would like to present the available_q attribute to the (admin) user as a select box with the choices of "Yes" or "No", and of course I would like the to have the select box show whatever is currently in the version database for this version, but can't seem to get it to do that. Here is the portion of the view code for the product form involving the select box for the associated model:
<%= form_for(#product) do |f| %>
…
<%= f.fields_for :versions do |version| %>
<%= version.select :available_q, options_for_select([['Yes', 't'],['No', 'f']], version.object.available_q) %><br />
…
<% end %>
…
Everything works well except that the current select box always shows yes even after updating the database with a 'No'. It's likely that I have forgotten to do something very simple, but would very much appreciate any help on this.
<%= version.select :available_q, options_for_select([['Yes', 't'],['No', 'f']], version.object.available_q == 't' ? 0 : 1) %>
You can try the solution above. The second parameter of options_for_select isn't the value to be shown, but the index of the value on the collection array [['Yes', 't'],['No', 'f']].
I have found a work-around: the difficulty I was having seems to have to do with using :available_q which has boolean data type. When I change it to string type, the problem goes away!
I've been trying to work through this for a few days and can't get anything to work. I have been building my first app based on Michael Hartl's amazing tutorial: http://ruby.railstutorial.org/. Additionally, I have tried this tutorial, but the differences in my code and his prove to be too great for me to follow along.
Where my app differs from Michael Hurtl's is that I am trying to create a site where you can post your left over cans of paint (instead of microposts, AKA twitter). When I created the app, I had a column in the Paints model called "color_family". Now I am looking to change it from a text field to a drop down with predetermined values, e.g. "Reds", Oranges", "Yellows", Greens" etc.
I started out by generating a new scaffold:
rails generate scaffold Color_Family family:string
then I generated a migration:
rails generate migration AddColor_FamilyToPaints family_id:int
and migrated it all.
Then I created the associations
class ColorFamily < ActiveRecord::Base
has_many :paints
end
and
class Paint < ActiveRecord::Base
attr_accessible :family_id, :name, :hex, :location, :quantity, :additional_info
belongs_to :user
belongs_to :color_family
...
end
This is where I get lost, and any tutorial I try to follow breaks everything. Where do I define my predetermined list of color_families?
Is it even worth it for me to go through the creation of a new model? I previously tried this in the form field:
<%= form_for(#paint) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.label :color_family %>
<%= select_tag(:color_family, options_for_select([['Red', 1],
['Orange', 2],
['Yellow', 3],
['Green', 4],
['Blue', 5],
['Purple', 6],
['Black', 7],
['Grey', 8],
['White', 9],
['Cream', 10],
['Brown', 12]])) %>
and while it created a dropdown for me, it never captured the info when I added a new paint.
Any help is greatly appreciated. Also, a link to a tutorial would probably do me the biggest help as I've very new to RoR and backend stuff in general.
I'm not sure if you are doing the reading version of the book, or the video. Personally, I recommend both! Absolutely amazing tutorial! One of the first things he does mention though, "Scaffold is not really for the real world" and you should consider this. When I'm doing projects, new old or just refactoring, I usually add everything by hand with the script/generate. The only "scaffold" I've ever used was the scaffold_controller because I was too lazy to do the controller by hand.
The short answer, you should have another model "Color" and the form should:
f.collection_select(:color_id, Color.find(:all), :id, :name, {:include_blank => 'Please Select A Color'})
And the ColorFamily should probably be a has_many_and_belongs_to_many Colors
If you could give me a run down of details associations supposed to be taking place, I can write up a small data modal for you.
Edit #1
You are needing a has_one :through relationship. The general concept will be...
Pivot tabel:
rails g migration ColorFamilyPaints paint_id:integer color_family_id:integer
Paint Class:
class Paint < ActiveRecord::Base
attr_accessible :family_id, :name, :hex, :location, :quantity, :additional_info,
:color_families_attributes # Need to add this in order for you to be able to post with drop down
belongs_to :user
...
# Creates the Relationship
has_one :color_families, :through => :color_family_paints
# Allows color families to be nested in the form.
accepts_nested_attributes_for :color_families, :allow_destroy => true
end
You'll notice a few changes. Addition to the attr_accessible, and the accepts_nested_attributes_for (you may need this, not sure with a has_one though). When you build the form, look at the ID/Name of the select box. If it ends in _attributes, use the accepts line. If not, you don't need it. Alter the :color_families_attributes to match the name of the select box.
Form HTML:
<%= form_for(#paint) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.label :color_family %>
<%= f.collection_select(:color_family, ColorFamily.find(:all), :id, :name, {:include_blank => 'Please Select Color Family'}) %>
</div>
<% end %>
More information on associations # RoR website.