Rails partial form in a form - ruby-on-rails

I have a Rails app with Expenses that belongs_to Vendors.
While the user is adding a new Expense, they might need to add a new Vendor.
I thought I could just add a button and a Vendor partial to the Expense form.
Like this:
<%= simple_form_for #expense, :html => {:class => 'form-horizontal'} do |f| %>
<div class="span5">
<a data-toggle="modal" href="#vendorform">
<p class="pull-right btn btn-primary btn-mini">New Vendor</p></a>
<%= render :partial => "vendors/vendorform" %>
</a>
<%= f.association :vendor, :label_method => :vendor_name, :label => 'Vendor', collection: Vendor.order('vendor_name ASC') %>
The _vendorform.html.erb looks like this:
<div id="vendorform" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="vendorformLabel" aria-hidden="true">
<div class="modal-header">
<a class="close" data-dismiss="modal">×</a>
<h4 id="vendorformLabel">Add Vendor</h4>
</div>
<div class="modal-body">
<%= simple_form_for Vendor.new do |f| %>
(bunch of fields)
</div>
<div class="modal-footer">
<%= f.submit 'Save Vendor', :class => 'btn btn-mini btn-primary' %>
<a class="btn btn-mini" data-dismiss="modal" href="#">Close</a>
<% end %>
</div>
</div>
This partial shows up OK. But, the Vendor record doesn't get created.
The submit of the partial actually somehow triggers the submit for the Expense. The page comes back with all of the required Expense fields red.
I think it's posting to the Expenses controller when the f.submit button in the Vendor partial is pressed !!!
Do I need something in the Expense controller?
Or is there a better way?
Thanks for the help!

Are you sure the vendor partial is in the same folder as the expense form? If not you should have
<%= render :partial => "folder/vendorform" %>

When you have nested attributes, you should use the simple_fields_for method which help manage associations. Then, remove the submit button for the vendor form and add it to the expense form instead. So the vendor form would be -
<div class="modal-body">
<%= simple_form_for Vendor.new do |f| %>
(bunch of fields)
<% end %>
</div>

Related

How to a parameter from my URL to Modal and Controller in Rails 4 application

