Routing Error - custom controller - ruby-on-rails

I have a has many through association.
Firms have many Users through Follows.
I want Users to be able to Follow Firms. - I am using Devise for the users.
I have the following action in my firms controller.
def follow
#firm.users << current_user
end
in my routes.rb
resources :firms do
post :follow, on: :member
end
and in my firms view
<%= link_to "Follow", follow_firm_path(#firm), method: :post %>
However when I keep getting the following Routing Error in the browser
No route matches {:action=>"follow", :controller=>"firms"}
Rake Routes confirms the following
follow_firm POST /firms/:id/follow(.:format) firms#follow
Any ideas what the problem may be?
Many thanks
Edit: Controller code
class FirmsController < ApplicationController
before_filter :authenticate_user!, :except => [:show, :index]
def index
#firm_names = Firm.all.map &:name
direction = params[:direction]
direction ||= "ASC"
#firms = Firm.order("name #{direction}")
respond_to do |format|
format.html # index.html.erb
format.js
end
end
def follow
#firm.users << current_user
end
I am using the follow action in a partial in the index view.

everything looks good and this should work perfectly. Except that I see a typo in the following line
<%= link_to "Follow", follow_firm_path(#firm), method: :post %>
after the :method there should an => not a : . this will make the link a get request not a post request, that might be the issue, try using a simple link and replace post will get in your routes.rb just to test if the issue is arising due to this.
you can also test route methods from the console
rails c
app.follow_firm_path(2)
I noticed you also have an error in your routes, there should be an => not a : after :on
resources :firms do
post :follow, :on => member
end

You should define methods like this...
resources :firms do
collection
post :follow, on: :member
end
end
I think if this method does not create anything its type should be get.
Try it

Related

Routing error for rails - uninitialized constant SubscribersController

I have a Subscriber model that takes in a "phone_number" and a "visit" integer. I have two controllers Subscribers and Visits(super and sub) I have never worked with nested controllers before and I'm having some issues with namespace I believe. Because I getting back the uninitialized constant error. Basically the subscriber controller signs up a subscriber and the visit controller counts the amount of times they've visited by user input of their phone_number. Why am I getting this error? I'll show my code for clarity.
CONTROLLERS
class Subscribers::VisitsController < ApplicationController
def new
#subscriber = Subscriber.new
end
def create
#subscriber = Subscriber.find_by_phone_number(params[:phone_number])
if #subscriber
#subscriber.visit += 1
#subscriber.save
redirect_to subscribers_visits_new_path(:subscriber)
else
render "new"
end
end
end
class SubscribersController < ApplicationController
def index
#subscriber = Subscriber.all
end
def new
#subscriber = Subscriber.new
end
def create
#subscriber = Subscriber.create(subscriber_params)
if #subscriber.save
flash[:success] = "Subscriber Has Been successfully Created"
redirect_to new_subscriber_path(:subscriber)
else
render "new"
end
end
ROUTES
Rails.application.routes.draw do
devise_for :users
resources :subscribers, except: :show
get '/subscribers/visits/new', to: 'subscribers/visits#new'
root "welcomes#index"
VIEWS
<h1>hey</hey>
<%= form_for #subscriber do |form| %>
<div class="form-group">
<p>
<%= form.label :phone_number %>
<%= form.text_field :phone_number %>
</p>
<% end %>
ERROR
Hmm, my guess is you are trying to route url subscriber/visits/new to new action in VisitsController?How about changing this line:
get '/subscribers/visits/new', to: 'subscribers/visits#new'
to:
namespace :subscribers do
get '/visits/new', to: 'visits#new'
end
Also try to move this block above resources :subscribers, except: :show if you still get the error.
Cheers
You probably do not need to inherit one controller from another. Simply define the controllers as you normally would:
app/controllers/subscribers_controller.rb
class SubscribersController < ApplicationController
# methods for Subscribers
end
in app/controllers/visits_controller.rb
class VisitsController < ApplicationController
# methods for Visits
end
Note that these must to be located in separate files, so that Rails can find the correct source file by the name of the object that it's looking for. This is a Rails naming convention.
Regarding your routes, you'll need to change to use one of 4 route formats. Reading the section on Adding More RESTful Actions in the Rails Routing from the Outside In guide might help.
1) To route visits as a nested resource, which is what it appears you're actually trying to do, you would use this:
resources :subscribers, except: :show do
resources :visits
end
This will produce these routes:
GET /subscribers/new
POST /subscribers
GET /subscribers
GET /subscribers/:id/edit
PATCH /subscribers/:id/update
DELETE /subscribers/:id/destroy
GET /subscribers/:id/visits/new
POST /subscribers/:id/visits
GET /subscribers/:id/visits
GET /subscribers/:id/visits/:id
GET /subscribers/:id/visits/:id/edit
PATCH /subscribers/:id/visits/:id/update
DELETE /subscribers/:id/visits/:id/destroy
This is the typical route structure for nested resources and separate controllers.
2) To make visits#new a simple collection (non-member) action in the VisitsController, then you likely want this:
resources :subscribers, except: :show do
collection do
get 'visits/new', to 'visits#new'
post 'visits', to 'visits#create'
end
end
This will produce these routes:
GET /subscribers/new
POST /subscribers
GET /subscribers
GET /subscribers/:id/edit
PATCH /subscribers/:id/update
DELETE /subscribers/:id/destroy
GET /subscribers/visits/new
POST /subscribers/visits
This is typically used to add new top-level routes in an existing resource and controller.
3) To construct visits as member actions, use this:
resources :subscribers, except: :show do
member do
get 'visits/new', to 'visits#new'
post 'visits', to 'visits#create'
end
end
This will produce these routes:
GET /subscribers/new
POST /subscribers
GET /subscribers
GET /subscribers/:id/edit
PATCH /subscribers/:id/update
DELETE /subscribers/:id/destroy
GET /subscribers/:id/visits/new
POST /subscribers/:id/visits
This is normally used to add new member routes in an existing resource and controller.
4) To simply make visits routes appear to be included in subscribers, you could use this:
get '/subscribers/visits/new', to: 'visits#new'
post '/subscribers/visits', to: 'visits#create'
resources :subscribers, except: :show
This will produce these routes:
GET /subscribers/visits/new
POST /subscribers/visits
GET /subscribers/new
POST /subscribers
GET /subscribers
GET /subscribers/:id/edit
PATCH /subscribers/:id/update
DELETE /subscribers/:id/destroy
This may be used to make arbitrary routes appear to be included in an existing resource, when they really may be independent.

