Rails - routing error on delete - ruby-on-rails

UPDATE rephrased after learning
I have extended my app with a new model called 'tag' (very similar set up as with comments in blog).
Intended outcome: the user to stay on the page when clicking the link_to button to delete a tag; I now get an routing error (below) and I don't understand why.
No route matches [DELETE] "/annotations/7/tags"
The TAG list is added to the view for ANNOTATIONS like this:
<div class="panel panel-default" style="background-color: white; word-wrap: break-word; font-size: 0.9em;">
<table id="tags" class="table table-hover">
<thead>
<tr>
<th>Tag</th>
<th>Type</th>
<th></th>
</tr>
</thead>
<tbody>
<% #annotation.tags.each do |tag| %>
<tr>
<td><%= tag.content %></td>
<td><%#= tag.tagtype_id | tag.tagtype.typeoftag %></td>
<td><%= link_to '', [tag.annotation, tag], method: :delete, data: { confirm: 'Please confirm deletion!' }, :class => "glyphicon glyphicon-remove" %></td>
</tr>
<% end -%>
</tbody>
</table>
</div>
These are my routes:
Rails.application.routes.draw do
root 'dashboard#index'
devise_for :users
resources :users, :documenttypes, :tagtypes
resources :documents do
resources :tags
get "pdf", on: :member
end
resources :annotations do
resources :comments, :tags
get "pdf", on: :member
end
get "annotations/:id/annotate" => "annotations#annotate", as: 'annotate'
get "angular_test", to: "angular_test#index"
mount PdfjsViewer::Rails::Engine => "/pdfjs", as: 'pdfs'
And the tags.controller
class TagsController < ApplicationController
def create
#annotation = Annotation.find(params[:annotation_id])
#comment = #annotation.tags.create(tag_params)
redirect_to annotation_path(#annotation)
end
def destroy
#annotation = Annotation.find(params[:annotation_id])
#comment = #annotation.tags.find(params[:id])
#comment.destroy
redirect_to annotate_path(#annotation)
end
private
def tag_params
params.require(:tag).permit(:content, :location, :tagtype_id)
end
end
UPDATE
The table in the view always has an empty row, which I cannot delete. I then get the routing error. With rows that were created when adding a tag, this does not happen and I can delete them. Why am I getting an empty row?

This needs to be done using AJAX (asynchronously), all you need to do is to have your destroy action to respond to javascript. You can do that by adding the remote option to the link for the deletion as below:
<td><%= link_to 'Delete', [tag.annotation, tag], method: :delete, remote: true, data: { confirm: 'Please confirm deletion!' }, :class => "glyphicon glyphicon-remove" %></td>
The remote: true option makes the request AJAX. Now on the controller side you need to respond with the resulting javascript code that you want to execute, probably hiding this row that you want to delete.
In the views folder, under the tags controller you need to create a file called destroy.js and in this file you specify the code that you want to be executed for handling this to hide for example that row.

Related

Facing issues with link_to "Edit" in rails

I am trying to display all the metrics in a table format with an edit option. But, I end up with the below error
In Index view, I am able to see all the data. But when I click on edit link, it is not redirecting to edit view where I have different columns to be showed.
index view:
<%= form_for :metrics_controller, url: metrics_path(#metric), method: :get do |f| %>
<table id="metrics">
<thead>
<tr id="AllMetricColumnNames">
<th id="CommentsColumn">Comments</th>
<th id="EditColumn">Edit</th>
</tr>
</thead>
<% #metricAll.each do |data| %>
<tr id="AllMetricValues">
<td id="Comments"><%= data.Comments %></td>
<td id="EditButton"><%= link_to "Edit", edit_metric_path(#metricAll) %></td>
<% end %>
</tr>
</table>
<% end %>
Controller:
class MetricsController < ApplicationController
def index
#metricAll = Metric.all
end
def show
#metric = Metric.find(params[:id])
end
def edit
#metric = Metric.find(params[:id])
end
private def post_params
params.require(:metric).permit(:Metric, :Comments)
end
end
routes:
root 'metrics#index'
get 'index' => 'metrics#index'
get 'edit' => 'metrics#edit'
resources :metrics
You're passing ALL the metrics for the edit route. Move from
<td id="EditButton"><%= link_to "Edit", edit_metric_path(#metricAll) %></td>
to
<td id="EditButton"><%= link_to "Edit", edit_metric_path(data) %></td>
data is the current metric in your code
According to your screenshot, the error is within the model.
Also, as mentioned by others, you should remove those get routes as the resources :metrics will generate the necessary routes for all your CRUD actions a.ka. for the index, show, edit, new, create, update, destroy.
My guess is that the metric.rb file has a belongs_to :automated_thresholding relationship but the metrics database table is missing the field automated_thresholding_id.
You should create a migration to add that field
add_reference :metrics, :automated_thresholding

My nested relationship is switching the ids of the models

I'm trying to delete an attachment from my rails project. I have the attachment nested under test_suite. When I hit the attachment delete button, the generated url switch the ids of attachment and test_suite. ex. the url should be localhost:3000/test_suites/3/attachments/11 but I'm getting localhost:3000/test_suites/11/attachmnts/3 and I get the error that attachment id=3 doesn't exist which is right because it should be attachment id = 11
Here is how I set it up.
routes.rb:
resources :test_suites do
resources :attachmnts, :only => [:create, :new, :destroy]
end
model/test_suite.rb:
class TestSuite < ApplicationRecord
has_many :attachemnts
end
model/attachment.rb:
class Attachment < ApplicationRecord
belongs_to :test_suite
has_attached_file :attach
validates_attachment_content_type :attach, :content_type => ["text/xml", "text/plain","text/html"]
end
I'm creating new attachment in test_suite show.The attachment will have a test_suite_id attribute.
test_suites_controller.rb:
def show
# create a variable pammed to test_suite with id passed from previous page
#test_suite = TestSuite.find(params[:id])
#attachment = Attachment.new
#attachment.test_suite_id = #test_suite.id
end
test_suite/show.html.erb:
<table class="table table-hover table-responsive">
<thead>
<tr>
<th>File Name</th>
<th>File Type</th>
<th>File Size</th>
<th>Created At</th>
<th></th>
</tr>
</thead>
<tbody>
<%= render partial: 'attachment', locals: {test_suite: #test_suite} %>
</tbody>
</table>
attachments/_attachment.html.erb:
<% test_suite.attachemnts.each do |attachment| %>
<tr>
<td> <%=attachment.attach_file_name %> </td>
<% if attachment.attach_content_type == 'text/plain'%>
<td>txt</td>
<% else %>
<td><%= attchement.attach_content_type.split('/').last %></td>
<% end %>
<td><%= attachement.attach_file_size %></td>
<td><%= attachement.created_at %></td>
<td><%= link_to '<span class="glyphicon glyphicon-remove-sign"></span>'.html_safe, test_suite_attachment_path(attachment),class:"btn btn-lg", method: :delete, data: {confirm: "Are you sure you want to delete the file?"} %>
</td>
</tr>
<% end %>
My rails routes outputs:
Prefix Verb URI Pattern Controller#Action
root GET / test_suites#index
test_suite_attachements POST /test_suites/:test_suite_id/attachements(.:format) attachements#create
new_test_suite_attachement GET /test_suites/:test_suite_id/attachements/new(.:format) attachements#new
test_suite_attachement DELETE /test_suites/:test_suite_id/attachements/:id(.:format) attachements#destroy
test_suites GET /test_suites(.:format) test_suites#index
POST /test_suites(.:format) test_suites#create
new_test_suite GET /test_suites/new(.:format) test_suites#new
edit_test_suite GET /test_suites/:id/edit(.:format) test_suites#edit
test_suite GET /test_suites/:id(.:format) test_suites#show
PATCH /test_suites/:id(.:format) test_suites#update
PUT /test_suites/:id(.:format) test_suites#update
DELETE /test_suites/:id(.:format) test_suites#destroy
When you're dealing with a nested object, you need the ids of both the parent and child object to perform show/edit/update/destroy operations. The issue is because you're not passing the test_suite object to test_suite_attachment_path helper. Modify your link to
<%= link_to '<span class="glyphicon glyphicon-remove-sign"></span>'.html_safe, test_suite_attachement_path(test_suite, attachment),class:"btn btn-lg", method: :delete, data: {confirm: "Are you sure you want to delete the file?"} %>
You can also pass an array of the parent and child objects instead of using the path helper.
#[test_suite, attachment]
<%= link_to '<span class="glyphicon glyphicon-remove-sign"></span>'.html_safe, [test_suite, attachment], class:"btn btn-lg", method: :delete, data: {confirm: "Are you sure you want to delete the file?"} %>
Please use a consistent spelling of 'attachments'. You're using a different version in every place.

CRUD in ruby on rails. Routing

Working through the "Ruby on rails 3 essential training" I'm encountering an issue with my routes and URL's. I have created a sujects_controller with a 'list' action and a 'show' action. Within my localhost, when I enter in:
localhost:3000.subjects/list, I get an error, 'couldn't find Subject with id=list'
But, when I enter in:
localhost:3000.subjects. I get the list that should have come up when entering the first URL. Also, after entering this second URL, I have links for Show, Edit, and Delete. When I hover my mouse over the link "Show", at the bottom of the page, the future output reads localhost.3000/subjects(3). This link works. But, according to my instructors tutorials, it should read, localhost.3000/subjects/show/3. For some reason my links and/or actions, aren't working appropriately and I'm not sure why since I'm following the instructions.
Here is my subjects_controller.rb file:
class SubjectsController < ApplicationController
def index
list
render('list')
end
# def index
# show
# render('show')
# end
def list
#subjects = Subject.order("subjects.position ASC")
##subjects = Subject.all
end
def show
#subjects = Subject.find(params[:id])
end
def new
#subjects = Subject.new
end
def create
#subject = Subject.new(params[:subject])
if #subject.save
redirect_to(:action => 'list')
else
render('new')
end
end
end
Here is my list.html and show.html file:
<div class="subject list">
<h2>Subjects</h2>
<table class="listing" summary="Subject list">
<tr class="header">
<th> </th>
<th>Subject</th>
<th>Visible</th>
<th>Pages</th>
<th>Actions</th>
</tr>
<% #subjects.each do |subject| %>
<tr>
<td><%= subject.position %></td>
<td><%= subject.name %></td>
<td class="center"><%= subject.visible ? 'yes' : 'no' %></td>
<td class="center"><%= subject.pages.size %></td>
<td class="actions">
<%= link_to("Show", {:action => 'show', :id => subject.id}, :class => 'action show') %>
<%= link_to("Edit", '#', :class => 'action edit') %>
<%= link_to("Delete", '#', :class => 'action delete') %>
</td>
</tr>
<% end %>
</table>
Show.html
<%= link_to("<< Back to list", {:action => 'list'}, :class => 'back-link') %>
<div class="subject show">
<h2>Show Subject</h2>
<table summary="Subject detail view">
<tr>
<th>Name</th>
<td><%= #subject.name %></td>
</tr>
<tr>
<th>Position</th>
<td><%= #subject.position %></td>
</tr>
<tr>
<th>Visible?</th>
<td><%= #subject.visible ? 'true' : 'false' %></td>
</tr>
<tr>
<th>Created</th>
<td><%= #subject.created_at %></td>
</tr>
<tr>
<th>Updated</th>
<td><%= #subject.updated_at %></td>
</tr>
</table>
</div>
And my config/routes.rb file:
Rails.application.routes.draw do
root :to=>"demo#index"
get 'demo/index'
get 'demo/hello'
get 'demo/other_hello'
resources :subjects
get 'subjects/list' => 'subjects#list'
get 'subjects/list' => 'subjects#show'
get 'subjects/create' => 'subjects#create'
The instructor never shows his routes.rb file so I just started using the gets in order to get my actions to work. The resources :subjects wasn't able to take care of everything so I used GET. Also in my subjects_controller I def:index to render list. If I don't do that nothing works at all. I'm obviously new to all of this but love learning about it and any information is appreciated. I have looked at the rails routing from the guides but that hasn't helped me much. Its more the concept/theory of why my links/actions aren't working that I'd be very interested to hear about. Thanks for any info!
When you specify in routes
resources :subjects
It creates seven actions( index, new, create, create, show, edit, update, destroy)
When you call localhost:3000/subjects it ask routes where to go. And index action is called
/subjects subjects#index display a list of all subjects
And when you are saying localhost:3000/subjects/list
It expect id after /subjects as there are routes mapped to that
localhost:3000/subjects/5 when you will call this it will call show method in controller asking for record with id 5 in database
/subjects/:id subjects#show
If you want to see all the routes, from console type
rake routes
And if you want to define extra method like list as below
get 'subjects/list' => 'subjects#list'
and remove all other routes for list from routes file
And there are many more options to specify routes and to learn that this is your best friend
http://guides.rubyonrails.org/routing.html
The issue is your routes.rb file. When you specify resources :subjects you're adding many routes, one of which is get 'subjects/:id' => 'subjects#show'
Since routes take precedence depending on the order you write them (top to bottom) this is overwriting your get 'subjects/list' => 'subjects#list' line.
You also have many other redundant routes that are being overwritten there.
get 'subjects/list' => 'subjects#list'
get 'subjects/list' => 'subjects#show'
subjects#show won't ever be called because the route calling subjects#list will take precedence
It's because you first decleared
resources :subjects
and then the other routes.
In your case the best way to add routes to a resource is the following:
resources :subjects do
collection do
get :list, to: :show
end
end
This will generate:
# rake routes
list_subjects GET /subjects/list(.:format) subjects#show
subjects GET /subjects(.:format) subjects#index
POST /subjects(.:format) subjects#create
new_subject GET /subjects/new(.:format) subjects#new
edit_subject GET /subjects/:id/edit(.:format) subjects#edit
subject GET /subjects/:id(.:format) subjects#show
PATCH /subjects/:id(.:format) subjects#update
PUT /subjects/:id(.:format) subjects#update
DELETE /subjects/:id(.:format) subjects#destroy

Rails: No route matches... missing required keys: [:element_id]

So, basically, I have Features nested within Elements which is nested within Apps. The Apps show page contains a Table of Elements, and each Element has a table of Features. I know that this will look a bit messy, but I'm more worried about functionality right now, and I'll clean up the HTML later.
Full error:
Showing ~/app/views/apps/show.html.erb where line #41 raised:
No route matches {:action=>"new", :controller=>"apps/elements/features",
:element_id=>nil} missing required keys: [:element_id]
My FeaturesController (only a few methods shown for the sake of space)
class Elements::FeaturesController < ApplicationController
before_action :set_feature, only: [:show, :edit, :update, :destroy]
# GET /features
# GET /features.json
def index
#features = Feature.all
respond_with(#features)
end
# GET /features/1
# GET /features/1.json
def show
respond_with(#element.features)
end
# GET /features/new
def new
#element = Element.find(params[:element_id])
#feature.element = #element
#feature = Feature.new
end
# GET /features/1/edit
def edit
end
# POST /features
# POST /features.json
def create
#element = Element.find(params[:element_id])
#feature = Feature.new(feature_params)
#feature.element = #element
#feature.save
if #feature.save
flash[:notice] = "#{#feature.name} purchase was added to the #{#feature.element.name}."
redirect_to(#feature)
else
flash[:error] = "There was a problem adding the purchase."
render :show
end
end
My show.html.erb for Apps:
<p id="notice"><%= notice %></p>
<p>
<strong>Name:</strong>
<%= #app.name %>
</p>
<p>
<strong>Infivewords:</strong>
<%= #app.infivewords %>
</p>
<p>
<strong>Description:</strong>
<%= #app.description %>
</p>
<div class="media">
<div class="media-body">
<table class="table table-hover">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th>Delete</th>
<tr>
</thead>
<tbody>
<% #app.elements.each do |element| %>
<tr>
<td><h4><%= element.name %></h4><br><h4><%= element.description %></h4></td>
<td>
<% element.features.each do |feature| %>
<td><h4><%= feature.name %></h4><h4><%= feature.description %></h4>
</td>
<% end %>
<td><h4><%= link_to "Delete", [#app, element], method: :delete, confirm: "Are you sure?" %></h4></td>
<td><%= link_to 'Add a Feature', new_element_feature_path(#element), class: 'pull-right' %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
</div>
<br>
<br>
<%= link_to 'Add an Element', new_app_element_path(#app) %>
<br>
<%= link_to 'Edit', edit_app_path(#app) %> |
<%= link_to 'Back', apps_path %>
Routes:
Rails.application.routes.draw do
resources :apps do
resources :elements, controller: 'apps/elements'
end
resources :elements do
resources :features, except: [:index], controller: 'apps/elements/features'
end
root to: 'apps#index'
Please excuse the mess. I'm new to rails and I've been tearing my code apart trying to figure this out. Please let me know if I should post any more code. Thank you in advance!
try changing the path inside
<td><%= link_to 'Add a Feature', new_element_feature_path(#element), class: 'pull-right' %></td>
to
new_element_feature_path(element)
since you are still looping #app.elements, right?
Solution:
In view, changed params to #element.feature:
<%= link_to 'Add a Feature', new_app_element_feature_path(#element.feature), class: 'pull-right' %>

Editing multiple records in one form - Rails

I'm trying to edit multiple records using one form, so the user can edit a few records then press submit at the end rather than after each individual one. I've posted my current code, and I get this error:
undefined method `connection_connection_path'
Controller
def show
#customer = Customer.find(params[:id])
#connection = #customer.connections
respond_to do |format|
format.html # show.html.erb
format.json { render json: #customer }
end
end
View
<table class="table">
<thead>
<th>Interface</th>
<th>Device</th>
<th>Speed</th>
<th>Site</th>
<th>Capable</th>
<th>Notes</th>
</thead>
<%= form_for(#connection) do |f| %>
<% #connection.each do |l| %>
<tr>
<td><%= l.interface %></td>
<td><%= l.device %></td>
<td><%= l.speed %></td>
<td><%= l.site.name%> </td>
<td><%= f.check_box :check %></td>
<td><%= f.text_field :notes %></td>
</tr>
<% end %>
<tr><%= f.submit %></tr>
</table>
<% end %>
routes
resources :connections
resources :sites
resources :customer_sites
resources :customers
root :to => "customers#index"
so where is your submit button?? and it should not done in show, maybe you might create a new method in your controller and do the multiple edit function.
The basic concept is when you have checks, you need to pass an array of your object to your method, and update them one by one. or you can do that using JS as well.
refer this railscast
http://railscasts.com/episodes/165-edit-multiple
and this stackoverflow
Rails 3 Edit Multiple Records in a Single Form
these resources you can get easily by google :D
if still have problem, just come and ask here again

Resources