I'm trying to pass parameters using link_to with ruby on rails, but it says the id parameter I'm sending is null.
code from where I'm sending the id.
<% #conference.papers.each do |paper| %>
<tr>
<td><%= paper.title %></td>
<td><%= paper.author %></td>
<td><%= link_to "Download Paper", paper.attachment_url %></td>
<td><%= link_to 'Reviews', paper %></td>
<% if (paper.accepted) %>
<td><%= "Accepted" %></td>
<% else %>
<td><%= "Not accepted" %></td>
<% end %>
<% if (#state1 && paper.accepted == false) %>
<td><%= button_to "Accept", accept_paper_path(id: paper.id), class: "btn btn-danger", data: { confirm: "Are you sure that you wish to accept #{paper.title}?"} %></td>
<% end %>
<% if (#state2) %>
<% session["a"] = paper.id %>
<td><%= link_to "Review paper", new_review_path(id: paper) %></td>
<% end %>
</tr>
<% end %>
code for the review controller
def new
#paper = Paper.find_by_id(params[:id])
#review = Review.new()
end
You missed .id in
link_to "Review paper", new_review_path(id: paper.id)
But it is not a good solution. If your Paper model has_many :reviews, it would be better to nest reviews routes in paper's ones. Like this:
# config/routes.rb
resources :papers do
resources :reviews
end
And so, your link_to will look like:
link_to "Review paper", new_paper_review_path(paper)
which will generate
/papers/:paper_id/reviews/new
You can learn more about Rails routing here.
Lets start by setting up the routes properly:
resouces :papers do
member do
patch :accept
end
end
This will let you accept a review by PATCH /papers/:id. To create the button use:
<%= button_to accept_paper_path(paper), method: :patch %>
Note that this should use the PATCH or PUT http method - not GET since it is a non-idempotent action.
Note that you can just pass the model instead of doing accept_paper_path(id: model) or accept_paper_path(id: model.id).
For reviews you will want to create what is called a nested resource:
resouces :papers do
member do
patch :accept
end
resources :reviews, only: [:new, :create]
end
This gives you the route /papers/:paper_id/reviews/new.
<%= link_to "Review paper", new_paper_review_path(paper) %>
To set the form to create a new review to the use correct path use an array containing the parent and child:
<%= form_for([#paper, #review]) %>
Related
I've searched this site and asked a couple other programmers and can't figure out what the problem is with my code. I'm a beginner to Rails, so I'm still trying to figure everything out.
I'm getting this error:
ActionController::UrlGenerationError in Lists#show
No route matches {:action=>"toggle_completed", :controller=>"tasks", :id=>nil, :list_id=>3} missing required keys: [:id]
Here is the code it's referring to on the Lists#show page:
<p id="notice"><%= notice %></p>
<h3>add a task</h3>
<%= render 'tasks/form', task: Task.new() %>
<p>
<strong>List Name:</strong>
<%= #list.name %><p></p>
<% #list.tasks.each do |task| %>
<td><%= task.id %></td>
<td><%= task.name %></td>
<td><%= task.completed %></td>
<td><%= link_to('Toggle', toggle_completed_list_task_path(:list_id => #list.id,
:id => task.id), :method => :put ) %></td><br />
<% end %>
</p>
My Routes:
resources :lists do
resources :tasks do
member do
put :toggle_completed
end
end
end
Tasks Controller:
def toggle_completed
#task = Task.find(params[:id])
#task.completed = !#task.completed
#task.save
end
List has_many: tasks
and
Task belongs_to: list
I've experimented a bit and on my Lists#show page, if I add this line:
<%= task.id %>
The correct value appears on the page, so I'm not sure why it's coming up nil. I've searched the site and haven't found anything that really discusses this exact issue. Thanks!
create a separate routes for toggle_completed ex-
put 'list/task/:id', to: 'tasks#toggle_completed', as: :list_task_completed
and
<%= link_to('Toggle', list_task_completed_path(:id => task.id), :method => :put ) %>
I'm using Rails 4
I need to delete association Box with link_to method. The problem is that I have to do it from parrent controller and method: patch. my corrent code is doing nothing because I don't know how to use data: for link_to.
#views/modifications/show.html.erb
<% #modification.boxes.each do |box| %>
<tr>
<td><%= box.name %></td>
<td><%= link_to "delete", #modification, remote: true, method: :patch %></td>
</tr>
<% end %>
By the way, this is used with Ajax so page doesn't need to be reloaded.
I have to do it
You don't have to do anything in any way - if Microsoft can release Windows for all the PC's in the world, I'm sure you can get this working.
You have several issues, the most important of which being... how do you identify the box object to delete?
The whole point of nested resources (which is what you need) is to give you the ability to identify a "parent" object and a child object.
Your current setup prevents you from identifying the box you wish to remove. Ideally, you should use the following code to get it sorted:
#config/routes.rb
resources :modifications do
resources :boxes, only: :destroy
end
#app/views/modifications/show.html.erb
<% #modification.boxes.each do |box| %>
<tr>
<td><%= box.name %></td>
<td><%= link_to "delete", [#modification, box], remote: true, method: :delete %></td>
</tr>
<% end %>
#app/controllers/boxes_controller.rb
class BoxesController < ApplicationController
def destroy
#modification = Modification.find params[:modification_id]
#box = #modification.boxes.find params[:id]
#box.destroy
end
end
Try to using link_to with delete method on box destroy path, like this:
<%= link_to 'Delete', box_path(box), method: :delete, remote: true %>
I'm creating a simple inventory app, there is a view that lists 'items'. It has tables with these rows:
<tr>
<td><%= item.title %></td>
<td><%= item.desc %></td>
<td><%= item.value %></td>
<td><%= item.room.name %></td>
<td><%= item.user.username %></td>
<td>
<%= link_to 'View', item %>
<%= link_to 'Edit', edit_item_path(item) %>
<%= link_to 'Delete', item, method: :delete, data: { confirm: 'Are you sure?' } %>
<%= link_to 'Add Comment', !?????! %>
</td>
/tr>
I have a linked model for 'comments' set up but don't know how to pass the 'item_id' to it when creating a new one.
The URL helpers actually accept the object to make a route for an association. Meaning, assuming you have a nested route for comments within items,
resources :items do
resources :comments
end
you can link_to the new_item_comments_path(item).
The method new_item_comments_path(item) makes a string URL based on the new_item_comments route, which you feed to link_to to make an HTML <a> tag.
To be clearer, in your view you would have:
<%= link_to 'View', item %>
<%= link_to 'Edit', edit_item_path(item) %>
<%= link_to 'Delete', item, method: :delete, data: { confirm: 'Are you sure?' } %>
<%= link_to 'Add Comment', new_item_comments_path(item) #-> (instead of ???) %>
In this case, the item you are passing is the reference to your current item, which allows the URL helper to make a URL for it from the route.
The Rails guide for routing should be a useful read for you.
Now that's assuming your Comment controller assigns the right stuff at the right place. You seemed to have figured that out, but I'll explain for the sake of clarity (and future visitors)
class CommentsController < ApplicationController
# GET /item/:item_id/comments/new
def new
#comment = Comment.new
#item = Item.find(params[:item_id])
#comment.item = #item
# render
end
# POST /item/:item_id/comments
def create
#comment = Comment.new(params[:comment])
#item = Item.find(params[:item_id])
#comment.item = #item
# if #comment.save blah
end
end
All credit should go to #jonallard
The solution is all about routing it seems, you need to pass a url to the form that makes new comments (linked models).
to do this:
Add this (or similar depending on object names) to the page that is calling the creation:
<%= link_to 'Add Comment', new_item_comment_path(#item) %>
In both the new and the create method of the comments_controller there is a line starting #comment = Comment.new. Under that line add:
#item = Item.find(params[:item_id]) AND
#comment.item = #item
edit the top line of the comments template for to: <%= form_for(#comment, {:url => item_comments_path(#item)}) do |f| %>
Edit routes to somethings like:
resources :items do
...
resources :comments
end
and Read this: http://guides.rubyonrails.org/routing.html#creating-paths-and-urls-from-objects!
As mentioned before all credit goes to #jonallard, his answer and his expertise.
I am trying to use the link_to feature to link one view to another.
The view i am calling link_to is app/views/instructors/show.html.erb and that snippet of code looks like this (namely, the second to last line of it)
<% provide(:title, #instructor.login) %>
<% courses = Course.where(:instructor_ID => #instructor.id) %>
<div class="span2">
<h1 align=center ><%= #instructor.login %></h1>
<%= link_to "Add course", new_course_path(:instructor_ID\
=> #instructor.id), :class => "btn" %>
<br>
<br>
<%= link_to "Remove course", delete_course_path(courses), :class => "btn"%>
</div>
The view I am trying to link to is is app/views/courses/show_all.html.erb and looks like this:
<% #courses.each do |course| %>
<tr>
<td><%= course.course_name %></td>
<td><%= course.instructor_ID %></td>
<td><%= link_to 'Show', course %></td>
<td><%= link_to 'Edit', edit_course_path(course) %></td>
<td><%= link_to 'Destroy', course, :method => :delete, :data => { :confirm => 'Are you sure?' } %></td>
</tr>
delete_course_path routes to app/views/courses/show_all.html.erb shown above. When I try the code above, I get the following error:
undefined method `each' for nil:NilClass
At this line:
<% #courses.each do |course| %>
Any ideas what i'm missing in my link_to?
In your show_all action, you should define a #courses instance variables. This is
<% courses = Course.where(:instructor_ID => #instructor.id) %>
not passed to show_all.html.erb.
An instance variables is a variable passed from action of controller to the view corresponding.
I suppose when you show page of instructor, your route will like this: /instructors/:id, so maybe in your show_all action of instructor controller, you need something like:
def show_all
#courses = Course.where(instructor_ID: params[:id])
render 'courses/show_all'
end
This means that #courses is nil. Did you set it in your show_all action of your controller? E.g.
def show_all
#courses = Course.all
end
Also, in your show view, you set courses to a collection of Course objects, but your "Remove course" link looks like you only want to delete one course. Why do you use the delete_course route to link to your show_all view?
I'd like to learn how to use the methods defined in the controller in the index page.
I'm trying to implement "like" button on my blog.
PostController
def like
#post = Post.find(params[:id])
#post.like += 1
#post.save
end
In the index where all the posts are listed, I tried something like this.
<% #posts.each do |post| %>
<tr>
<td><%= post.name %></td>
<td><%= post.created_at.strftime("%Y/%m/%d, %I:%M%p") %></td>
<td><%= post.view %></td>
<td><%= link_to 'like', like_post_path %></td>
<td>hate</td>
</tr>
<% end %>
I got the idea by looking at the code,
<%= link_to 'make a new post', new_post_path %>
<%= link_to 'Edit', edit_post_path(post) %>
I thought the way to use methods in the controller in the index page was
(method in PostController)_post_path, but it seems I got it wrong.
undefined local variable or method `like_post_path'
I've also tried like(post).
My ultimate goal is to make this function as an ajax function, so I expected it to be a form like
<% link_to_function 'like', like_post, remote: true %>
What's the right way of using the method "like" in this case?
You'd need to define a named route to make this work. Like:
# in config/routes.rb
resources :posts do
member do
get 'like'
end
# OR
get 'like', :on => :member
end
# in `rake routes` this would show up as:
like_post GET /posts/:id/like(.:format) posts#like
# you'd reference in a view like:
like_post_path(#post)