I am new to rails development.
I have created a new database model called review and a controller called reviews_controller. In my routes file I have created the resource for reviews. However when I try and use the reviews#show in a link I get the error. No route matches {:action=>"show", :controller=>"reviews"}.
I have looked this error up but any of the results that I have found are more involved than the code that I am using. Is there something very basic that I am missing here.
Code for the model is
class Review < ActiveRecord::Base
belongs_to :user
end
Code for the controller is
class ReviewsController < ApplicationController
def show
#review = Reviews.find(params[:id])
end
def new
end
end
My link to in my header partial is
<li><%= link_to "Review", review_path %></li>
Code from my routes file
resources :users #New Line
resources :sessions, only: [:new, :create, :destroy]
resources :microposts, only: [:create, :destroy]
resources :reviews
Any help on this would be greatly appreciated as I cant get anywhere on this.
Welcome to SO!
Since you are linking to a specific review, you need to pass in the review's id to the link_to method.
<li><%= link_to "Review", review_path(#review) %></li>
Rails is smart enough to take the whole #review object to figure out its id.
Alternatively, you can link to all your reviews with
<li><%= link_to "Reviews", reviews_path %></li>
Since you said you have this link in your header partial, this might be what you actually want to do.
Related
I'm trying to understand an app in which it creates a link via link_to to new_user_session_path. In my controller, there is no new nor session. The generate link is users/sign_in which you can see here : [ListenUp][1]. Also, sign_in is not in the controller. My hunch is that it is some RoR magic.
The controller :
class UsersController < ApplicationController
def index
#users = User.all
end
def show
#user = User.find_by_permalink(params[:id])
#songs = Song.where(user: #user)
#friendships = #user.all_friendships
end
end
The routes
Rails.application.routes.draw do
devise_for :users
resources :users
resources :friendships
root 'pages#search'
resources :pages
resources :playlists
resources :songs
get 'search' => 'pages#search'
get 'search_results' => 'pages#search_results'
end
Part of the view that I'm trying to figure out :
<li><%= link_to "sign in", new_user_session_path %></li>
<li><%= link_to "sign up", new_user_registration_path %></li>
Thanks
[1]: http://listenup-songshare.herokuapp.com/
Rails will automatically generate helpers for you based on your route names. See Rails Routing From the Outside In for this straight from the horses's mouth.
By Convention these helpers look something like ACTION NAME + CONTROLLER NAME + "path" (or "url").
Given this routes file, you might have a new_song_path generated for you.
In addition to this, gems you add to your Gemfile can also create additional routes. Here you see that new_user_session_path is not your code.
To list all the routes in your app, including those added by other gems, run rake routes. Usually I run rake routes > tmp/routes.txt, which saves the output to a file named tmp/routes.txt (if you're not hip to bash), and I refer to this file often when developing my Rails app.
I have the Comment model, which is polymorphic associated to commentable models like Project, User, Update etc. And I have a page where a user can see every User's comment. I want a link near each comment with an address of an object this comment is associated with.
I could write something like that:
link_to 'show on page', Object.const_get(c.commentable_type).find(c.commentable_id)
But this will work only for not nested routes (like User). Here's how my routes look like:
resources :users do
resources :projects, only: [:show, :edit, :update, :destroy]
end
So when I need a link to a Project page, I will get an error, because I need a link like user_project_path.
How can I make Rails to generate a proper link? Somehow I have to find out if this object's route is nested or not and find a parent route for nested ones
You could use a bit of polymophic routing magic.
module CommentsHelper
def path_to_commentable(commentable)
resources = [commentable]
resources.unshift(commentable.parent) if commentable.respond_to?(:parent)
polymorphic_path(resources)
end
def link_to_commentable(commentable)
link_to(
"Show # {commentable.class.model_name.human}",
path_to_commentable(commentable)
)
end
end
class Project < ActiveRecord::Base
# ...
def parent
user
end
end
link_to_commentable(c.commentable)
But it feels dirty. Your model should not be aware of routing concerns.
But a better way to solve this may be to de-nest the routes.
Unless a resource is purely nested and does not make sense outside its parent context it is often better to employ a minimum of nesting and consider that resources may have different representations.
/users/:id/projects may show the projects belonging to a user. While /projects would display all the projects in the app.
Since each project has a unique identifier on its own we can route the individual routes without nesting:
GET /projects/:id - projects#show
PATCH /projects/:id - projects#update
DELETE /projects/:id - projects#destroy
This lets us use polymorphic routing without any knowledge of the "parent" resource and ofter leads to better API design.
Consider this example:
Rails.application.routes.draw do
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
resources :projects
resources :users do
# will route to User::ProjectsController#index
resources :projects, module: 'user', only: [:index]
end
end
class ProjectsController < ApplicationController
def index
#projects = Project.all
end
# show, edit, etc
end
class User::ProjectsController < ApplicationController
def index
#user = User.joins(:projects).find(params[:user_id])
#projects = #user.comments
end
end
This would let us link to any project from a comment by:
link_to 'show on page', c.commentable
And any users projects by:
link_to "#{#user.name}'s projects", polymorphic_path(#user, :projects)
I'm sure that there is a simple solution to this problem, but I can't for the life of me see what I am doing wrong - it's been a few months since I've worked on a Rails project, I must be forgetting something important.
I'm just trying to create a basic Rails form, but I am getting a no method path error when I navigate to the new form page.
This is for my Report model...
routes.rb
resources :report, only: [:new, :create], path_names: {new: ''}
report_controller.rb
def new
#report = Report.new
end
report/new.html.erb
<%= form_for #report do |f| %>
<% end %>
Navigating to http://localhost:3000/report yields
undefined method `reports_path'
Just to be comprehensive, here's the model...
class Report < ActiveRecord::Base
belongs_to :user
belongs_to :weather
belongs_to :feature
end
and the routes
report_index POST /report(.:format) report#create
new_report GET /report(.:format) report#new
I'm sure this is an amateur mistake... but I can't see what it is!
You need to change your routes to include a :show path if you want to be able to go to /report.
The path that I believe you are looking for is localhost:3000/reports/new
Oh for the love of god. It was a pluralization issue. The files should appear and be named as follows:
routes.rb
resources :reports, only: [:new, :create], path_names: {new: ''}
reports_controller.rb
class ReportsController < ApplicationController
def new
#report = Report.new
end
end
And the view files should all be in a folder called 'reports', not 'report'. The model is just the singular report.rb.
I have nested routes that I'm having difficulty formatting the way I want to.
My routes.rb has the following
resource :loan_application do
scope ":loan_application_id" do
resources :wizard, only: [:show, :update]
end
end
When I click the link to create a new resource:
<%= link_to business_loan_application_path(#user), method: :post %>
I get sent to a URL that looks like the following
http://localhost:3000/businesses/69/163/loan_application/wizard/eligibility
For some reason the loan_id (163) comes before /loan_application. I would like it to come after /loan_application.
When I rake routes I can see the same problem:
business_loan_application_wizard GET /businesses/:business_id/:loan_application_id/loan_application/wizard/:id(.:format) wizard#show
In my application I made the routes without your scope:
resources :loan_application do
resources :wizard, only: [:show, :update]
end
That leads me into exact the pathes I need
<%= link_to "Whatever", current_user %>
is linking to /user.id
My routes are setup like this
resource :user, except: [:index, :destroy]
So it should be linking to /user, right?
When I visit /user it says "Couldn't find User without an ID".
My user show action looks like this
def show
#user = User.find(params[:id])
end
The reason you are getting /user.id is because you have defined your routes as
resource :users, except: [:index, :destroy]
Note the singular resource which will create all the routes without any :id. As you don't have an accepting param within the route, the current_user that you are passing is matched to the format i.e., like .html, .js, etc. which in your case becomes .id
I would recommend using resources (note the plural)
resources :users, except: [:index, :destroy]
This will resolve the error Couldn't find User without an ID as you would be passing an params id within your route.
NOTE:
As per Rails convention, controller name should be plural. For UsersController, resources should be resources :users
I have had this happen many times. My fix is to use the path helpers.
<% link_to "Whatever", user_path current_user %>
This will drop the .id and make it /user/id