Cameron Bass Cameron Bass - 4 months ago 22
Ruby Question

Understanding rails routes

I getting very confused about how rails routing works. I have a very simple app at this point so should be easy to debug. Here is my problem - I have a controller that is trying to call a show action, but it seems to be overriding another action that I'm calling in the same controller. As far as I can tell from rake routes is that if the url read this

localhost.com/subscribers/1
that should render the id of the subscriber that I'd like to view but I also have a url that get called like this
localhost.com/subscribers/visit
so effectively none of these page work now? I really don't know what's happening here so any help would be great! Here is my code.

CONTROLLER



class SubscribersController < ApplicationController
helper_method :sort_column, :sort_direction

def index
@search = Subscriber.search(params[:q])
@subscriber = @search.result
@search.build_condition if @search.conditions.empty?
@search.build_sort if @search.sorts.empty?
end

def show
@subscriber = Subscriber.find_by(id: params[:id])
end

def new
@subscriber = Subscriber.new
end

def create
@subscriber = Subscriber.new(subscriber_params)
if @subscriber.save
@subscriber.touch(:subscription_date)
SubscriberMailer.welcome_subscriber(@subscriber).deliver_now
flash[:notice] = "Subscriber Has Been Successfully Created"
redirect_to new_subscriber_path(:subscriber)
else
render "new"
end
end

def search
@subscriber = Subscriber.new
end

def visit
@subscriber = Subscriber.find_by_phone_number(params[:phone_number])
if @subscriber
@subscriber.visit ||= 0
@subscriber.visit += 1
@subscriber.save
render "visit"
end
end


ROUTES:



devise_for :users
resources :subscribers
resources :comments, only: [:new, :create]

get "subscribers/search", to: "subscribers#search"
get "subscribers/visit", to: "subscribers#visit"

root "subscribers#new"


RAKE ROUTES:



subscribers GET /subscribers(.:format) subscribers#index
POST /subscribers(.:format) subscribers#create

new_subscriber GET /subscribers/new(.:format) subscribers#new
edit_subscriber GET /subscribers/:id/edit(.:format) subscribers#edit
subscriber GET /subscribers/:id(.:format) subscribers#show
PATCH /subscribers/:id(.:format) subscribers#update
PUT /subscribers/:id(.:format) subscribers#update
DELETE /subscribers/:id(.:format) subscribers#destroy
comments POST /comments(.:format) comments#create
new_comment GET /comments/new(.:format) comments#new
subscribers_search GET /subscribers/search(.:format) subscribers#search
subscribers_visit GET /subscribers/visit(.:format) subscribers#visit


Am I doing something fundamentally wrong here? Please help me out!

Answer

The router tries to match the routes going from the top of routes.rb to the bottom, and uses the first route that matches.

In your case, /subscribers/visit matches /subscribers/:id - the router thinks it's the show action for a subscriber with the ID visit.

If you move your custom paths above your resources :subscribers in the routes file, you'll achieve the behaviour you're expecting.

Comments