Nested form keeps creating new forms instead of overwriting previous - ruby-on-rails

I have a nested form that I render in my Submission show view that is meant to show a status field and notes field. This seems to be working fine, however whenever I navigate to the show view, it seems to show the current Status and Notes fields as well as creating additional Status and Notes fields. I would just like it to show one status and notes field that can be overwritten with new data.
Current form being rendered:
<%= form_for #submission do |f| %>
<%= f.fields_for :agent_activities do |a|%>
<td> <div class="field">
<%= a.text_field :Status%>
</div>
</td>
<td> <div class="field">
<%= a.text_field :Notes %>
</div>
</td>
<td>
<div class="actions">
<%= f.submit %>
</div>
</td>
<% end %>
<% end %>
Submission Controller:
def show
#submission.agent_activities.build
end

Solved.
This is a pluralized statement:
<%= f.fields_for :agent_activities do |a|%>
Needed to be singular like this,
<%= f.fields_for :agent_activity do |a|%>

Related

Can't get form to work when trying to create new item in Ruby on Rails

I am just starting to learn Ruby on Rails on my own, and my main source of learning is from online sites such as here and codecademy, which only does an OK job at actually explaining what's happening when I code.
My project is a very simple IT Inventory site, that displays a database with info on items. This is to practice with CRUD, and right now I am stuck on the create part. Whenever I click a link on my main page, it is suppose to go to a page with a form on it that they can enter and then submit, but it won't even display the page with the form. Here is my current code.
Routes.rb
Rails.application.routes.draw do
get '/items' => 'items#index'
get 'items/new' => 'items#new'
post 'items' => 'items#create'
root 'items#index' #homepage and /items are same page for now
Items Controller
class ItemsController < ApplicationController
def index
#items = InventoryItem.all
end
def new
#item = InventoryItem.new
end
def create
#item = InventoryItem.new(item_params)
if #item.save
redirect_to '/items'
else
render 'new'
end
end
private
def item_params
params.require(:item).permit( :idnumber, :vutag, :fund, :dept, :bldg, :person, :mfct, :mfctdate, :commonname, :modelnum, :serial, :cost)
end
end
new.html.erb
<%= form_for(#item) do |f| %>
<div>
<%= f.label :inventoryitem %><br>
<%= f.text_area :idnumber %><br>
<%= f.text_area :vutag %><br>
<%= f.text_area :fund %><br>
<%= f.text_area :dept %><br>
<%= f.text_area :bldg %><br>
<%= f.text_area :person %><br>
<%= f.text_area :mfct %><br>
<%= f.text_area :mfctdate %><br>
<%= f.text_area :commonname %><br>
<%= f.text_area :modelnum %><br>
<%= f.text_area :serial %><br>
<%= f.text_area :cost %><br>
</div>
<div>
<%= f.submit "Create" %>
</div>
<% end %>
index.html
<table>
<tr>
<th>IDNum</th>
<th>VU Tag</th>
<th>Fund</th>
<th>Dept</th>
<th>Bldg</th>
<th>Person</th>
<th>Mfct</th>
<th>Mfct Date</th>
<th>Common Name</th>
<th>Model</th>
<th>Serial</th>
<th>Cost</th>
</tr>
<tr>
<% #items.each do |item| %>
<td> <%= item.idnumber %> </td>
<td> <%= item.vutag %> </td>
<td> <%= item.fund %> </td>
<td> <%= item.dept %> </td>
<td> <%= item.bldg %> </td>
<td> <%= item.person %> </td>
<td> <%= item.mfct %> </td>
<td> <%= item.mfctdate %> </td>
<td> <%= item.commonname %> </td>
<td> <%= item.modelnum %> </td>
<td> <%= item.serial %> </td>
<td> <%= item.cost %> </td>
<% end %>
</tr>
</table>
<br><br>
<%= link_to "New Entry", "items/new" %>
A very basic app to display info from a database. (I'll go back and make it pretty once it works.
The page that displays the table works fine, its when I click on the link and go to items/new that it gives me this error:
NoMethodError in Items#new
Showing /home/group3/ITSite/app/views/items/new.html.erb where line #1 raised:
undefined method `inventory_items_path' for #<#<Class:0x007f8b11137718>:0x007f8b10012fc8>
Extracted source (around line #1):
<%= form_for(#item) do |f| %>
<div>
<%= f.label :inventoryitem %><br>
<%= f.text_area :idnumber %><br>
<%= f.text_area :vutag %><br>
<%= f.text_area :fund %><br>
Rails.root: /home/group3/ITSite
Application Trace | Framework Trace | Full Trace
app/views/items/new.html.erb:1:in `_app_views_items_new_html_erb__1490812464141641456_70117522166260'
Can anyone help me figure out what the error is and where I need to fix it? I don't believe its the html page itself, but rather something leading up to that, or something named wrong. The naming convention in Ruby on Rails throws me off a little bit.
Rails uses convention over configuration. What that means is that names are important. Your model is InventoryItem. Therefore your controller should be called InventoryItemsController.
In your routes, as Vasfed mentioned, the convention is to use the resources method to generate the necessary paths. So rather than get '/items/new', etc just use resources :inventory_items.
Let's say you make those changes. In your InventoryItemsController new action, set #inventory_item = InventoryItem.new. Of course, you can call your variables whatever you want but it makes sense to call it what it actually is. That's why I'm suggesting #inventory_item. Good so far?
In your form, do this: form_for(#inventory_item) do |f|. Rails will automatically translate that into a "new" path for that model instance: new_inventory_item_path (aka inventory_items/new).
Use resources in routes, it creates named routes along with routes.
Rails.application.routes.draw do
resources :items, only:[:index, :new, :create]
root 'items#index'
end
Also you should name model the same as controller and route, for defaults to work

Cocoon: allow users only to add not edit

I have a Ticket model, which has many Comments. In the edit view, I allow users to add comments, using cocoon. However I want to ensure that previous comments can't be edited. In the view I use a partial called indexlist to render all the previous comments (and delete them). For brevity, I haven't included that code. So in the view I have
<h1>Comments</h1>
<%= render 'comments/indexlist' %>
<br /><br />
<%= f.fields_for :comments do |tc| %>
<%= render partial: 'comment_fields', locals: {f: tc} %>
<% end %>
<div>
<%= link_to_add_association 'Add Comment', f, :comments, :class => "btn btn-primary" %>
</div>
The problem is using f.fields_for :comments do |tc| ... is that it renders each previous comment, but without it, if there are validation errors on the subform all the data is lost during the form round trip.
I'm sure there's an easy solution to this one...
I guess you'll need to have a conditional in the comment_fields
<% if f.object.user_id == current_user.id %>
<div class="field">
<%= f.label :content %>
<%= f.text_field :content %>
</div>
<% else %>
<%= f.object.content %>
<% end %>
That will let you edit your own comments.
The other way you could do it is have one form purely for the ticket and use ajax to add/edit comments rather than use cocoon and nested_attributes which would be the like the way stackoverflow works.

Ruby on Rails go to a specific page when clicking "f.submit"

In my Ruby on Rails application I have the following form for booking_line view:
<%= form_for #booking_line do |f| %>
<%= f.hidden_field :showing_id %>
<%= image_tag "thor_hammer.jpg",:size => "900x250" %>
<td width="300px"> <br><%= f.label :seat_id, 'Please Select a Seat:' %>
<br><%= f.collection_select :seat_id, free_seats, :id,:seats_available %><br>
</td>
<td width="300px">
<div class="actions">
<%= f.submit %>
</div>
<br>
<%= render "/error_messages", :message_header => "Cannot save: ", :target => #booking_line %>
</td>
<% end %>
But as this is booking_line, what I want to happen is that when the submit button is clicked it creates a booking and a booking_line because in the booking_line table it has the attribute booking_id so that the association is made between the two. How can I achieve this?
you can use url in form_for method..to overwrite individual conventions, such as:
<%= form_for(#post, url: my_custom_path) do |f| %>
...
<% end %>
and then add your own logic at my_custom action to achieve it

Rails nested model form wrong html id

I have a Cover model which has many Slots. I created a form following the #196 Railcast and #197 Railcast.
The form works fine for creation, but when I want to update a Cover (specifically a child Slot) it doesn't get updated. The problem seems to be that the html name attribute of the fields for the slot do not contain the proper ID, instead, they always seems to start at 0 for the slots and increase. Here is the relevant code:
_form.html.erb:
<%= form_for(#cover) do |f| %>
...
<%= f.fields_for :slots do |builder| %>
<%= render "slot_fields", :f => builder %>
<% end %>
...
<% end %>
_slot_fields.html.erb:
<div class="fields">
<p>
<div class="field">
<%= f.label :width %>
<%= f.number_field :width %>
</div>
...
output html:
<p>
<div class="field">
<label for="cover_slots_attributes_0_width">Width</label>
<input id="cover_slots_attributes_0_width" name="cover[slots_attributes][0][width]" type="number" value="50" />
</div>
However the slot ID is 3
Thanks in advance

Submit a form to execute the UPDATE action from within the index

I'm trying to create a feature that allows users to edit a Client entry directly from the index page. When the user clicks 'Edit', a partial is rendered which replaces the elements with input text fields. But when the 'Update client' button is pressed, I get the error:
"No route matches [POST] "/clients/27"
I'm able to create new clients and destroy clients directly from the index... what am I doing wrong with the update action?
The partial:
<tr id="test">
<%= form_for Client.find(27), :method => :PUT do |f| %>
<td class="input">
<%= f.text_field :name, :value => "Test" %>
</td>
<td class="input">
<%= f.text_field :company %>
</td>
<td class="input">
<%= f.text_field :email %>
</td>
<td class="grayedOut"></td>
<td class="actions">
<%= f.submit "Confirm edit" %>
</td>
<% end %>
</tr>
routes.rb file:
resources :clients do
resources :projects do
resources :items
end
end
I figured it out. For whatever reason, nesting a form inside of a table seems to mess up the way form submits. When I rendered the partial outside of the table, the form had no problem submitting the update action.
I'm still confused as to WHY this happening. My solution to this problem is to use divs instead of tables.
EDIT: OK, so I researched this topic a bit more and found out that 'forms' are not valid children of <table> or <tr>. To fix this problem, I put the <%= form_for %> tag inside of the first <td>, and the <% end %> tag inside of the last <td>. Now it's working perfectly! Here's what my partial looks like now:
<tr id="test">
<td class="input">
<%= form_for Client.find(27), :method => :PUT do |f| %>
<%= f.text_field :name, :value => "Test" %>
</td>
<td class="input">
<%= f.text_field :company %>
</td>
<td class="input">
<%= f.text_field :email %>
</td>
<td class="grayedOut"></td>
<td class="actions">
<%= f.submit "Confirm edit" %>
<% end %>
</td>
</tr>

Resources