routing with non rest actions - ruby-on-rails

im having some trouble creating a route for my non restfull action in my controller, here is my code:
controller:
class StoresController < ApplicationController
def toggle_store
#store=Store.find(params[:store])
if #store.available==true
#store.update_attribute(:available, false)
else
#store.update_attribute(:available, true)
end
redirect_to #store
end
end
routes:
resources :groups do
resources :stores do
member do
post :toggle_store
end
end
end
but when i use the path in a link i get this url: http://example.com/groups/1/stores/toggle_store.2
and i need something like this:
http://example.com/groups/1/stores/2/toggle_store
any ideas?
Thanks
EDIT:
rake routes:
toggle_store_group_store POST /groups/:group_id/stores/:id/toggle_store(.:format) stores#toggle_store
Link:
<%=link_to "toggle", toggle_store_group_stores_path(#group,store), :method => :post %>

ok i fixed it like this:
routes.rb:
resources :groups do
resources :stores do
post :toggle_store
end
end
controller:
def toggle_store
authorize! :toggle, :store
#store=Store.find(params[:store_id])
if #store.available==true
#store.update_attribute(:available, false)
else
#store.update_attribute(:available, true)
end
redirect_to #group
end
link:
<%=link_to "to", toggle_store_group_store_path(#group,store), :method => :post %>

Related

Routing to delete in my restful web service is not working

I am having an problem routing to my delete method on my restful web service for permissions.
My routes are set up as follows :
namespace :service do
namespace :v1 do
resources :surveys do
resources :permissions, only: [:index, :create, :delete, :update]
end
end
end
The following spec passes
it "routes toya expected controller method" do
{:get => 'service/v1/surveys/3/permissions'}.should route_to(controller: 'service/v1/permissions', action: 'index', :survey_id => "3")
end
This spec fails
describe 'DELETE :destroy' do
it "routes to expected controller method" do
{:delete => 'service/v1/surveys/3/permissions'}.should route_to(controller: 'service/v1/permissions', action: 'destroy', :survey_id => "3")
end
end
The snippet from my controller is as follows
module Service
module V1
class PermissionsController < ApplicationController
before_filter :authenticate_user!, :only => []
def index
render :json => permissions, :each_serializer => Service::V1::PermissionSerializer
end
def destroy
debugger
# cant route to here
a = 1
end
end
end
end
Any suggestions ? I am slightly confused between destroy and delete, I think that might be the source of my problem
You need to pass permission id as well like:-
{:delete => 'service/v1/surveys/3/permissions/permission_id'}.should route_to(controller: 'service/v1/permissions', action: 'destroy', :survey_id => "3", :id => "permission_id")

acts_as_votable redirecting when trying to vote up/vote down

I've problem with acts_as_votable gem. I have simple forum app and I want to have feature to vote up and down posts. I used for this acts_as_votable gem. I've added to posts controllers two methods:
def upvote
#post = post.find(params[:id])
#post.liked_by current_user
redirect_to forum_topic_path(#post.topic.forum, #post.topic)
end
def downvote
#post = post.find(params[:id])
#post.downvote_from current_user
redirect_to forum_topic_path(#post.topic.forum, #post.topic)
end
My routes is :
resources :topics, except: :index do
resources :posts do
member do
put "like", to: "posts#upvote"
put "dislike", to: "posts#downvote"
end
end
end
And in my topic show action view i have the followings links:
= link_to "Upvote", like_topic_post_path(post.topic.id,post.id, method: :put)
= link_to "Downvote", dislike_topic_post_path(post.topic.id,post.id, method: :put)
When I'm trying to click upvote or downvote i have been redirected to:
http://localhost:3000/topics/104/posts/55/like?method=put and i have following error:
No route matches [GET] "/topics/104/posts/55/like"
What's wrong?
Try "GET" method instead of "PUT" as shown below,
resources :topics, except: :index do
resources :posts do
member do
get "like", to: "posts#upvote"
get "dislike", to: "posts#downvote"
end
end
end
I'd change the PostsController code for redirect to:
redirect_to :back
If you are using Rails 5 this is better:
redirect_back(fallback_location: root_path)

Routing error No route matches id nil (Rails)

I'm getting the following error on a page that contains a link to credit/edit an object:
Routing Error
No route matches {:controller=>"connections", :action=>"edit", :id=>nil}
My app has user profile pages (#show action in users_controller.rb) with a link to create or edit an existing "connection" (a relationship between users like Facebook or LinkedIn). If the connection does not exist, the link will send the user to create a new connection. If the connection already exists, the link will send the user to edit the existing connection. My create functionality works fine. However, once the connection has been created, visiting the user page throws the routing error. It clearly does not like my link_to for the edit action.
Here is the link_to on the user page:
<% unless current_user == #user %>
<% if #contact.present? %>
<%= #user.first_name %> is your <%= #connection.description %> (<%= link_to "edit contact", { :controller => 'connections', :action => 'edit', :id => #connection.id} %> )
<% else %>
How do you know <%= #user.first_name %>? (<%= link_to "edit contact", { :controller => 'connections', :action => 'create', :user_id => #user.id }, :method => 'post' %> )
<% end %>
The error also specifically states that :id is set to nil (null). The problem must be here. How can I my app to refer to the correct connection? My instance variable should have done the trick.
Here's the connection controller:
class ConnectionsController < ApplicationController
def index
end
def update
#connection = current_user.connections.find(params[:id])
if #connection.update_attributes(params[:connection])
flash[:notice] = "Contact relationship updated"
render 'activities'
end
end
def edit
#connection = current_user.connections.find(params[:id])
end
def create
##user = User.find(params[:user_id])
#connection = current_user.connections.build(params[:connection])
#user = User.find(params[:user_id])
if #connection.save
flash[:success] = "Contact relationship saved!"
else
render #user
end
end
end
And here's the User controller show action (where the link_to exists):
def show
#user = User.find(params[:id])
#connection = current_user.connections.build(:otheruser_id => #user)
#contact = current_user.connections.where(user_id: current_user, otheruser_id: #user)
end
routes.rb:
authenticated :user do
root :to => 'activities#index'
end
root :to => "home#index"
devise_for :users, :controllers => { :registrations => "registrations" }
resources :users do
member do
get :following, :followers, :posts, :comments, :activities, :works, :contributions, :connections
end
end
resources :works do
resources :comments
end
resources :relationships, only: [:create, :destroy]
resources :posts
resources :activities
resources :reposts
resources :comments do
member do
put :toggle_is_contribution
end
end
resources :explore
resources :connections
Any ideas on how to fix the link_to? Thanks!
EDIT 1: relevant rake routes:
connections GET /connections(.:format) connections#index
POST /connections(.:format) connections#create
new_connection GET /connections/new(.:format) connections#new
edit_connection GET /connections/:id/edit(.:format) connections#edit
connection GET /connections/:id(.:format) connections#show
PUT /connections/:id(.:format) connections#update
DELETE /connections/:id(.:format) connections#destroy
Your problem is in:
#connection = current_user.connections.build(:otheruser_id => #user)
That instantiates a connection object and assigns it to #connection. This object hasn't been saved, therefore it doesn't have an id. Conceptually it's wrong too, how can you edit something that doesn't exist yet? If you want to send the user to create a new connection, Connections#new is what you're after.

Add new action to route

I got these actions in users controller
class UsersController < ApplicationController
def index #default action
...
end
def new #default action
...
end
def another_new
...
end
def create
...
end
def another_create
...
end
end
I want to be able to
/users/another_new and call from some sort of link :method => :another_create
to make /users/another_new
I got the following config/routes.rb
get '/users/another_new' :to => 'users#another_new'
resources :users
my question is if this is the correct way to add the get and how I add the another_create method.
in your config/routes.rb file do this
resources :users do
collection do
get 'another_new'
post 'another_create'
end
end
Also have a look HERE for clear understanding of concepts.
Hope this helps you dude :)
try this in routes.rb
match "/users/another_new " => "users#another_new", :as => 'another_new'
then you can do
link_to "MyUrl", another_new_path
this should work. Good luck.
Also note that you shouldn't have :method => :another_new. Your options for :method are :get, :put, :post, and :delete, and the one you use should match how you defined the action in routes.

DRY routing for one polymorph resource with nested resources

Given the following models:
class Blog < ActiveRecord::Base
has_many :posts
end
class SiteBlog < Blog
end
class ProjectBlog < Blog
end
class Post <ActiveRecord::Base
belongs_to :blog
end
And the following routes:
resources :blogs do
resources :posts
end
In say a form partial, the following will work fine if #blog is a Blog:
form_for [#blog, #post] ...
However, if #blog is a ProjectBlog or SiteBlog, it bombs since it will be looking for a URL helper such as project_blog_posts.
I guess something like this would solve this:
[:project_blogs, :site_blogs].each |blogs| do
resources blogs do
resources :posts
end
end
I'm wondering whether there's a way to use the routes for subclassed models (e.g. ProjectBlog) to use the routes of the parent model (Blog). The "as" option only deals with the last object passed like [#blog, #post] to form_for.
Update
As requested below, here are the routes:
resources :blogs, only: [:show] do
resources :posts, only: [:new, :create, :edit, :update]
end
blog_posts POST /blogs/:blog_id/posts(.:format) posts#create
new_blog_post GET /blogs/:blog_id/posts/new(.:format) posts#new
edit_blog_post GET /blogs/:blog_id/posts/:id/edit(.:format) posts#edit
blog_post PUT /blogs/:blog_id/posts/:id(.:format) posts#update
blog GET /blogs/:id(.:format) blogs#show
Update 2:
The tip from an answer below:
form_for [#blog, #post], url: blog_posts_path(#blog, #post) do |f|
This works for "new" actions only, for "edit" actions, I'd get - as expected - a bad URL:
params[:action] # => "edit"
blog_posts_path(#blog, #post) # => "/blogs/publikationsreihe-tafelrunde/posts.5"
So the "if" I mentioned would fix this:
form_for [#blog, #post], url: params[:action]=='new' ? blog_posts_path(#blog, #post) : blog_post_path(#blog, #post) do |f|
But this looks incredibly clumsy, there must be a better way.
Easily solvable by passing the resource url to the form:
<%= form_for [#blog, #post], :url => blog_posts_path(#blog, #post) do |f| %>
...
<%- end %>

Resources