Im trying to set up a bookings form where people can book services. Within the Service model there is a duration set and I want to use this to automatically populate the end_time. For example, if I book a 60 minute service at 2017-03-22 1PM I want the end time to be set at the same day but one hour later. Is it possible to send this in with a form?
<%= form_for([service, service.bookings.new]) do |f| %>
<div class="row">
<div class="col-sm-12">
<%= hidden_field_tag "recipients", #user.id %>
<div class="form-group">
<%= label_tag 'Available times' %>
<%= f.datetime_select :start %>
<%= f.hidden_field :end, value: Time.at([:start].to_i + service.duration) %>
<%= f.hidden_field :service_id, value: service.id %>
<%= f.hidden_field :price, value: service.price %>
</div>
<%= submit_tag 'Book', class: 'btn btn-complete btn-lg btn-large btn-block' %>
</div>
</div>
<% end %>
I've tried with above but get
undefined method `to_i' for [:start]:Array
which I guess is because :start is not yet saved and renders nil.
Any ideas on how to solve this?
Thanks a lot
[:start] is just return an Array contain symbol, and you can not get anything.
You should create end_time in controller or model when you got the start_time, or other way is using the javascript code get end_time when type start_time in the form
Consider not doing business logic in a view. Send these params and set the end variable in model or controller.
Why does your code not work?
datetime_select returns a set of select tags (one for year, month, day, hour, and minute).
Related
I have a form created using form_with. What I need is to retain the values submitted using that form after page reload. I am able to save the value of text_field but not the value of check_box. What should I change in my code so that I can achieve the same?
html.erb
<%= form_with url: search_path,
id: :search_by_filter,
method: :get, local: true do |f| %>
<div>
<p><strong>Search by Name</strong></p>
<%= f.label 'Name' %>
<%= f.text_field :name, value: params[:name] %>
</div>
<br>
<div>
<%= label_tag do %>
<%= f.check_box :only_students, checked: params[:only_students] %>
Show only students
<% end %>
</div>
<br/>
<div class="submit_button">
<%= f.submit :Search %>
</div>
<% end %>
controller.rb
def get_desired_people(params)
people = Person.includes(:country, :state, :university).order(id: :desc)
people = people.where(is_student: params[:only_students]) if params[:only_students]
people = people.where(name: params[:name]) if params[:name].present?
people
end
Here I am able to retain the value of params[:name] but not the value of params[:only_students]. It always remains unchecked after form submission. How can I retain the checked and unchecked value?
f.check_box check_box_tag is expecting checked to by boolean value, and every param is a string (string is always evaluated to true if exists) so you should do:
checked: params[:only_students].present?
you don't have to worry about a value of param, as unchecked params are not send while posting.
EDIT:
above works for check_box_tag.
f.check_box is tricky, you should carefully read description: https://api.rubyonrails.org/classes/ActionView/Helpers/FormBuilder.html#method-i-check_box
The behaviour you described seems pretty correct, you can deal with it or switch to check_box_tag as a better option when not updating model attributes
All the solutions above did not work for me. Try this:
<%= check_box_tag :only_students, true, params[:only_students] %>
I'm very new to ruby on rails. I'm trying to make a text field to assign one of my variables (end_date), but I keep getting this error:
undefined method `end_date' for #<Quiz:0x007fccd1e0f9c0>
Here's my code:
<%# Main Canvas where cardes places %>
<div class="column large-11" id="main">
<%= form_for #quiz do |q| %>
<%= q.label :quiz_name %>
<%= q.text_field :quiz_name %>
<%= q.label :end_date %>
<%= q.text_field :end_date %>
<%= hidden_field_tag 'selected', 'none' %>
<%= q.hidden_field :classroom_id, value: #classroom_id%>
<%= q.submit "Create Quiz", class: "expanded button" %>
<% end %>
<%= form_tag("/quiz/#{#classroom_id}/copy", method: "get") do %>
<%= label :id, "ID" %>
<%= text_field_tag "id", "" %>
<%= submit_tag "Copy Quiz By ID", class: "expanded button" %>
<% end %>
</div>
Let me break down how these different pieces relate to one-another, which hopefully will make this easier for you to troubleshoot.
<%= form_for #quiz do |q| %>
Here you are invoking form_for to create a form bound to the #quiz object. It yields a form builder object as the argument q.
<%= q.text_field :quiz_name %>
Here you are calling the text_field method on the form builder with the field named quiz_name. This means it will generate a text input, and call the quiz_name method on #quiz to find the current value.
So given that background, it should be clear why you are seeing this error:
<%= q.text_field :end_date %>
You are telling the form builder to call #quiz.end_date for the value of this field, but that method does not exist.
You have not given enough code samples for us to determine why you expect this method to exist. Perhaps this is a field you've added to the quizzes table, but haven't yet run the migration? Is this supposed to be a virtual attribute on Quiz? Or perhaps you just want to send a field that isn't connected to the Quiz model inside this form. (You can do that with a separate set of helpers, in this case text_field_tag, that give you more flexibility in where the data comes from).
I have a field called delivery_day which is of type string in delivery_preference model.
In form, I want to provide 7 checkboxes for each day like Sunday,Monday,etc., and later want to concat.
For example if a user checks Sunday and Friday, I want to concat & store it as "Sunday,Friday" in delivery_day field.
Thanks in Advance!!
You can design your form like this -
<%= form_for #delivery_preference do |f|%>
<%= f.check_box :delivery_day, {multiple: true}, "Sunday" %>Sunday
<%= f.check_box :delivery_day, {multiple: true}, "Monday" %> Monday
<%= f.submit "Add" %>
<% end %>
After submitting the form, you can get your check box selections in your controller as follows:
def your_action_name
params[:delivery_preference][:delivery_day].delete("0")
DeliveryPreference.create(delivery_day: params[:delivery_preference][:delivery_day].join(","))
end
Hope it helps!
Might have better solutions, but when I encountered similar problem, I used check_box_tag to solve it.
<%= check_box_tag "delivery_preference[delivery_day][0]", 'monday' %>Monday
<%= check_box_tag "delivery_preference[delivery_day][1]", 'tuesday' %>Tuesday
<%= check_box_tag "delivery_preference[delivery_day][2]", 'wednesday' %>Wednesday
<%= check_box_tag "delivery_preference[delivery_day][3]", 'thursday' %>Thursday
<%= check_box_tag "delivery_preference[delivery_day][4]", 'friday' %>Friday
<%= check_box_tag "delivery_preference[delivery_day][5]", 'saturday' %>Saturday
<%= check_box_tag "delivery_preference[delivery_day][6]", 'sunday' %>Sunday
then you will receive an array like { deliver_day: ['monday', 'tuesday'] } in you controller. You can choose to concat in your controller, and then save, or you can move the logic to your model.
in your controller, you strong parameter should be like
params.require(:delivery_preference).permit(.., :deliver_day => [])
to permit the array.
I do not have enough reputation to leave a brief comment yet. However, does your migration have delivery_day have something similar to t.boolean :public, default: true_or_false_here within it?
If so, within the form, you could have something like:
...
<div class="form-group">
<%= f.label :public, class: 'checkbox' do %>
<%= f.check_box :public %> Monday
<% end %>
</div>
<div class="form-group">
<%= f.label :public, class: 'checkbox' do %>
<%= f.check_box :public %> Tuesday
<% end %>
</div>
...
After above, you could designate (via boolean logic) your "concat & store it as "Sunday,Friday"
I want to pass several params in the url of the current page with a form_tag but I have failed to understand to correct syntax.
Quick explanation: I have outfits (model) that has many outfit_items (model).
Each outfit_item has available_sizes (attribute of outfit_item). All of this is set by the admin.
Then on the show page of an Outfit, (for example http://localhost:3000/outfits/7) I want to display the available sizes for each outfit_item, let the visitor pick his size for each item and press submit. The selected sizes should then appear in the URL.
Here is what I have in my show view, at the url :
<%= form_tag(#outfit_path, :method=>'post') do %>
<% #outfit.outfit_items.each do |outfit_item| %>
<div class="col-md-2 col-sm-6 col-xs-6">
<%= image_tag outfit_item.item_image.url(:medium) %><br>
<% sizes = outfit_item.available_sizes.split(",") %>
<%= select_tag "size#{outfit_item.category}", "<option>#{sizes[1]}</option><option>#{sizes[2]}</option><option>#{sizes[3]}</option><option>#{sizes[4]}</option>".html_safe, :class => "input-mini select-mini" %><br>
<%= hidden_field_tag "size#{outfit_item.category}", value: outfit_item.category %>
</div>
<% end %>
<%= submit_tag "ok size" %>
<% end %>
I want to land on this url when I hit submit
http://localhost:3000/outfits/7?size1=42&size2=L&size3=S&size4=44
Thanks for your help
You could do like this. Hope it helps.
<%= form_tag(#outfit_path, url: your_path(size1: value1, size2: value2, ......) :method=>'post') do %>
I would do it like this:
<%= form_tag(outfit_path(#outfit), :method=>'get') do %>
<% #outfit.outfit_items.each do |outfit_item| %>
<div class="col-md-2 col-sm-6 col-xs-6">
<%= image_tag outfit_item.item_image.url(:medium) %><br>
<% sizes = outfit_item.available_sizes.split(",") %>
<%= select_tag "size#{outfit_item.category}", options_for_select(sizes), :class => "input-mini select-mini" %><br>
<%= hidden_field_tag "size#{outfit_item.category}", value: outfit_item.category %>
</div>
<% end %>
<%= submit_tag "ok size" %>
<% end %>
Some assumptions:
Notes:
outfits_path(#outfit) would normally (from convention) be "/outfits/<outfit id>", so that's what i've used here - this is what i'd expect from convention
If you want to land on the url, ie make it public, you should make it a GET request, not a post request. so i've changed the form to make a GET request
you've got a hidden_field_tag in there. This will show up in
your url as well, so it's impossible to get the exact url you desire
AND have the hidden field tag in there.
options_for_select(sizes) is a much nicer way of generating a bunch of option tags
I get the feeling that there's a much nicer way to do what you're trying to do here, but without knowing more about your schema i can't say what.
Rails newbie here.
I have 2 models: Target and Observation
Target works fine. I generated scaffolding for Observation, like this:
rails generate scaffold Observation date:date target:references
So app/models/observation.rb says:
class Observation < ActiveRecord::Base
belongs_to :target
end
Then I edited app/models/target.rb:
class Target < ActiveRecord::Base
has_many :observations
end
The scaffolding created app/views/observations/_form.html.erb which includes:
<div class="field">
<%= f.label :target %><br />
<%= f.text_field :target %>
</div>
And app/controllers/observation_controller.rb which includes:
def create
#observation = Observation.new(params[:observation])
I then go to create a new Observation. I enter a date and the ID of a target in the target field. When I submit, I get this error in the browser:
ActiveRecord::AssociationTypeMismatch in ObservationsController#create
Target(#2190392620) expected, got String(#2148287480)
Seems like the scaffolding would set up something that would work. But the error makes sense. It's receiving the ID of the Target instead of the Target itself. So I edited app/controllers/observation_controller.rb to say:
def create
#target = Target.find(params[:observation][:target])
#observation = #target.observations.create(:date => params[:observation][:date])
Now it creates the Observation record, with the reference to the Target. But the date field is blank.
I realize this may be a dumb newbie or RTFM question, but I'd really appreciate a pointer in the right direction. Thanks.
Here's the full contents of the form, after changing it to reflect the answer received.
<%= form_for(#observation) do |f| %>
<% if #observation.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#observation.errors.count, "error") %> prohibited this observation from being saved:</h2>
<ul>
<% #observation.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :date %><br />
<%= f.date_select :date %>
</div>
<div class="field">
<%= f.label :target %><br />
<%= f.collection_select :target_id, Target.all, :id, :name %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
change
<%= f.text_field :target %>
to
<%= f.text_field :target_id %>
And really better is to use something like select for this thing. Like:
<%= f.collection_select :target_id, Target.all, :id, :title %>
UPD
As far as date_select helper set not ordinary banch of variables for each element (year, month, day) you shoul do this:
date = [ params[:observation]['date(1i)'], params[:observation]['date(2i)'], params[:observation]['date(3i)'] ].join(".")
#observation = #target.observations.create(:date => date)
Actually just look into HTML source and you'll see it
(Not sure if you are still monitoring this, OP? For the benefit of everyone coming here via Google:)
There will be no params[:observation][:date] because dates are entered using several HTML input fields, and then magically merged in assignment. The keyword for this is "multi-parameter attributes", and this is the best explanation I've found:
How do ruby on rails multi parameter attributes *really* work (datetime_select)
I also wonder if this simpler snippet would work.
#observation = #target.observations.create(params[:observation])
You can use:
<%= collection_select(:observation, :target_id, Target.all, :id, :title %>
i think it will help you.