I have a system which handles reservations. I am writing the UI for a user to select a start and end date which is submitted to the rooms controller and returns all available rooms for those dates. I'm struggling with
The actual form
Processing the dates in the rooms controller.
Having used form_for a lot, I know how datetime_select works, but using form_tag I can't seem to find how to implement the same thing.
Also, it looks as though using datetime_select :year, :start_year passes the date to the controller in 5 parameters, which is going to be messy to parse.
I wonder if I configure the form properly, the controller will know how to parse the date natively and automatically solve the second problem
Thanks for your help!
Check out this answer if I understand your question correctly then you can implement it in the same way as you would using form_for.
Related
I'm making an application that involves booking appointments for users. I have a User model and an AvailableDate model. The user has_many availble_dates and the AvailableDate belongs_to user.
I want to present a form for the user so that they can mark a couple of dates in a calendar and each of the dates they mark will become an AvailableDate object tied to that user.
At the moment my solution is to do all the work that a form_for helper would normally do manually. This involves a lot of javascript and is generally just getting far too messy.
I can't figure out how I should make a form_for tag work when I need to create potentially infinitely many dates. In theory a user could keep marking off dates in the future as available. If I knew how many dates I needed to create for a user, I could do user.available_dates.build, N times. But this doesn't work here.
Can anyone help? It like this problem should be pretty common. Am I designing my application wrong?
One technique is to render the fields for your association once, outside the form.
When the user performs whatever interaction that should create a new set of inputs you use javascript to clone the initial set of fields and insert them into the form. The one thing you need to do is change the name of these inputs so that they are unique. Usually people use the current time in milliseconds for this unique identifier.
Been there & have found several resources to help: Tutorial & Cocoon
The bottom line is you need to ensure child_index is unique for each field. The tutorial I use has child_index: Time.now.to_i to create a truly unique id, consequently allowing you to add as many fields as you want
The best way to do this:
Render fields_for as a partial (passing your form builder object)
When you want to add new field, create ajax_field action
Make ajax_field view have its own form_builder
Both your original & ajax_field forms will call the partial
On front-end, you can use JS to GET new form action & append field to page
I can give you code if you want
I am building an Invoicing application where an Invoice can have various Items.
In the invoice view I have a row like this for every item:
<%= f.text_field :price %>
<%= f.text_field :quantity %>
A new item can be added to an invoice using Ajax, i.e. without resubmitting the page.
This works pretty well.
It would be nice, though, if the total of all the items would get updated through Ajax as well, without the user having to resubmit the page every time.
Can anybody tell me how this can be done?
Thanks for any help.
You should considering using some kind of front end MVC or MVVM framework to handle this. Take a look at knockoutjs:
Simplify dynamic JavaScript UIs by applying the Model-View-View Model (MVVM) pattern
http://learn.knockoutjs.com/#/?tutorial=collections <-- this tutorial shows almost exactly what you would be after.
Basically, you would setup a viewModel that would represent your view which would have a collection of line entries, this would be "observable" which means in knockout language whenever it is changed (added to or deleted from) your binding to it would be updated. For example it could be a with 's bound to each line item.
Then you can have a calculated observable which would update automatically
It depends on your existing code. Do you submit / receive data in JSON format? Try to use some kind of client-side processing (plain javascript, jQuery or other framework).
Or you use more traditional Rails :remote form with js.erb templates? If so, you can update the invoice total in the create.js.erb . Something like (I assume the invoice total is wrapped with a tag with id="total", item belongs_to invoice, invoice has total field)
... # your current code
$("#total").update("<%= escape_javascript(#item.invoice.total)%>");
Same for delete and update actions.
I have a model with a column called start and typed as :datetime.
I would like to be able to calculate how many days there are until the start date and time.
Currently, I have a simple view that does
<%= #myModel.start - Time.now %>
This gives me something like -650.878217378
How can I get it to display days and hours until that date
It seems wrong to be doing this in the view - should I make another instance variable for this calc in my view?
Thanks!
The distance_of_time_in_words / distance_of_time_in_words_to_now view helpers will produce human friendly strings, see the rails docs for examples.
If you are going to be doing calculations like this and the rails provided view helpers don;t meet your needs, I'd write my own view helpers. I don't think there's anything 'naughty' about doing
<%= distance_of_time_in_words_to_now(#myModel.start) %>
I am implementing in Ruby on Rails and I am trying to work with the collection_select, I'm a newbie. I just want to do, I have a list with groups and a list with roles. These are both models. So, I list my groups, and next to that, I have a dropdown list with the role for the group. each group has 1 role.
I implemented some code already, but the collection_select always only remembers the last item. So I want a list with groups, connected with the desired role. But, now I only have 1 item. This is my view:
<% #groups.each do |group| %>
<li>
<%= collection_select('group', 'role_id', #roles, 'id', 'name') %>
</li>
<% end %>
I don't really know what to do now? Someone who knows what I am doing wrong?
Thanks
So, I assume that you're doing a form? What model does the form belong to?
To help debug this sort of thing, usually it'd be a good idea to check your development.log file to see what parameters the form is passing to the controller. Something like:
Parameters: {"commit"=>"Save", "action"=>"update", "_method"=>"put",
"id"=>"6168", "group"=>{"role_id"=>"2", ...}, "controller"=>"groups"}
Now, usually a Rails controller is expecting a form with the data for a single model. If you're wanting to update multiple models or rows at the same time, you're going to have to get creative.
First thing to do might be to try returning an array of groups. Your form at the moment is not using an array. I doubt that these Rails helpers will help you though. Helpers like these are designed to update one ActiveRecord object at once.
It's possible you may need to rethink the design of your app to better fit the Rails way, or roll your own form and iterate over the array that it passes through. Doing it the Rails way is the recommended option, it just might take some brain bending from your end to figure that part out. If you need help, maybe provide more information on what you're actually trying to achieve.
I'm trying to use attr_accessor for a date which normally works fine except when I attempt to use it with the select_date helper method.
Looking at the code behind the helper method I'm guessing it looks for the table column with date type. And in this case since there is no table it's not handling it correctly and I get:
ActiveRecord::MultiparameterAssignmentErrors
"search"=>{"number_of_days"=>"3",
"searchable_id"=>"6933",
"startdate(1i)"=>"2011",
"startdate(2i)"=>"2",
"startdate(3i)"=>"11"}}
Is there a way around this? Or do I need to create some kind of before filter in the controller? I'd prefer doing it on the model level, but I'm not sure how to handle this case? An attr_accessor for each seems a bit over kill. Anyone else have an elegant solution?
attr_accessor fields don't usually get saved when you save/update to the model. How are you updating the model?
Also, you can convert the startdate params to a date object like this :
#start_date = Date.civil(params[:search][:"startdate(1i)"].to_i,params[:search][:"startdate(2i)"].to_i,params[:search][:"startdate(3i)"].to_i)
Check here
select_date is for building the dropdowns which are not associated with a model field (with the idea that you can then pick them up on the other side and do what you want with them). I assume you're meaning date_select which does run off the model?
In any case, as far as I know, long story short, there's no nice and pretty way to get this to work. It's not because of the way the helper works, but because of the way that active record deals with these attributes split into multiple parameters.
In a bit more detail if you're interested, the reason why this doesn't work easily is because when Active Record is dealing with the params you've passed in, it goes through execute_callstack_for_multiparameter_attributes which interprets the keys which have been split into the "date(1i)" style, and mungs them into the applicable class which they should be (a date or time object). The way it works out whether it should create a date or time is by checking it against the type of the attribute (see here), but since an your 'startdate' attribute isn't bound to a particular type, it doesn't get treated as a date or datetime column in the db would.
I think I would deal with it similarly to #Phyo-Wai-Win, but use select_date to set a different param, outside of the 'search' namespace which you then pass into the model as appropriate in the controller. This way, it's not much work, and it means you're not messing with the way you initialize the record or what attributes it expects.
Coming in way late, but in case anyone else stumbles by, the answer for modern rails lies in include ActiveRecord::AttributeAssignment in your model.
This answer did it for me.
I'm a little late here, but I just came across this problem and did not like the top answer. I found a method in the ActiveRecord source called extract_callstack_for_multiparameter_attributes (this is different than the method idlefingers mentioned)
I have the following method in my model. I am calling this method manually but you could probably override update_attributes to run it automatically when you save from the controller. The params argument is actually params[:my_model] from the controller.
attr_accessor :submit_from, :submit_to
def set_dates(params)
dates = extract_callstack_for_multiparameter_attributes(params)
dates.each_pair do |field, date_array|
send "#{field}=", Date.new(*date_array)
end
end