rails 3 newbie, with a general question about adding an additional route after scaffolding.
I create a scaffold for books... Which works great, and provides a nice index page.
The Index page shows all books in the system,
I'd like to add a page '/books/yours' that shows the books the user created. I already added the user_id to the books table, so that's working when users create new books.
But I can't figure out how to add the 'yours' page... Here's what I did:
In the books_controller.rb added:
def yours
#books = Books.all
respond_to do |format|
format.html # yours.html.erb
format.xml { render :xml => #notes }
end
end
Then I added a views/books/yours.html.erb page with just an H1 tag that says bingo...
Then in routes.rb I added:
Cline::Application.routes.draw do
resources :books
devise_for :users
match '/books/yours', :to => 'books#yours'
root :to => 'pages#home'
But it doesn't work? What'd I do wrong? thxs!
you could do this:
resources :books do
collection do
get 'yours'
end
end
So the url looks like: /books/yours
Here's everything explained: http://edgeguides.rubyonrails.org/routing.html
Related
So I always thought routes was straightforward but it clearly isn't. I want my page to show data.html.erb but it keeps on showing show.html.erb. These are my only two views in the user folder
My controller is:
class UserController < ApplicationController
def data
render :json => User.including_relationships
end
end
and my routes.rb is:
Rails.application.routes.draw do
get 'users/:data' => 'users#data'
resources :user
end
I always seem to get the show.html.erb page instead of the data.html.erb. Im sure there's something easy to fix here but what?
The : before data in your route denotes a variable, try
Rails.application.routes.draw do
get 'users/data' => 'users#data'
resources :user
end
Recently I've been trying to get a quiz page directing to a results page (and, with thanks to StanBoyet, I think I've finally managed it).
I have a User model and controller, and log in (using Devise) is all working fine. I have a QuizAnswers model and controller and all the tables present on the database. I also have a ResultsController.
Here is my routes.rb (note the resources):
Rails.application.routes.draw do
devise_for :users
root :to => 'home#index'
get "elearning" => "home#elearning"
get "howitworks" => "home#howitworks"
get "leadershipstyles" => "home#leadershipstyles"
get "whattypeofleader" => "quizzes#new"
get "showmetheskills" => "home#showmetheskills"
get "safeguarding" => "home#safeguarding"
get "toolsforthejob" => "home#toolsforthejob"
get "whatnext" => "home#whatnext"
get "congratulations" => "home#congratulations"
get "teamwork" => "home#teamwork"
get "facilitation" => "home#facilitation"
get "planning" => "home#planning"
get "communication" => "home#communication"
resources :quizzes
resources :results
resources :quiz_answers
resources :users do
resources :posts
end
end
In my quiz form, I pass form_for #quiz_answers (made accessible by the QuizAnswers#new action):
def new
#user = current_user
#quiz_answer = current_user.quiz_answers.build
end
(I have also tried, as an alternative, #quiz_answer = QuizAnswer.new)
When I click submit, the QuizAnswers#create action is triggered, which looks like this:
def create
redirect_to results_path
end
Which (rake routes tells me) points to results#index (ResultsController#index action) which I have set up like this:
def index
# in order to access all the results in our view...
#results = QuizAnswer.find(current_user.id)
end
When I click submit though, I'm getting the error:
Couldn't find QuizAnswer with 'id'=35
I have two questions:
How do I set up my new QuizAnswers with a reference to the id of the current_user? (QuizAnswers has a user_id attribute, as well as the usual id attribute).
Secondly, is this all horribly over-engineered or is this just 'the Rails way'? (If I'm doing it wrong, feel free to explain how I should do it 'right').
This line is very strange:
#results = QuizAnswer.find(current_user.id)
You need to change it to
#results = QuizAnswer.where(user_id: current_user.id)
#or
#results = current_user.quiz_answers
I created my app using the following scaffold
rails generate scaffold server hostname:string
rails generate scaffold template remote_template_id:integer remote_template_name:string server:belongs_to
I edited the routes to be nested
resources :servers do
resources :templates
end
Now I edited stuff around and my app is working great. However, as this is back-end and not customer facing, I wish to able to run a query such as this, where 'templatename' at the end is an arbitrary string
http://127.0.0.1:3000/servers/1/templates/find_by_remote_template_name/templatename
Essentially, be able to search using the column name remote_template_name .
What would be the best way to approach this problem?
In your routes.rb file:
resources :servers do
resources :templates
match 'templates/search/:template_name', to: 'templates#search', via: :get
end
Then you should be able to query http://localhost:3000/servers/1/templates/search/whatever which will route to the #search action of the TemplatesController passing in params[:template_name]
Special Thanks to Jon.
Solution: the correct routing had to be set and the search function in the controller needed some tweaking
routes.rb:
resources :servers do
resources :templates
match 'templates/search/:template_name', to: 'templates#search', via: :get
end
And I had to add in the column name that is being searched in the TemplatesController
def search
#template = #server.templates.where("remote_template_name = ?", params[:template_name])
respond_to do |format |
format.html
format.json { render json: #template }
end
end
class CommentsController < ApplicationController
def create
#commentable= context_object()
#comment = #commentable.comments.build(params[:comment].merge(:user_id => current_user.id))
if #comment.save
respond_to do |format|
format.js
end
else
render :action => 'new'
end
end
private
def context_object
params[:constraint][:context_type].singularize.classify.constantize.find( context_id )
end
def context_id
params["#{ params[:constraint][:context_type].singularize }_id"]
end
end
This commenting module has served me well but I ran into a hitch this morning, possibly because of my use of nested resources. Essentially, I now have a URL like:
/projects/3/albums/6/attachments/84
When I comment on that page, I get the error:
ActiveRecord::RecordNotFound (Couldn't find Project without an ID):
app/controllers/comments_controller.rb:102:in `context_object'
app/controllers/comments_controller.rb:14:in `create'
My routes file looks like:
resources :projects do
resources : albums do
resources :attachments
end
end
resources :attachments do
resources :comments, :only => [:create, :update,:destroy],
:constraint => {:context_type => "conversations"}
end
Any ideas on how I can get the commenting module to play nicely with commenting on project>Album>Attachment ?
Thanks for the input,
Posting this as an answer in order not to clutter the comments to the original question.
Since you don't have the requirement to keep attachments available via /attachments - making the second resources block useless, do something like this:
resources :projects do
resources :albums do
resources :attachments do
resources :comments, :only => [:create, :update,:destroy],
:constraint => {:context_type => "conversations"}
end
end
end
That's going to change your routes helpers (_path and _url), go through your controller(s) and view(s) and change them to reflect your new helpers.
Specifically, attachment_comments_path becomes project_album_attachment_comments_path.
The full list of routes for those models can be viewed by running rake routes in a console. I'd also recommend you take a closer look to the Rails routing guide.
I have a controller with the 7 RESTful actions plus an additional 'current' action, which returns the first active foo record:
class FooController < ApplicationController
def current
#user = User.find(params[:user_id])
#foo = #user.foos.where(:active => true).first
#use the Show View
respond_to do |format|
format.html { render :template => '/foos/show' }
end
end
#RESTful actions
...
end
The Foo Model :belongs_to the User Model and the User Model :has_many Foos.
If I structure the routes as such:
resources :users do
resources :foos do
member do
get :current
end
end
end
The resulting route is '/users/:user_id/foos/:id'. I don't want to specify the foo :id, obviously.
I've also tried:
map.current_user_foo '/users/:user_id/current_foo', :controller => 'foos', :action => 'current'
resources :users do
resources :foos
end
The resulting route is more like I would expect: '/users/:user_id/current_foo'.
When I try to use this route, I get an error that reads:
ActiveRecord::RecordNotFound in FoosController#current
Couldn't find Foo without an ID
edit
When I move the current action to the application controller, everything works as expected. The named route must be conflicting with the resource routing.
/edit
What am I missing? Is there a better approach for the routing?
I think you want to define current on the collection, not the member (the member is what is adding the :id).
try this.
resources :users do
resources :foos do
collection do
get :current
end
end
end
Which should give you a route like this:
current_user_foos GET /users/:user_id/foos/current(.:format) {:controller=>"foos", :action=>"current"}
Also map isn't used anymore in the RC, it will give you a deprecation warning.