so I'm new to rails and currently going through a tutorial for it on tutorialspoint. What I've gotten so far is a controller and a corresponding view for it which is an erb file. This is the code for the view:
<% if #books.blank? %>
<p>There are not any books currently in the system.</p>
<% else %>
<p>These are the current books in our system</p>
<ul id = "books">
<% #books.each do |c| %>
<li><%= link_to c.title, {:action => 'show', :id => c.id} -%></li>
<% end %>
</ul>
<% end %>
<p><%= link_to "Add new Book", {:action => 'new' }%></p>
However, when I try to view this through localhost:3000 while having the
rails server
command running a WEBrick server in the background on localhost:3000,
it keeps directing me to the default view on my browser,which is being rendered by the server from the following path:
/Users/hassanali/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/railties-4.2.4/lib/rails/templates/rails/welcome/index.html.erb
instead of the actual view within my rails application folder's view folder..which is
/Users/hassanali/Desktop/library/app/views/book/list.html.erb
I've been trying to fix this for ages now and no avail. Does anyone know what I can do?
Because you not define root_path for your app.
In config/routes.rb define root_path for it, ex:
root 'book#list'
You can tell Rails what you want '/' to route to by using root controller#action.
For example say you had a controller that looked like this.
class BooksController < ActionController::Base
def index
#books = Books.all
end
def show
#book = Books.find(params[:id])
end
end
If you wanted '/' to route to your index method, you would do the following in config/routes.rb.
Rails.application.routes.draw do
root 'books#index'
# Other routes here...
end
As a side note, if you add two root method calls, it will use the last one in the routes file.
http://guides.rubyonrails.org/routing.html#using-root
Since you have show and new action referenced you'll also likely want those routes as well. It's recommended to use RESTful routing schemes. Rails provides a useful method called resources which creates all the routes and helper methods needed to CRUD a resource.
That might look like the following.
Rails.application.routes.draw do
root 'books#index'
# A books resource
resources :books
end
http://guides.rubyonrails.org/routing.html#crud-verbs-and-actions
I encourage you to read the Rails Guide on routing so you understand your options.
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.
About a year and a half ago I took an online course in Ruby on Rails using version 3.2. I got through the class and made the application and now I'm going back through the class PDFs and doing it in Rails 4.1.0.
I've got to a section where I'm getting an error and I'm not sure if I'm doing something wrong or if something changed from Rails 3.2 to 4.1.
I've got this form_tag tag:
<%= form_tag :action => 'review', :id => #restaurant do %>
<strong>Poster: </strong><%= text_field "review", "poster" %><br /><br />
<strong>Date: </strong><%= datetime_select "review", "date" %><br /><br />
<strong>Review:</strong><br />
<%= text_area "review", "review", :rows => 5 %><br />
<%= submit_tag "Review" %>
<% end %>
The instructions say to get this to work to put the following code in the restaurants_controller.rb file:
def review
Restaurant.find(params[:id]).reviews.create(params[:review])
redirect_to :action=>"show", :id => params[:id]
end
But when I try and view the page that has the for for it I get this error:
No route matches {:action=>"review", "controller=>"restaurants", :id=>#<Restaurant id: 1, name: "Marco & Luca", created_at: "...", updated_at: "..."
My rake routes shows that show is mapped to the restaurants#show is mapped to the restaurant path.
Is the form_tag piece wrong?
In the instructions from the class we didn't set up anything in routes.rb, I'm guessing that's because of the redirect_to line in the controller file. Is that deprecated now? Is that no longer valid?
Routes file as requested: (in the class exercise we didn't have to edit the routes file).
Rails.application.routes.draw do
# You can have the root of your site routed with "root"
root 'restaurants#index'
resources :restaurants do
collection do
get 'login'
get 'register'
post 'newuser'
post 'validate'
post 'search'
end
end
Thanks!
You do need a route for that. The way it works is:
User fills in a form on some page and sends data to review route
Server processes user's data and returns a redirect to show route
A user gets a redirect and requests the show route
A server executes the show action
Apparently the route for review action (or as I called it above: a review route) doesn't exist in routes.rb. Add it.
UPD: Your routes file looks really odd, you seem to not follow a common practice to process one type of resources in one controller. Here, you probably need to add:
...
post 'search'
post 'review'
# ^ THIS ^
end
end
But you already process at least 3 types of resources in one controller: Users, Sessions and Restaurants. This might not be your fault if you were told to do so, but in either case it's not a proper way to structure an application.
Try:
<%= form_tag :action => 'review', :id => #restaurant.id do %>
I'm using a custom action to get the id of a project into the session, so that only relevant info for that project is shown in other areas. I've made a custom action in the projects controller, and am having trouble getting a link to work in the view to call that action. I just get an error saying "Couldn't find project without ID". I'm new to rails - I know it's probably an easy question, but help would be much appreciated, thanks!
View Code:
<%= link_to 'Select Project', :action => :select_project %>
Controller Code:
def select_project
#project = Project.find(params[:id])
session[:project_id] = #project.id
end
Routes:
resources :projects do
collection do
get :select_project
end
end
Alternative routes code:
resources :projects do
put 'select_project', on: :member
end
This is untested but I believe it is what you are looking for:
Routes:
resources :projects do
member do
post :set_current
end
end
this should create the following:
Endpoint: /projects/:id/set_current POST
Helper: set_current_project_path
Controller
def set_current
project = Project.find(params[:id])
session[:project_id] = project.id
redirect_to projects_path, :notice => "Current project set to #{project.name}"
end
Views
# index / erb tags excluded for simplicity
#projects.each do |project|
link_to 'Select Project', set_current_project_path(project), :method => :post
end
# show
<%= link_to 'Select Project', set_current_project_path(#project), :method => :post %>
See:
http://guides.rubyonrails.org/routing.html#adding-more-restful-actions
http://guides.rubyonrails.org/routing.html#crud-verbs-and-actions
Note also the use of 'post' instead of 'get', since we are changing the state of an object (session)
it is preferred to use a post not a get, otherwise users might pull up an old get request in the address bar
of their browser and set their session to a project unknowingly.
like varatis said - use rake routes or CONTROLLER=projects rake routes to help with determining what your route/path helpers look like and what http verbs they are expecting
And is there a reason why it's project not #project in the controller
The #project creates an instance variable; in a rails controller instance variables are made available to the views. This set_current action will never render a view, so no reason to make an instance variable out of it.
How come you have to set it to member and not collection in the routes
any action where you want to reference params[:id] should be a member route, an alternative would be to leave it as a collection route and pass params[:project_id] and pass that in all of your link_to calls, but in this case member makes more sense.
I believe resources :projects is a short cut for this break down
member do
get :show
get :edit
put :update
delete :destroy
end
collection do
get :index
get :new
post :create
end
hopefully that clarifies your questions some?
I think the route generated would be select_project_projects_path.
Link:
<%= link_to 'Select Project', select_project_projects_path %>
For future reference, run rake routes to see the automatic route helpers generated by Rails.
I have a gem which is essentially just a bunch of ActiveRecord::Base classes in the gems namespace. For all of them I get the same type of problem. I have the model...
module MyGem
class User < ActiveRecord::Base
...
end
end
Then in my app I have the routes...
resources :users
What gets screwed up is in the link_to...
<% #users.each do |user| %>
<td><%= link_to 'Show', user %></td>
<% end %>
I get...
undefined method `my_gem_user_path' for #<#<Class:0x0000000305f728>:0x00000003055408>
I've tried various things in routes.rb, but I'm thinking the solution may be to configure the model/link_to to call user_path(user) instead of my_gem_user_path(user) by default. I just don't know how, if at all possible, to do this.
Anybody know the best practice here?
I think the best practice here is to namespace your routes. Your class is namespaced as MyGem::User. #link_to uses #polymorphic_path to query the class for its class name and then calls #underscorize on that class name to get the path, so it assumes that the path will be my_gem_user_path, not user_path. That means the resources call should be wrapped like so:
namespace(:my_gem) do
resources :users
end
Then, my_gem_user_path will resolve to the MyGem::UsersController. Make sure your controller is namespaced like that as well. If you don't want the route to resolve to that controller, you can provide the controller name as an option to #resources.
edit: That's interesting, I didn't think it would run into that problem. There may still be some configuration to fix that, so I wouldn't mark this as solved yet. You can always replace the polymorphic_path (which is what is getting called when you use the resource-oriented path like above) with named routes. For example, instead of
link_to "User", user
you can always explicitly use
link_to "User", my_gem_user_path
When you use RESTful routes in your routes.rb file (with the #resources method), it provides you with those named routes.
For the form_for, the syntax is slightly different:
form_for(#user, #task)
becomes
form_for([#user, #task], :url => my_gem_user_my_gem_tasks_path(#user, #task), :method => :post)
for a new form. For an edit form, it would be
form_for(#task, :url => my_gem_user_my_gem_tasks_path(#user, #task), :method => :put)
Does that make sense? Here's a link to the documentation for form_for http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_for
I'm trying to edit a form, the route is controller/id/action for edit so for example
people/124321/edit
I'm trying to make this form submit to the update action using this code:
<% form_for :probe, #probe, :action => "update" do |f| %>
...
...
...
<%= submit_tag 'Submit' %>
<% end %>
When I click submit, it gives me an error stating
Unknown Action.
No action responded to (id).
Edit
The only thing in my routes specified for probes is map.resources :probes
RoR just did the people/124321/edit by itself when I generated the controller.
Rake routes shows this
probes GET /probes(.:format) {:controller=>"probes", :action=>"index"}
POST /probes(.:format) {:controller=>"probes", :action=>"create"}
new_probe GET /probes/new(.:format) {:controller=>"probes", :action=>"new"}
edit_probe GET /probes/:id/edit(.:format) {:controller=>"probes",action=>"edit"}
GET /probes/:id(.:format) {:controller=>"probes", :action=>"show"}
PUT /probes/:id(.:format) {:controller=>"probes", :action=>"update"}
DELETE /probes/:id(.:format) {:controller=>"probes", :action=>"destroy"}
Edit 2 Probe Controller
def edit
#probe = Probe.find(params[:id])
end
def update
#probe = Probe.find(params[:id])
debugger
if #probe.update_attributes(params[:probe])
flash[:notice] = "Successfully updated probe."
redirect_to probes_path
else
render :action => 'edit'
end
end
It's hard to say exactly since you have posted very little supporting details for your question, but my guess is that your routes file is set up such that the precedence of something matching :controller/:action/:id comes before the route you're aiming for, :controller/:id/:action.
Routes are evaluated top-down, first match wins.
I'll echo John's answer, too. You shouldn't need to specify :action => 'update', and in fact these days I usually extract the form out of both new.html.erb and edit.html.erb into a partial _form.html.erb. form_for will figure out if the object is a new record and POST to either the create or update action, as appropriate.
I have seen some situations in the past where route changes reloaded in development mode confuse the routing code, which is usually fixed by restarting the server.
rake routes is also a good debugging tool. Check the page source to see what Rails has used for the form's action attribute, then scan down the output of rake routes to see where the request will end up.
If you're using RESTful resources, then you should just be able to do this:
<% form_for(#probe) do |f| %>
.
.
.
<%= f.submit 'Submit' %>
<% end %>
Rails can work out whether you're creating a new record or updating an existing one. See Binding a Form to an Object for further details.
Also, note the use of f.submit in my example. The *_tag helpers go together, so you wouldn't usually see a form_for helper with a submit_tag.
"Unknown Action. No action responded to (id)." sounds like a routing problem.
Have you removed or commented out the default routes in your routes.rb file?
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
If the default routes are being run it could be swapping the id for the action?