I'm struggling with this line in the _form: <%= simple_form_for(#post, url: blog_path) do |f| %>, which gives me the error:
No route matches {:action=>"show", :controller=>"posts"} missing required keys: [:id]
Keep in mind that in my routes I have: resources :blog, controller: 'posts', which is to say I am working off of a posts MVC, but I wanted /posts/ to be replaced by /blog/ in the routes.
posts_controller
def new
#post = Post.new
end
def edit
end
The _form works when I go to edit, but not create new.
routes
blog_index GET /blog(.:format) posts#index
POST /blog(.:format) posts#create
new_blog GET /blog/new(.:format) posts#new
edit_blog GET /blog/:id/edit(.:format) posts#edit
blog GET /blog/:id(.:format) posts#show
PATCH /blog/:id(.:format) posts#update
PUT /blog/:id(.:format) posts#update
DELETE /blog/:id(.:format) posts#destroy
model_path by default routing logic in Rails leads to blog#show => /blogs/:id
Change it to blogs_path.
Looking at you routes, I see obvious naming conflict, you must be defined routes wrong.
Be sure it looks like resources :posts, :as=>"blogs", both plural.
UPD
If you want to have only one blog, then resource :post, :as=>"blog", both singular.
But that means one actual input. I'm quite sure you speak of blog/post1, blog/post2, otherwise I can't see any sense in calling it blog?
sorry my english...
<%= simple_form_for(#post, url: blog_path) do |f| %> In this line you are redirecting the form to show (blog_path)
But , depending on the route , the show needs an id (blog GET /blog/:id(.:format)).
You must create a "create" method in the controller that receives the parameters strong ...
There is another method you can use: rails generate scaffold_controller posts
This will build the full CRUD , so you only have to configure the parameters
I hope that helps you
I got best of both worlds this way:
resources :blog, to: 'posts'
resources :posts
Related
I am completely new to ruby, andI am following this ruby rails tutorial step by step, except for the detail that I've called my app "cinema".
I created a resource named "posts", there is a controller class called posts controller. From the page posts/new I should post a text with title, and execute an action (show). I am trying to add the show action in the routes file and in the controller class.
The show action should be called when a form is submitted, the form includes a title and a text field, mapped into the database.
In paragraph 5.7, there is a non-clear instruction: it says to add this line:
post GET /posts/:id(.:format) posts#show
To my routes.rb file, but it doesn't say where to write it exactly, I put it under resources:posts (maybe it's the wrong place, it doesn't saying anything about that).
I also added the show method to the controller class:
def show
#post = Post.find(params[:id])
end
private
def post_params
params.require(:post).permit(:title,:test);
end
But when I submit the form I still get this error:
The rake routes command result:
Prefix Verb URI Pattern Controller#Action
welcome_index GET /welcome/index(.:format) welcome#index
root GET / welcome#index
posts GET /posts(.:format) posts#index
POST /posts(.:format) posts#create
new_post GET /posts/new(.:format) posts#new
edit_post GET /posts/:id/edit(.:format) posts#edit
post GET /posts/:id(.:format) posts#show
PATCH /posts/:id(.:format) posts#update
PUT /posts/:id(.:format) posts#update
DELETE /posts/:id(.:format) posts#destroy
It doesn't tell you to add it to routes.rb. It's one of the routes that is created automatically with:
resources :posts
Remove the line from your routes.rb restart the server and continue with the tutorial.
Tip: you can run rake routes to see all available routes in your application.
Your whole question seems completely contradictory to me.
You never do this in rails routes -
post GET /posts/:id(.:format) posts#show
Instead in routes.rb file.
get 'posts/:id' => 'posts#show'
The routing is done on a priority basis (first come first serve), so if your are adding get 'posts/:id' after the resources :posts, it is of no use as resources :posts already does it for you (read the rails routing guide on resources).
Your form submission should be a post data, if you are using resources 'new' should be a 'get' data and the corresponding 'post' should be 'create'. Your 'new' route has an error, then where else are you rendering your form to submit the form data?
My suggestion is that you keep the 'resources :post' and remove every other this corresponding to your :post from routes file. If you have everything else right then it should probably work fine.
resources :posts
delete it
rails s
paste resources :posts
rails s
I make it and success
Edit: I've seen a number of these but couldn't find an answer to this so I'm attempting to document it as best I can and asking this question.
I have a model-less rails app (calling an API) with a nested comments resource. I am able to post a comment against a story if I go directly to the comments#new or comments#index action and accordingly post to the comments#create action.
However I'd like very much to be able to post a comment on the same page as the #show action of the parent resource: (opusses#show)
I've tried using the rails url_helper path from rake routes as opuss_comments_path and explicitly stating the controller and action. In both cases I still get this message:
No route matches {:controller=>"comments", :action=>"create"}
Here is my routes db:
resources :users
resources :sessions, only: [:new, :create, :destroy]
resources :osessions, only: [:new, :create, :destroy]
resources :authors do
member do
get :following
get :followed
post :follow
end
end
resources :opusses do
resources :comments
member do
get :like
get :authorfeed
post :repost
end
end
And my Rake Routes:
DELETE /authors/:id(.:format) authors#destroy
opuss_comments GET /opusses/:opuss_id/comments(.:format) comments#index
POST /opusses/:opuss_id/comments(.:format) comments#create
new_opuss_comment GET /opusses/:opuss_id/comments/new(.:format) comments#new
edit_opuss_comment GET /opusses/:opuss_id/comments/:id/edit(.:format) comments#edit
opuss_comment GET /opusses/:opuss_id/comments/:id(.:format) comments#show
PUT /opusses/:opuss_id/comments/:id(.:format) comments#update
DELETE /opusses/:opuss_id/comments/:id(.:format) comments#destroy
&&
like_opuss GET /opusses/:id/like(.:format) opusses#like
authorfeed_opuss GET /opusses/:id/authorfeed(.:format) opusses#authorfeed
repost_opuss POST /opusses/:id/repost(.:format) opusses#repost
opusses GET /opusses(.:format) opusses#index
POST /opusses(.:format) opusses#create
new_opuss GET /opusses/new(.:format) opusses#new
edit_opuss GET /opusses/:id/edit(.:format) opusses#edit
opuss GET /opusses/:id(.:format) opusses#show
PUT /opusses/:id(.:format) opusses#update
DELETE /opusses/:id(.:format) opusses#destroy
When I call the code below from comments#index page it works perfectly. However it's quite common to post to another form from a different controller and when I call this code from the opusses#show page it fails with the error above.
On the off chance it had to do with the URL helper, I tried specifying the controller and action explicitly and that still didn't work - generated the same error.
Classic newbie mistake, but for others benefit =>
I had rake routes and I had the path correct, what I wasn't doing was submitting a the id of the parent resource. So POST to the path and include the object in question. In my case this mean opuss_comments_path(#opuss["xyz"]) where xyz was the id of my object.
opuss_comments GET /opusses/:opuss_id/comments(.:format) comments#index
POST /opusses/:opuss_id/comments(.:format) comments#create
Ah.. learning. :)
Based on your routes, You shouldn't have to use a url helper. but you do have to make sure that you have a handle on the Opuss object in the controller. so do something like this ;
#opuss = Opuss.find(params[:id]) #or your equivalent finder code
#comment = #opuss.comments.build
and then in your view;
<%= form_for([#opuss, #comment]) do |f| %>
.... rest of form
<% end %>
I have a Wizard model that the client references w/o an ID (it's saved in the session), so I've created a singular resource for :show and :update. I want the admin to have access to all instances of that model via index so admin can delete strays, so I've added a plural resources for :index and :destroy. The index and destroy works, but I can't figure out the right arguments to pass to form_for in the update view.
The setup
# config/routes.rb
WTest::Application.routes.draw.do
resource :wizard, :only => [:show, :update]
resources :wizards, :only => [:index, :destroy]
...
end
resulting in
$ rake routes
wizards GET /wizards(.:format) {:action=>"index", :controller=>"wizards"}
wizard DELETE /wizards/:id(.:format) {:action=>"destroy", :controller=>"wizards"}
GET /wizard(.:format) {:action=>"show", :controller=>"wizards"}
PUT /wizard(.:format) {:action=>"update", :controller=>"wizards"}
This sets up routes the way I'd expect.
The question (revised since original post)
In the console:
>> app.wizard_path
raises the error ActionController::RoutingError: No route matches {:action=>"destroy", :controller=>"wizards"}
Why is this? Have I set up my routes incorrectly? I need to specify :url => wizard_path for form_for() in the wizards's update view.
The details
If I specify an explicit path in my call to form_for:
# app/view/wizards/update.html.erb
<%= form_for #wizard, :url => wizard_path do |f| %>
<%= f.submit %>
<% end %>
... then attempting to render this for gets an error on the form_for line:
No route matches {:action=>"destroy", :controller=>"wizards"}
I have no idea why it's trying to match the destroy action. How do I get the form to submit to the {action=>"update", :controller=>"wizards"} route?
(By the way, I looked at bug 267, and I don't think it is the same as what I'm observing. But if it is this bug, is there a workaround?)
Carrying on the long tradition of answering my own questions (meh!), I think I figured it out. If my analysis is wrong, I'd be happy to give someone else the checkmark...
The cause of the problem
Look at the output of rake routes
$ rake routes
wizards GET /wizards(.:format) {:action=>"index", :controller=>"wizards"}
wizard DELETE /wizards/:id(.:format) {:action=>"destroy", :controller=>"wizards"}
GET /wizard(.:format) {:action=>"show", :controller=>"wizards"}
PUT /wizard(.:format) {:action=>"update", :controller=>"wizards"}
The path method 'wizard_path' is ambiguous: it can either refer to the DELETE clause, in which case it needs an :id argument (wizard_path(22)), or it can refer to the GET and PUT clauses, in which case it doesn't take an ID argument.
The solution
So my solution was to create a route specifically for deletion. My revised routes.rb file now reads:
resources :wizards, :only => [:index]
resource :wizard, :only => [:show, :update]
match 'wizard/:id' => 'wizards#destroy', :via => :delete, :as => :delete_wizard
and rake routes now produces:
$ rake routes
wizards GET /wizards(.:format) {:action=>"index", :controller=>"wizards"}
wizard GET /wizard(.:format) {:action=>"show", :controller=>"wizards"}
PUT /wizard(.:format) {:action=>"update", :controller=>"wizards"}
delete_wizard DELETE /wizard/:id(.:format) {:controller=>"wizards", :action=>"destroy"}
I needed to make a one-line change to the delete link in wizards/index.html.erb to use the new delete_wizard_path, but everything works now.
I'm getting into Rails and trying to add a "vote" feature on a blog setup from here: http://guides.rubyonrails.org/getting_started.html
In app/controllers/posts_controller.rb I created this:
def incvotes
#post = Post.find(params[:id])
post.update_attributes(:upvotes => 1 )
format.html { redirect_to(#post, :notice => 'Vote counted.') }
format.xml { head :ok }
end
In app/views/posts/index.html.erb I created this:
<%= link_to 'Vote', :controller => "posts", :action => "incvotes", :id => post.id %>
But the link is giving the error
No route matches {:controller=>"posts", :action=>"incvotes", :id=>1}
I'm missing something here, but not sure what.
rake routes:
incvotes_post POST /posts/:id/incvotes(.:format) {:action=>"incvotes", :controller=>"posts"}
posts GET /posts(.:format) {:action=>"index", :controller=>"posts"}
POST /posts(.:format) {:action=>"create", :controller=>"posts"}
new_post GET /posts/new(.:format) {:action=>"new", :controller=>"posts"}
edit_post GET /posts/:id/edit(.:format) {:action=>"edit", :controller=>"posts"}
post GET /posts/:id(.:format) {:action=>"show", :controller=>"posts"}
PUT /posts/:id(.:format) {:action=>"update", :controller=>"posts"}
DELETE /posts/:id(.:format) {:action=>"destroy", :controller=>"posts"}
home_index GET /home/index(.:format) {:action=>"index", :controller=>"home"}
root /(.:format) {:action=>"index", :controller=>"home"}
try
= link_to "vote", incvotes_post_path(post), :method=>:post
and if that doesn't work, try changing the method to :put
My guess is that you probably do not have a definition in your routes file for the action you just defined in the controller. Both an action in the controller and an action in the routes file must be defined for Rails to generate urls correctly.
Your routes file probably has something like this:
resources :posts
But you want to add more than the standard actions generated by the resources keyword, so try something like this:
resources :posts do
member do
post 'incvotes'
end
end
This tells routes that you have another action in your posts controller called incvotes that accepts HTTP post requests as long as they are pointed at a member route with the correct action (/posts/14 is a member route, while /posts/ is a 'collection' route). So you will have a new route probably like /posts/14/incvotes that you can post a form to and everything should start working properly.
EDIT:
Actually I guess since you are just adding 1 to an attribute on a model, you don't need a POST action (which are normally associated with posting forms as with create and update). To send a post, you might need to change the HTML in the view to include a form and have it post to the correct url. So you can try that, or you can change your routes file to read get 'incvotes' instead of post 'incvotes'. Sorry for the confusion, hope that helps!
The incvotes_post route only accepts a HTTP POST, and a link always produces a HTTP GET.
Use a form with a button instead (or do a POST using AJAX).
Try using button_to instead link_to:
In your view:
<%= button_to 'Vote', incvotes_post_path(post) %>
In your config/routes.rb add the route to incvotes action as post:
resources :posts do
member do
post 'incvotes'
end
end
And in your controller, create the incvotes action:
def incvotes
# Something
redirect_to :posts
end
I'm setting up friendships within a RoR website. The model for it is user_id, friend_id, and pending (boolean). I followed the RailsCast on friendships for the most part, but making some changes to it too. What I have so far is that when you go to a user's page you can click Request Friendship and the code uses:
user_friendships_path(current_user, :friend_id => #user), :method => :post
This calls the create method in the Friendships controller. It automatically sets pending to true. What I want now is to have a link to Accept it which would just turn pending to false. So I am trying to set it up like
(<%= link_to "Accept", user_friendship_path(:user_id => current_user.id, :friend_id => friendship.user.id, :pending => 'false'), :method => :put %>)
I don't actually want to go to the edit page, because it just needs to set that boolean to false, so I want to call the update directly. But when I run this page, I get the error:
No route matches {:action=>"destroy", :controller=>"friendships", :user_id=>1, :friend_id=>2, :pending=>"false"}
I don't understand why. I'm not calling the destroy (that would be with :method => :delete), and there actually is a destroy method within the Friendship controller.
The resources are set up like:
resources :users do
resources :friendships
end
And the paths from running "rake routes" are:
user_friendships GET /users/:user_id/friendships(.:format) {:action=>"index", :controller=>"friendships"}
user_friendships POST /users/:user_id/friendships(.:format) {:action=>"create", :controller=>"friendships"}
new_user_friendship GET /users/:user_id/friendships/new(.:format) {:action=>"new", :controller=>"friendships"}
edit_user_friendship GET /users/:user_id/friendships/:id/edit(.:format) {:action=>"edit", :controller=>"friendships"}
user_friendship GET /users/:user_id/friendships/:id(.:format) {:action=>"show", :controller=>"friendships"}
user_friendship PUT /users/:user_id/friendships/:id(.:format) {:action=>"update", :controller=>"friendships"}
user_friendship DELETE /users/:user_id/friendships/:id(.:format) {:action=>"destroy", :controller=>"friendships"}
Any help would be greatly appreciated. Please let me know if you require more information.
Thanks.
The path that exists according to rake routes is
user_friendship PUT /users/:user_id/friendships/:id(.:format) {:action=>"update", :controller=>"friendships"}
The method you are using is put, but you aren't supplying ':id'.
There are two solutions depending on what you are trying to do:
Change the method to get - that will point you to the new action
Add :id to your URL builder - that will point you to the update action
Your code is leaning towards the second, but I think if you want to create a new friendship, the first would be better.
I'm baffled as to why the URL helper is mapping to a destroy action. However there is a simpler problem: user_friendship_path expects params :user_id and :id, not :friend_id.