Rails creating multiple entries at once - ruby-on-rails

I am trying to figure out the cleanest way to create multiple DB entries at once (or if it's even a good idea).
I have an Event model, which has many Bands and many Venues, through the event_bands and event_venues models.
Right now, the user first creates the event, then is redirected to the form to create the event_band and event_venue relationships. I would like to streamline all of this into one form if possible, like this (bottom lines are most relevant):
<%= form_for #event do |f| %>
<%= f.label :name %>
<%= f.text_field :name %><br />
<%= f.label :contact %>
<%= f.text_field :contact %><br />
<%= f.label :price %>
<%= f.text_field :price %><br />
<%= f.label :info %>
<%= f.text_area :info %><br />
<%= f.label :date %>
<%= f.date_select :date, start_year: 2014 %><br />
<%= f.label :time %>
<%= f.text_field :time, placeholder: "7:40pm" %><br />
<%= f.label :band %>
<%= select(:event_band, :band_id, options_for_select(Band.order(name: :asc).collect { |b| [b.name, b.id]} )) %><br />
<%= f.label :venue %>
<%= select(:event_venue, :venue_id, options_for_select(Venue.order(name: :asc).collect { |v| [v.name, v.id]} )) %><br />
<%= f.submit %>
<% end %>
Because the event_band and event_model require event.id, I guess I would have to use an after_create callback to build and save them. The issue I'm having conceptualizing this is that I want to post those extra :band_id and :venue_id params through the form for the event.
Is there a cleaner way to handle posting params for multiple models through one form and then using them in a callback or am I headed in the wrong direction?

You can use fields_for : see doc

Related

Carrierwave Rails with Edit Form and file_field (No file selected)

When my edit view loads, all my fields are populated with the record detail, but the file_field shows "No file Selected" next to the browse button. I would prefer that is show the record file name instead. Why does it not show that a file that was uploaded?
Edit View
<%= form_for #document, :html => {:multipart => true} do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :file, "File" %><br />
<%= f.file_field :file %><br />
<%= f.hidden_field :file_cache %><br />
<%= f.label :name, "name" %><br />
<%= f.text_field :name %><br />
<%= f.label :memo, "memo" %><br />
<%= f.text_area :memo %>
</p>
<%= f.hidden_field :folder_id %>
<p><%= f.submit "Upload" %></p>
<% end %>
I think a good counterquestion is "why should show an uploaded file by default?".
But basically is because security reasons and none of the browsers (yep, nothing to do with rails) is going to allow that, so you must to indicate manually to the user about the uploaded files.

How to add CarrierWave uploader to Devise registration view? (rails gems)

When users register, I want them to be able to upload an avatar. The new registration .html.erb looks like this:
<h2>Sign up</h2>
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => {:multipart => true} ) do |f| %>
<%= devise_error_messages! %>
<div>
<%= f.label :username %><br />
<%= f.text_field :name %>
</div>
<div>
<%= f.label :image %><br />
<%= f.file_field :image %>
</div>
<div><%= f.label :email %><br />
<%= f.email_field :email %></div>
<div><%= f.label :password %><br />
<%= f.password_field :password %></div>
<div><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %></div>
<div><%= f.submit "Sign up" %></div>
<% end %>
<%= render "links" %>
User.rb:
class User < ActiveRecord::Base
....
mount_uploader :image, ImageUploader
ImageUploader exists...
When I try to visit the view, it tells me that User::ImageUploader doesn't exist. When I try to specify the fully qualified name of the class in the user model, either as an 'include' statement or as an argument to the mount_uploader function, it can't find that either. Do I need to somehow build in a separate form_tag in that view? I'm sure this has been done before. Any help is appreciated.
Have you:
Added an :image column to your User model?
Defined the uploader app/uploaders/image_uploader.rb?
Restarted your server?
You shouldn't need to have this as a separate form tag, as long as the image attribute exists on the User model.
You may need to check your form markup. I notice you have :username on the label and :name on the field.
Try changing:
<%= f.label :username %><br />
<%= f.text_field :name %>
to
<%= f.label :name, "username" %><br />
<%= f.text_field :name %>

Multiple Checkboxes, Convert to String, Single DB Column Rails

