I have created model, view and controller:
$ rails generate scaffold Post name:string title:string content:text
Then I have added the method on Post controller:
def fill_default_data
Post.fill_default_data
end
But when I have open http://localhost:3000/posts/fill_default_data in browser I get the error:
ActiveRecord::RecordNotFound in
PostsController#show
Couldn't find Post with
ID=fill_default_data
It looks like Rails don't see fill_default_data action and use show method. How can I add new method to scaffold generated controller?
You should add the relevant route to your config/routes.rb file. If you currently have:
resources :posts
You should change that to:
resources :posts do
collection do
get :fill_default_data
end
end
That will generate a route that you can access through /posts/fill_default_data. Now your app is actually accessing the show action and filling in "fill_default_data" as the ID.
Or if you want to add the method to a member rather than the collection, use the following:
resources :posts do
member do
get :fill_default_data, :as => 'fill_out_data'
end
end
This using member if preferred if you are performing the action on a single post rather than on a collection of posts. Also, the :as option generates named route helpers (stuff like *_path or *_url) in case you want them.
Related
I'm new to Ruby on Rails, I'm trying to create my first application. I'm using resourceful routes for instance 'subjects':
resource :subjects do
member do
get :delete
end
end
I've created controller SubjectsController and views for its methods. In index view I'm trying to create a link to show view like that:
link_to("Show", subject_path(1))
but it returns the error:
undefined method `subject_path' for #<#<Class:0x007fc820551488>:0x007fc8229468c0>
Did you mean? subjects_path
The same thing with helper 'new_subject_path'. But what weird new_subjects_path doesn't give any error and creates a proper link. What's wrong with my app? Should I use plurals for path helpers???
I believe your problem is because you are using the resource singular, when you mean to use the resources plural version. Try changing your routes to:
resources :subjects do
member do
get :delete
end
end
And you should find you get the expected rails url helper methods.
The convention is when you expect to have several items of the resources existing, to use the plural versions resources :subjects, but when you expect only a single entity to exist use the singular resource :subject which will create different routes and helpers that don't require an id param.
If you want singular resource, change :subjects to :subject.
resource :subject do
member do
get :delete
end
end
Or use full resources instead of resource:
resources :subjects do
member do
get :delete
end
end
With either change, you'll be able to use subject_path helper. But with the first one, you cannot pass in a ID. If you need that, use the second one.
To add a route to the collection photo I write :
resources :photos do
collection do
post 'myaction'
end
end
and this generates a path /photos/myaction. However, in case of the create action, Rails generates a path /photos not /photos/create. How can I configure my route.rb so that I could use photos_path instead of myaction_photos_path (just like the create action)?
I'm new with RoR so this is a newbie question:
if I have a controller users_controller.rb and I add a method foo, shouldn't it create this route?
http://www.localhost:3000/users/foo
because when I did that, I got this error:
Couldn't find User with id=foo
I of course added a view foo.html.erb
EDIT:
I added to routes.rb this code but I get the same error:
resources :users do
get "signup"
end
This doesn't work automatically in rails 3. You'll need to add
resource :users do
get "foo"
end
to your routes.rb
You'll definitely want to have a look at http://guides.rubyonrails.org/routing.html, it explains routing pretty well.
Rails is directing you to the show controller and thinks that you're providing foo as :id param to the show action.
You need to set a route that will be dispatched prior to being matched as /users/:id in users#show
You can accomplish this by modifying config/routes.rb by adding the following to replace your existing resource describing :users
resource :users do
get "foo"
end
Just to add to the other answers, in earlier versions of Rails there used to be a default route
match ':controller(/:action(/:id))(.:format)'
which gave the behaviour you describe where a request of the form controller/action would call the given method on the given controller. This line is still in routes.rb but is commented out by default. You can uncomment it to enable this behaviour but the comment above it explains why this is not recommended:
# This is a legacy wild controller route that's not recommended for RESTful applications.
# Note: This route will make all actions in every controller accessible via GET requests.
At the schema ':controller/:action(.:format)', you can also easily do the following
resources :users do
get "foo", on: :collection
end
or
resources :users do
collection do
get 'foo'
end
end
http://guides.rubyonrails.org/routing.html#adding-collection-routes
I'm still trying to get the hang of rails and i'm trying to create a simple app with a form where i can enter the data and then submit it and it will be stored in the db. I got this very simple by starting a new project and then running:
$ rails generate scaffold RSVP firstName:string lastName:string
Now i want to redirect to a thank you page after adding a new record via the form.
I've manually added the method below to my rsvps_controller.rb file:
# GET /rsvps/thank_you
def thank_you
respond_to do |format|
format.html # thank_you.html.erb
format.json { render json: #rsvps }
end
end
This line is in my routes file:
resources :rsvps
My question is, when i run rake routes, i don't see a route for my thank_you method. Shouldn't my :rsvps resource pick up my thank_you route and how does the routes know which controller method are which http calls(get, post, put, etc)?
In order to get a route that will hit that action in your controller you should have in your routes.rb file something like:
resources :rsvps do
member { get :thank_you }
end
or
resources :rsvps do
collection { get :thank_you }
end
it depends for if you want to access the resource you've just created or not.
You can take a look # http://guides.rubyonrails.org/routing.html it should help you understating the routing mechanism better.
Adding on to what wlad said, the resources :rsvps things in your routes.rb file creates a set of default routes that are going to be needed by most models. Things like index, new, create, or show. The reason your thank_you action isn't showing up in rake routes is because thank_you isn't one of the actions that were so common that they needed to be included out of the box without extra code.
If you are going to need to load a rsvp model on the thank you page to display any data in that model then you will need to use a member route. The :id in the route will be there because this is a resources member route and has to be associated with a particular resource. There has to be something in the url to know what to load.
resources :rsvps do
member { get :thank_you } #GET /rsvps/:id/thank_you(.:format)
end
If you just want a generic route that points to that controller action then you can use something like this:
match "/rsvps/thank_you" => "rsvps#thank_you", as: "rsvp_thank_you"
You can add more actions to any controller but rails will not treat this functions as actions unless you specify them in routes file. It will be treated as just another function in controller class created by user.
so if you want to add the thank_you function as action you need to add this to routes file.
There are multiple ways of doing so as others have explained in their answers.
adding-more-restful-actions
Using member and collection inside resources.
Use member when you want the function to be used only with the some model object.
eg: preview for photo id 1
GET /photos/:id/preview
In our example you member if you want such route and functionality.
GET /rsvps/:id/thank_you
Note :id in params is needed when you specify it as a member action.
resources :rsvps do
member do
get :thank_you #GET /rsvps/:id/thank_you(.:format)
end
end
Use collection if you want to call the action directly like
GET /rsvps/thank_you(.:format)
in resources
resources :rsvps do
collection do
get :thank_you #GET /rsvps/thank_you(.:format)
end
end
You need to specify the type of action (GET|POST) while adding it to routes.
In our example thank_you has been specified as a GET action. You can choose either.
You can create you own preety_urls or non restful routes using match.
(This will also require to have the action defined in resources block).
check out more on match here http://guides.rubyonrails.org/routing.html#non-resourceful-routes
I suggest you to go through this awesome documentation created by the rails team.(once more ;) ) http://guides.rubyonrails.org/routing.html
Cheers.
As you have said you just want to show a thank you page for each rsvp so a member route should be used. like this
resources :rsvps do
member get :thank_you
end
You should use collection of thank_you when you want to show all or some specific collection of thank_you.
when you include this and run rake routes again you will see the new http action there.
In my UserController I have:
def join
end
I have a join.html.erb in my /views/user/ folder.
My routes has a :
resources :user
When I go to:
http://localhost:3000/user/join
I get:
The action 'show' could not be found for UserController
Re: why isn't the join action found?
To answer your specific question, what's happening is that you want to have an action "join" for your User model.
Your problem is that you haven't defined a route matching the url http://localhost:3000/user/join
The line resources :user in your routes file only defines routes for the seven standard rest verbs/actions:
index, new, create, show, edit, update, destroy
See: http://apidock.com/rails/ActionController/Resources/resources
Added: to fix, you'll need to add an explicit or generic route. Routing docs
Added: Re: why am I seeing the error message re show? To be ultra-precise, the route selector "GET /usr/:id" (created by your resource call) is being used to select the SHOW action for the User resource. The :id value is being set to "join". Since you don't have a Show method defined in your controller, that's the error that you're seeing.
You're using resources, but have a non-REST action, so you need to add the join action to the route with the appropriate HTTP verb:
map.resources :users, :member => { :join => :get }
Place:
def show
end
in your UserController.
To be certain:
app/controllers/users_controller.rb
def join
end
app/views/users/join.html.erb
config/routes.rb
resources :users