All, i am facing an issue with passing a parameter into my Modal to sent the value of a field. I am able to pass and lookup the value via params if i go to new page where i can find the value from the URL params. But i am trying to use the same logic but in a modal and i can't seem to get it to work.
_my comments partial has the following
<% Reply.all.each do |reply|%>
<% if reply.parent_id == comment.id%>
<p class="feed-s-connection-update-item__headline Sans-1px-black-55%">
<%= image_tag(User.find(reply.user_id).avatar,:size => "20x20",class: "image-responsive") %>
<%=reply.body %>
</p>
<%end%>
<%end%>
<% from_reply_form ||= nil %>
<% unless from_reply_form %>
<p>
<%= link_to 'reply', new_reply_path( :id => comment.id) %>
</p>
<%= link_to 'Add release', new_reply_path(#reply,:id => comment.id), {:remote => true, ':id' => 'comment.id','data-toggle' => "modal", 'data-target' => '#replyModal'} %>
<% end %>
<div id="modal-window" class="modal hide fade" role="dialog" aria- labelledby="myModalLabel" aria-hidden="true"></div>
</div>
</li>
</ul>
<%end%>
I am trying this out using this link:
<%= link_to 'Add release', new_reply_path(#reply,:id => comment.id), {:remote => true, ':id' => 'comment.id','data-toggle' => "modal", 'data-target' => '#replyModal'} %>
If i use i am taking to the new page and will have the params in the url which works fine
url: https://hidemyurldevel/replies/new?id=72
<%= link_to 'reply', new_reply_path( :id => comment.id) %></p>
I am able to see the same URL when i try the other URL where remote is true, but i am not able to see the PARENT_ID populated.
Replies_controller - know this part i need to remove the respond but i have it break here so i can see whats returning
def create
#reply = Reply.new(reply_params)
if #reply.save
flash[:notice] = "thanks for reply"
respond_to do |format|
format.js
redirect_to :back
end
end
end
def new
#reply = Reply.new
#comment = Comment.find(params[:id])
#userid = current_user.id
end
Here is the Modal i call
for some reason the value is not populated into the Modal
<%= form_for(#reply) do |f| %>
<div id="replyModal" class="modal fade" tabindex="-1" role="dialog" aria- hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria- hidden="true">×</button>
Post A Reply
</div>
<div class="modal-body">
<form class="form center-block">
<div class="form-group">
Post <%= f.text_area :body, class:"form-control input-lg" %>
<%= f.hidden_field :user_id, :value =>#userid %>
<%= f.hidden_field :parent_id, :value =>#comment.id %>
</div>
<div class="field">
</div>
</form>
</div>
<div class="modal-footer">
<div>
<button class="btn btn-primary btn-sm" data-dismiss="modal" aria-hidden="true">reply</button>
<ul class="pull-left list-inline"><li><i class="glyphicon glyphicon-upload"></i></li><li><i class="glyphicon glyphicon-camera"></i></li><li><i class="glyphicon glyphicon-map-marker"></i></li></ul>
</div>
<div class="actions">
<%= f.submit class: "btn btn-primary btn-sm"%>
</div>
</div>
</div>
</div>
<%end%>
I can't seem to be able to use the parent_id from the URL and pass it into the
This works fine if you go to the new page but not when i try passing it into the URL to the controller. Please help!
So guys i solve my problem... I am not sure if this is the right way to go, but i wasn't setting the comment parameters and it was Nill to begin with.... i just initialize the comment and set it to the instance of the comments and that works..
Excerpt
i am iterating the comment
then in my reply section where i add a comment field next to each comment i am able to pass the value in the URL
<%#comment = comment%>
<%= link_to 'Add release', new_reply_path(:#comment => comment), {:remote => true, :id => comment.id,'data-toggle' => "modal", 'data-target' => '#replyModal'} %>

Form attribute is not nil but getting First form attribute can't be nil error

I'm getting an error on my edit user modal that says that the first argument can't be nil; however, the form works and pulls the information as expected. The setup is like this:
1) I have a table that summarizes employees
2) each employee has a modify action
3) the modify action opens up a modal with the edit form
The form works and users are able to edit employees. However, every time it's open I get an internal error notification saying that the first argument can't be nil or empty. just to be sure, I'm displaying the employee name in the edit modal to confirm it's not nil (and it's not). The problem is, I'm getting notifications for internal server errors caused by this issue although somehow the form is working.
Any thoughts on what could be causing this and how to fix it?
Employee table code:
<tr>
<td> <%= employee.name %> </td>
<td> <%= employee.status ? t(:active) : t(:inactive) %> </td>
<td> <%= mmm_dd_yy_date(employee.created_at) %> </td>
<td> <%= mmm_dd_yy_date(employee.updated_at) %> </td>
<td> <%= link_to t(:edit), '#', "data-toggle" => "modal", "data-target" => "#EditModal_#{employee.id}", "data-remote" => edit_employee_path(employee) + "#modal-edit-form" %> |
<%= link_to t(:remove), employee, method: :delete, data: { confirm: t(:confirm_remove_employee, name: employee.name)} %>
<!-- Modal -->
<div id='<%= "EditModal_#{employee.id}" %>' class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title"><%= t(:edit_employee) %></h4>
</div>
<div class="modal-body">
<%=render partial: 'edit_form', locals: {employee: employee} %>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal"><%= t(:close) %></button>
</div>
</div>
</div>
</div>
</td>
</tr>
Form modal code:
<div id= "modal-edit-form">
<%= employee.name %>
<%=form_for(employee) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class = "row" >
<div class = "col-xs-6">
<%= f.label :name%>
<%= f.text_field :name, class: 'form-control' %>
<%= f.label :status %>
<%= f.collection_select :status, {true: t(:yes), false: t(:no)}, :first, :last, selected: employee.status %>
<%= f.submit t(:update), class: "btn btn-primary"%>
</div>
</div>
<% end %>
</div>
The code looks good to me.
--
The one thing I would say is that including form_for multiple times on the same page is a big no-no - a bunch of conflicts will occur (id etc).
I would personally move the functionality to your employees#edit action as ajax:
#app/controllers/employees_controller.rb
class EmployeesController < ApplicationController
respond_to :js, :html, :json, only: :edit
def edit
#employee = Employee.find params[:id]
respond_with #employee
end
end
#app/views/employees/edit.js.erb
$("<%=j render 'edit' %>").appendTo("body");
// fire modal
#app/views/employees/edit.html.erb
<div id='<%= "EditModal_#{employee.id}" %>' class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title"><%= t(:edit_employee) %></h4>
</div>
<div class="modal-body">
<%=render partial: 'edit_form', locals: {employee: #employee} %>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal"><%= t(:close) %></button>
</div>
</div>
</div>
</div>
#app/views/employees/index.html.erb
<%= link_to t(:edit), '#', data: { toggle: "modal", target: "#EditModal_#{employee.id}", remote: edit_employee_path(employee) + "#modal-edit-form" }, remote: true %>
This way, you'll only be appending the edit forms when you render them.

Rails 4.0.4 custom form_for route

I'm trying to map a form_for to a specific controller and action. I've got the resources: apikey in the routes. All the solutions I've found don't seem to work. The form is placed inside a view of which the parent folder name doesn't correspond to the correct controller. Here is my form with my not working solution:
<%= form_for #key, url: { controller: :apikey, action: :update }, remote: true do |f| %>
<%= f.label :userkey, "Key" %>
<%= f.text_field :userkey %>
<%= f.submit "Update" %>
<% end %>
Here is my controller:
class ApikeyController < ApplicationController
def index
end
def update
respond_to do |format|
if #key.update(apikey_params)
format.js
else
format.html { render action: 'edit' }
end
end
end
private
def apikey_params
params.require(:apikey).permit(:userkey)
end
end
This is the log I get in the console:
Started GET "/accounts?utf8=%E2%9C%93&_method=patch&apikey%5Buserkey%5D=thekey&commit=Update"
As you can see, it doesn't call the apikey but the accounts controller. What am I doing wrong?
Update
A little weird, as I didn't really change anything, I now get this error when opening the site:
No route matches {:action=>"update", :controller=>"apikey"}
This is my rake routes:
apikey_index GET /apikey(.:format) apikey#index
POST /apikey(.:format) apikey#create
new_apikey GET /apikey/new(.:format) apikey#new
edit_apikey GET /apikey/:id/edit(.:format) apikey#edit
apikey GET /apikey/:id(.:format) apikey#show
PATCH /apikey/:id(.:format) apikey#update
PUT /apikey/:id(.:format) apikey#update
DELETE /apikey/:id(.:format) apikey#destroy
Update 2
Originally I had the form inside a bootstrap modal, like this:
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="myModalLabel">Change API key</h4>
</div>
<div class="modal-body">
<form role="form">
<div class="form-group">
<%= form_for #key, method: "post", remote: true do |f| %>
<%= f.label :userkey, "Key" %>
<%= f.text_field :userkey, class:"form-control", id:"apikeyinputfield" %>
<%= f.submit "Update", class: "btn btn-success btn-sm" %>
<% end %>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" id="submitnewapikey" data-dismiss="modal" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
If I delete the surrounding modal, the form automatically to map to the correct controller and action. This is not the case when surrounded by the modal. Really weird. Maybe the modal JS code messes up the form_for JS code.
You don't actually need to specify the url in form_for.
If no url is specified form_for will automatically identify which controller and method based on the #key parsed to it, regardless of what view the form is located.
<%= form_for #key, remote: true do |f| %>
<%= f.label :userkey, "Key" %>
<%= f.text_field :userkey %>
<%= f.submit "Update" %>
<% end %>
the piece code above can have the following outcomes:
if #key is a new record ( #key.new_record? returns true):
The form will send the request to ApikeyController create action
if #key is a not a new record ( #key.new_record? returns false), which is your case:
The form will send the request to ApikeyController update action
More info can be found here.
Hope this can help you.

Rails - multiple forms unintentionally using the same object

I've got a page showing details for every #user. Each user has an enrolment, which can has a comment. When I e.g. do this:
<% #user.each do |u| %>
<% the_enrolment = Enrolment.where(user_id: u).first %>
<% end %>
Then in every iteration the enrolment is a different enrolment, as the user changes in every iteration. So far, so simple.
But when I pass this enrolment variable (while looping through) to a partial which contains a form, like this:
<%= render 'the_partial', enrolment: the_enrolment %>
With this form (in the partial view):
<%= form_for enrolment, :url => the_path, remote: true do |f| %>
<%= f.hidden_field :id %>
<%= f.text_area :comment %>
<%= f.submit "Save" %>
Then, in the finally rendered page, every form uses the same enrolment. (They all have the same id and every text_are is pre filled with the content of one of them. What am I doing wrong here?
The complete iteration looks like this:
#user.each do |u|
the_enrolment = Enrolment.where(user_id: u).first
<%= the_enrolment %> # correct id
<%= render 'the_partial', enrolment: the_enrolment %>
end
Thank you very much!
Update
Here is an update with the newest informations. The problem seems to be that the form is placed inside a twitter bootstrap modal. Here is the whole partial:
<%= enrolment.id %> # here it's the correct id
<div id="myModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="myModalLabel">Admin Comment</h3>
</div>
<%= form_for enrolment, :url => the_path, remote: true do |f| %>
<div class="modal-body">
<p>
<%= "enrolment in modal: #{enrolment.id}" %> # at this place the id is ALWAYS the id of the very first enrolment
<%= f.hidden_field :id %>
<%= f.text_area :comment_admin %>
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
<%= f.submit "Save", class: "btn btn-success", id: "admin-comment-submit-button" %>
</p>
</div>
<% end %>
</div>
If I delete everything on this page concerning the modal, the form works.

understanding some embedded erb in Rails with bootstrap

Below is a chunk of code for a modal in bootstrap. I am trying to fully grasp what is happening and i am having trouble with role-options-<%= user.id %> both in the href= and div id tags. I just am not getting what is happening here. I feel like it is passing data some how. I also am not sure how to search correctly for this. So if anyone has any insight for me or places they could point to that would explain this one line.
is it linking directly to the div and passing the user.id?
<a data-toggle="modal" href="#role-options-<%= user.id %>" class="btn btn-mini" type="button">Change role</a>
<%= render user %>
<div id="role-options-<%= user.id %>" class="modal" style="display: none;">
<%= simple_form_for user, :url => user_path(user), :html => {:method => :put, :class => 'form-horizontal' } do |f| %>
<div class="modal-header">
<a class="close" data-dismiss="modal">×</a>
<h3>Change Role</h3>
</div>
<div class="modal-body">
<%= f.input :role_ids, :collection => Role.all, :as => :radio_buttons, :label_method => lambda {|t| t.name.titleize}, :label => false, :item_wrapper_class => 'inline', checked: user.role_ids.first %>
</div>
<div class="modal-footer">
<%= f.submit "Change Role", :class => "btn" %>
<a class="btn" data-dismiss="modal" href="#">Close</a>
</div>
<% end %>
</div>
Anywhere you see <%= ... %> tags in ERB markup, the Ruby code within the tags is being run and the result is printed out as text in the template (technically, the resulting value from the Ruby code has the #to_s method called on it, to convert it to a String).
So in this snippet:
<div id="role-options-<%= user.id %>"
the ERB template is generating a <div> element with an id attribute whose value is "role-options-", where will be whatever the Ruby code user.id.to_s returns.
And this snippet is similar: its creating a link (<a>) element whose href attribute is of the form #role-options-<user ID>. The only difference is that it begins with #, which means the link will be a page anchor, i.e. it will link to a different section of the same page, namely to the previously mentioned <div>.

Resources