I have a form, that among other things, contains about 20 different checkboxes. Like so:
<%= form_for #inventory do |f| %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
...
<p>
<%= f.check_box :apple %><%= f.label :apple %><br />
<%= f.check_box :banana %><%= f.label :banana %><br />
<%= f.check_box :orange %><%= f.label :orange %>
...
</p>
...
<% end %>
What I want to do is take the value of the selected checkbox, comma delimit them, and save them in a column in the db. So if the apple and orange checkbox is checked it saves as:
#inventory.fruit = "apple, orange"
how do I do this?
I don't think we can send multiple values as a string rather than an array. Look at the below solution
In Rails, how to handle multiple checked checkboxes, just split on the , or?
The solution is in pure HTML code but you can use check_box_tag instead.

How to create only the field_for object in a nested form

I have a nested form where users can create any amount of products (<%= f.fields_for :products do |product| %>) and at the same time also create a location (nested_form_for #location) to put those products. But instead, what i want is users to select a location and only be allowed to create the products. I don't want to create the locations at all on this form. The form also should not give a location per product but only one location for all of them.
How would you make the form select a location and create products only ?
This form creates both the location and X amount of products:
<%= nested_form_for #location, :validate => true do |f| %>
# This will turn into selecting of predefined locations and not creating
# the location as you see below this line
<%= f.label :business_name, "Business Name" %><br />
<%= f.text_field :business_name %>
<%= f.label :address %><br />
<%= f.text_field :address %>
<%= f.label :phone_number, "Phone Number" %><br />
<%= f.text_field :phone_number %>
<%= f.label :website %><br />
<%= f.text_field :website %>
</div>
<%= f.fields_for :products do |product| %>
<%= product.label :name %>:<br>
<%= product.text_field :name %>
<%= product.label :price %>:<br>
<%= product.text_field :price %>
<%= product.link_to_remove "Remove" %> # Removes a product field
<% end %>
</div>
<p><%= f.link_to_add "Add Product", :products %></p> # Ajax add product field
<div class="actions">
<%= f.submit %>
</div>
<% end %>
If I understand you correctly, you want users to choose from a list of locations, and then add products to that location. These locations are predefined somewhere (I'm getting in your db_seed) in your application. Assuming those two things, then the question to your answer is just have a normal form_for #product and inside your form you will have a select with the option objects being the location where they users can choose.
<%= form_for #product do |p| %>
<%= p.label :name %>:<br>
<%= p.text_field :name %>
<%= p.label :price %>:<br>
<%= p.text_field :price %>
<%= select :product, :location_id, Location.all.collect {|l| [ l.business_name, l.id ] } %>
<% end %>
and in your controller you can just get the location with params[:product][:location_id] to retrieve the location the user selected and do your normal database stuff. Hopefully that's clear enough for you.
If you want to create more than one product at a time, you need to use a form_tag and generate your own helpers to add/remove products. This is more difficult but creates a better user experience.

Rails - User Input for Multiple models on a single form - How

This is basically a nested form question, albeit with only one field that belongs to a parent model. My data entry form collects data for a model - however I also need to collect one other a data element/value (UserID) that actually goes into a parent record that will be created with the detail record.
AFAIK Rails expects each form field to map to a model and I need to create an unbound data input field that I will use separately.
How can I override this default behaviour and create a'free form/unbound field'?
TIA,
BC
Heres something from my own app:
Access it by:
params[:company] and params[:user]
Controller:
#company = Company.new
#user = User.new
View:
<% form_for #company, :url => companies_path do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<p>
<%= f.label :website %><br />
<%= f.text_field :website %>
</p>
<hr />
<% fields_for #user do |u| %>
<p>
<%= u.label :email %><br />
<%= u.text_field :email %>
</p>
<p>
<%= u.label :username %><br />
<%= u.text_field :username %>
</p>
<p>
<%= u.label :password %><br />
<%= u.password_field :password %>
</p>
<p>
<%= u.label :password_confirmation %><br />
<%= u.password_field :password_confirmation %>
</p>
<% end %>
<p>
<%= f.submit "Submit" %>
</p>
<% end %>
For the "magic" form <=> model mapping form_for is used. (http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html)
If you need something out of the current model try using http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html
With that you can add tags separate from the model, eg
radio_button_tag
inside the form_for block

Resources