Thumbs up gem routing error

I seek clarification on using the thumbs up gem with rails 4. I current have a user resource and a post resource and have set up thumbs up as follows.
add gem to gemfile and installed it using bundler.
Generated require migration
User model
class User < ActiveRecord::Base
acts_as_voter
end
Post model
class Post < ActiveRecord::Base
acts_as_voteable
end
Post controller
def vote_up
#post = Post.find(params[:id])
current_user.vote_for(#post)
respond_to do |format|
format.js
end
end
View
<%= link_to('vote for this post!', vote_up_post_path(#post) , :method => :post) %>
Route file
resources :posts do
member do
post :vote_up
end
end
However i keep getting this error
No route matches [POST] "/posts/vote_up"
And after running rake routes I can see that the following route is available to me:
vote_up_post POST /posts/:id/vote_up(.:format) posts#vote_up
any ideas what could be the cause of this error ?
Could you please show us your view.
Apparently, you are calling
/posts/vote_up
instead of
/posts/:id/vote_up
"vote_up" acts like a RESTful action, similar to "post/1/delete", "post/1/edit". So you need to add this custom RESTful action in route.
Change your route like this at first.
resources :posts do
member do
post 'vote_up'
end
end
Then, in your view, to use this path, add resource as arg
vote_up_post_path #post
Reference: http://guides.rubyonrails.org/routing.html#adding-more-restful-actions
Other people reading this notes should realise that post is not a singluar of his controller posts... but the post http verb
resources :contenders do
member do
post 'vote_up'
end
end
Not sure but in your view, instead of #post try giving #post.id to vote_up_post_path.
<%= link_to('vote for this post!', vote_up_post_path(#post.id) , :method => :post) %>

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.

Ruby on Rails: How to override the 'show' route of a resource?

Currently I have a route that looks like this:
resources :posts
I want to override the 'show' action so that I can display a url like this:
posts/:id/:slug
I am currently able to do this by adding a custom match route:
resources :posts
match 'posts/:id/:slug' => 'posts#show'
However, when I use the link_to helper, it does not use my custom show route.
<%= link_to 'show', post %> # renders /posts/123
How can I define my show route so that I can still use the link_to helper?
Update: As you can read in the following answers, you can override the route to the 'show' action, but it's probably more work than it's worth. It's easier to just create a custom route:
# config/routes.rb
match 'posts/:id/:slug' => 'posts#show', as: 'post_seo'
# app/views/posts/index.html.erb
<%= link_to post.title, post_seo_path(post.id, post.slug) %>
You have two routes which point to posts#show (you should be able to confirm this by running rake routes), and your link is using the wrong one.
When you call link_to('show', post) the URL of the link is generated by calling url_for(post) which (eventually, after passing through several other methods on the way) calls post_path(post). Since the route to posts#show that was created by your call to resources(:posts) is named post, that is the route that post_path generates.
You also currently have inconsistent routes for the show, update and destroy actions which will probably cause you problems later on.
You can fix this by changing your routes to the following:
resources :posts, :except => ['show', 'update', 'destroy']
get 'posts/:id/:slug' => 'posts#show', :as => 'post'
put 'posts/:id/:slug' => 'posts#update'
delete 'posts/:id/:slug' => 'posts#destroy'
Unfortunately you still can't use link_to('show', post) just yet, because it relies on being able to use post.to_param as the single argument needed to build a path to a post. Your custom route requires two arguments, an id and a slug. So now your link code will need to look like this:
link_to 'show', post_path(post.id, post.slug)
You can get around that problem by defining your own post_path and post_url helpers in app/helpers/posts_helper.rb:
module PostsHelper
def post_path(post, options={})
post_url(post, options.merge(:only_path => true))
end
def post_url(post, options={})
url_for(options.merge(:controller => 'posts', :action => 'show',
:id => post.id, :slug => post.slug))
end
end
Which means we're finally able to use:
link_to 'show', post
If that all seems like too much work, a common alternative is to use URLs that look more like posts/:id-:slug, in which case you can stick with the standard RESTful routes and just override the to_param method in your Post class:
def to_param
"#{id}-#{slug}"
end
You'll also need to do a little bit of work splitting up params[:id] into an ID and a slug before you can look up the relevant instance in your show, edit, update and destroy controller actions.
resources :posts, except: :show do
get ":slug" => :show, as: "", on: :member
end
and define helper
def post_path post
"/posts/#{post.id}/#{post.slug}"
end
db/migrate/add_slug_to_articles.rb
add_column :articles, :slug, :string
add_index :articles, :slug
models/article.rb
class Article < ActiveRecord::Base
extend FriendlyId
friendly_id :name, use: :slugged
def should_generate_new_friendly_id?
new_record?
end
end
Or...
class Article < ActiveRecord::Base
extend FriendlyId
friendly_id :name, use: :history
end
http://railscasts.com/episodes/314-pretty-urls-with-friendlyid
https://github.com/norman/friendly_id

Resourceful Routes helpers _path and _url dont work

I am trying to redirect user to show_city_url or show_city_path but i get an exception that they are both undefined.In the city controller i have three actions show,like, and dislike. unlike_city_path and like_city_path works but show_city_path doesnt.Also when i put this in all_cities action redirect_to :controller=>"city",:action=>"show" works.What am i doing wrong?Thank you.
class HomeController < ApplicationController
def all-cities
redirect_to show_city_url
end
end
In the Routes
resources :city do
member do
post :like
post :dislike
get :show
end
end
according to your comments:
resources :cities, :controller => 'city' do
collection do
get :show, :as => :show
end
member do
post :like
post :dislike
end
end
now you can call show_cities_url and you'll land in the show action of your CityController.
PS: Following the Rails' convention makes your life easier ;)
RoR Guide: Rails Routing from the Outside In

Resources