How to access associated object id in ajax loaded form - ruby-on-rails

Using Rails 3.2, how can I access the id of an associated object within an embedded form loaded by ajax?
For example, I have an object called Hotels. Each Hotel has_many Rooms. When I edit a Hotel I would like to add new Rooms to this Hotel using an ajax loaded new Rooms form on the Hotel edit page.
I started by creating all the ajax using jquery on the Rooms index page. Everything works great there, but I don't have a Hotel ID, so I present a Hotel selection dropdown box. Now, I would like to add a new Room directly on the Hotel edit page. I don't understand how to pass the Hotel ID (#hotel.id) to the new ajax loaded Room _form.html.erb partial. On the _form.html.erb partial, I have:
<% if defined?(#hotel.id) %>
<%= f.hidden_field :hotel_id, :value => #hotel.id %>
<% else %>
<%= f.collection_select(:hotel_id, Hotel.all, :id, :name) %>
<% end %>
On the Hotel edit page, I have a link to add a new Room:
<%= link_to 'Add a Room', new_room_path, :remote=>true, :class => 'new_room' %>
And in my rooms_controller.rb I have:
# GET /rooms/new
# GET /rooms/new.json
def new
#room = Room.new
render :partial => 'form', :locals => { :room => #room }
end
How can I get the associated #hotel.id inside my ajax loaded new Room _form.html.erb partial?

Related

Output record id through form builder nested form

I have a model called "loans", which has many :vehicles. The model implementation for loan accepts nested attributes for vehicles through a nested form (provided through simple_form gem).
class Loan < ApplicationRecord
has_many :vehicles
accepts_nested_attributes_for :vehicles
end
.
class LoansController < ApplicationController
def new
#loan = Loan.new
#loan.vehicles.build
end
def edit
#loan = Loan.find(params[:id])
#vehicle = #loan.vehicles
end
end
Edit.html.erb:
<%= simple_form_for #loan, :html => {:class => "loan-edit-form"} do |f| %>
<%= f.simple_fields_for :vehicles do |vehicle| %>
<%= render 'vehicle_fields_edit', :f => vehicle %>
<% end %>
<% end %>
_session_fields_edit.html.erb:
<div class="nested_vehicle" data-id="<%= #vehicle.id %>">
<%= f.hidden_field :id, id: "vehicle_id", name: "vehicle_id" %>
<div class="divider-top"></div>
<div class="vehicle-number">
Vehicle <span class="vehicle-count-rails"><%= f.index + 1 %></span>
</div>
...... etc
</div>
The problem is I'm unable to show the database record ID of the vehicle in the edit nested form as I'm trying to do in the "data-id" attribute since I'm using simple form builder and not simply looping through the loan records using #loan.vehicles.each do |vehicle|.
Using a hidden field I'm able to show the record ID, however, it is shown within an input form field item, whereas I need to retrieve only the ID value alone for use within the data-id attribute.
I've tried <%= f.id %> but get a form builder error. How can I get the record ID whilst using form builder as I've described?
Try this, instead of f.id:
<%= f.object.id %>

How to dynamically add a (HABTM) collection_select + associated text_field in a Rails form?

For a personal invoicing app in rails I could use some advice on the following: In a new invoice form, how to dynamically add a new row consisting of a collection_select for products and an associated text_field for amount by clicking add new product?
Since one invoice has many products and a product has many invoices, I figured this is a HABTM relationship both ways. Therefore I have created the tables invoices, products, and their join table invoices_products.
I would like the invoices/new page to have a form where a user can use a collection_select to pick a product (all products are already preloaded in the products table) and fill in the amount in a text field behind it.
A user should be able to duplicate these two fields (collection_select and text_field) by clicking add new product, something like RailsCast #403 Dynamic Forms 04:50.
Now how would I go about doing that? And in what table would I put the data from the amount text_field, since there are multiple products per invoice so multiple amounts?
Any answer in the right direction will be greatly appreciated!
This depends on how many additional fields you want
A good tutorial for this can be found here
Ajax
The right way would be to add the element dynamically with Ajax
This is tricky because it means you're not going to have the form_builder object available for the dynamically added items. Regardless, you can still do it with this code:
#config/routes.rb
get "new_field_path", to: "invoices#new_item"
#app/views/controller/index.html.erb
<%= ... form %>
<%= link_to "Add Field", new_field_path, remote: :true %>
Controller
#app/controllers/invoices_controller.rb
def new_item
#invoice = Invoice.new
#invoice.products.build
render "new_item", layout: false
end
#app/views/invoices/new_item.html.erb
<%= form_for #invoice do |f| %>
<%= render partial: "products_fields", locals: { f: f } %>
<% end %>
#app/views/invoices/_products_fields.html.erb
<%= f.fields_for :products, child_index: Time.now.to_i do |p| %>
<%= p.text_field :name %>
<% end %>
Form
#app/views/invoices/new.html.erb
<%= form_for #invoice do |f| %>
<%= render partial: "products_fields", locals: { f: f } %>
<%= link_to "Add Field", new_field_path, remote: :true %>
<%= f.submit %>
<% end %>

How to browser multiple file with paperclip in rails4

I have three field
a) email
b) phone number
c) browse files (Here one link `add more file`)
When user click on add more file link then one more browse button appear and so on
I want to save all files when user click on submit button
How Can I do that with paperclip in rails 4
Model
User.rb
has_many invoices
accepts_nested_attributes_for :invoices, :allow_destroy => true
Invoice.rb
belongs_to :user
I have use field_for for invoice in view
controller
def new
#user = User.new
#user.invoices.build
end
def create
User.create(user_params)
end
It looks like your current setup will work well for one file, however if you want to add multiple files, you'll need to build the objects again & load a new fields_for to support that. To do this, I would recommend using Ajax:
I don't know if this will work, but this is how I would tackle the problem:
Put your fields_for into a partial
On your form, include "+" button with :remote => :true
Controller will handle AJAX request & build a new object
On successful AJAX request, load a partial with new fields_for
See if the submit includes all the files
Create fields_for Partial
Your form will likely look like this:
<%= f.fields_for :invoices do |field| %>
<%= field.file_field :image %>
<% end %>
You need to turn this into a partial:
<%= f.fields_for :invoices do |field| %>
<%= render :partial => 'images_fields', locals: {f: field} %>
<% end %>
Your partial could then look like:
<%= f.file_field :image %>
Include "+" Button On Your Form
On your form, you can just create a link like this:
<%= link_to "+", your_controller_action, :remote => :true %>
Controller Will Handle Ajax Request
#app/controllers/your_controller.rb
def new
#user = User.new
#user.invoices.build
respond_to do |format|
format.js { #user.invoices.build }
format.html
end
end
This should render a new object, which you can then append to the form with the returned JS:
#app/views/controller/new.js.erb
$("form").append("<%=j render :partial => 'images_fields', locals: {f: #user} %>")
See If It Submits All The Files
My code probably won't work as it needs debugging. However, this is the process I would use. If you try it, we can debug in the comments
Let me know how it goes!!

Rails ajax form not submitting from within another

I have a Rails 3.2 ajax form that creates a new Room for a Hotel. The new Room ajax form works correctly on the Room index page, but once I embed the new Room ajax form on a Hotel edit page, the form is submitted normally without using Ajax.
To create the new Room form, I use the following link on the Hotel edit.html.erb page:
<%#= link_to 'Add a Room', new_room_path(:hotel_id => #hotel.id), :remote => true, :class => 'new_room' %>
This loads the following form partial on to that same page:
<%= form_for #room, :remote => true, :html => { :class => "remote-form" } do |f| %>
<%= f.text_field :number %>
<%= f.text_field :size %>
<% if(params.has_key?(:'hotel_id')) %>
<% #hotel_id = params[:hotel_id] %>
<%= f.hidden_field :hotel_id, :value => #hotel_id %>
<% else %>
<%= f.collection_select(:hotel_id, Hotel.all, :id, :name) %>
<% end %>
<%= f.submit "Add this room", :class => 'room_create' %>
<%= link_to 'Cancel', '#', :class => "room_cancel" %>
<% end %>
And finally, I have the following in my create.js.erb (inside the rooms folder):
alert('Test creating a room');
var content = $('<%= escape_javascript(render(#room)) %>');
$("#room_list tbody").append(content);
The create.js.erb is not executed and the form is submitted regularly (non-ajax) and I finally arrive on the room show.html.erb page.
Why is the form be working correctly on the Units index page, but not on the associated Hotel edit page?
Even when you set :remote => true, Rails generates a form tag. Nested form tags are not supported by browsers and will result in unpredictable behavior.
You should rethink the views architecture here. Probably you can have the forms for the rooms outside of the form for the hotel, or maybe you can use fields_for and accepts_nested_attributes_for to edit children objects.
Here's a full example on how to use nested attributes: Nested Attributes Examples.
You cannot nest a form inside a form in HTML. When you click any submit button on a form, even if it's inside another form, only the outermost form will be properly submitted.
You can either use nested attributes to add the attributes for the room directly to the form, so that when the overall form is submitted so are all the rooms... or use a div and a link, instead of a form and a submit button.

going against REST conventions in Rails forms

Let me be clearer.
my app has two tables/models: Bikes and Cars
I have a form on page views/cars/index
However, even though the form is in views/cars/index, it has attributes (:pedals and :handlebars) for the Bikes table.
1) Which controller should the form on cars/index with attributes for the Bikes model be submitted to ?
2) What does the form have to look like (in terms of submitting from a view in the Cars index to Bikes model? <%= form_for(#car) do |f| %> OR <%= form_for(#bike) do |f| %>
3) What changes do I have to make to the route when I submit from the index of views/cars/index to insert data into the bikes table? why did I get a missing controller error message when I tried the solution posted by #axsuul
below this line is an earlier (maybe less clear) attempt to explain the problem but i don't think it was clear
this is a form that I have in views/cars/new.html.erb
<%= form_for(#car) do |f| %>
<% if #car.errors.any? %>
and the results are visible in views/cars/show and views/cars/index
However, if I want to submit a form from views/cars/index (Yes I know you don't usually submit from index), and then have it show in a completely different model views/bikes/index, what do I have to change to this?
<%= form_for(#car) do |f| %>
<% if #car.errors.any? %>
If i understand your question right you have a form for creating bikes on your cars/index page.
In that case, create a new bike in the cars controllers index action,
class CarsController < ApplicationController
...
def index
#cars = Car.all
#bike = Bike.new
end
...
end
and use that to create the form,
<%= form_for(#bike) do |f| %>
...
which left like that will be handled by bikes controllers create action.
I still consider this RESTful...
You can choose whatever URL you want to submit to by doing
<%= form_for(#car), :url => create_car_path do |f| %>
for the route
post '/views/cars/index', "cars#index", :as => :create_car
If you are asking to customize which view to render after submitting, you do that in the controller
def index
#car = Car.new(params[:car])
if #car.save
render 'bikes/index'
end
end
Hmm, so from what you explained, you are probably looking for something along the lines of
bikes_controller.rb
def create
#bike = Bike.new(params[:bike])
if #bike.save
redirect_to cars_path and return # this should go back to /cars if successful
end
render 'cars/index' # or render /views/cars/index.html.erb
end
cars_controller.rb
def index
#bike = Bike.new
end
index.html.erb
<%= form_for #bike, :url => create_bike_path do |f| %>
routes.rb
get 'cars' => "cars#index", :as => :cars
post 'cars' => "bikes#create", :as => :create_bike

Resources