Search code examples
ruby-on-railscustom-routes

Rails Routing Precedence favors the first


So Ive been working on a rails project that defines two different create actions in the same controller. Here's my controller:

class SmsSendsController < ApplicationController
  def new
    @at = SmsSend.new
    @contact = Contact.find_by(id: params[:id])
  end
  def create
    @at = SmsSend.create(sms_params)
    if @at.save!
    @con = current_user.contacts.find_by(id: @at.contact_id)
    AfricasTalkingGateway.new("trial-error").sendMessage(@con.phonenumber, @at.message)
    end
  end
  def new_all
    @at = SmsSend.new
    @contact = Contact.find_by(id: params[:id])
  end
  def create_all
    @at = SmsSend.create(sms_params)
    if @at.save!
    current_user.contacts.each do |c|
      AfricasTalkingGateway.new("trial-error").sendMessage(c.phonenumber, @at.message)
    end
    end
 end

  private
  def sms_params
    params.require(:sms_send).permit(:mobile, :message, :contact_id)
  end
end

In my

routes.rb

file, Ive used both custom and resourceful routes to define routes for the first and the second new/create actions:

Rails.application.routes.draw do
  devise_for :users
  get 'sms_sends/new_all', to: 'sms_sends#new_all'
  post 'sms_sends', to: 'sms_sends#create_all'
  resources :contacts
  resources :sms_sends
  root 'contacts#index'
end

So both post actions will work if and only if its routes are placed before the other. Is there a way I can get rid of the precedence? Or where am I going wrong?

Thankie.


Solution

  • So both post actions will work if and only if its routes are placed before the other.

    That is how you should define for the routes to work. Because the routes that defined in the routes.rb will be compiled from top-to-bottom. So if your custom routes gets preceded by resourceful routes, then the custom routes will conflict with your resourceful routes.

    Is there a way I can get rid of the precedence?

    Define them as collection routes like so,

    resources :sms_sends do
      get 'sms_sends/new_all', to: 'sms_sends#new_all', on: :collection
      post 'sms_sends', to: 'sms_sends#create_all', on: :collection
    end
    

    The above will generate routes with path helpers like below

    sms_sends_new_all_sms_sends   GET    /sms_sends/sms_sends/new_all(.:format)   sms_sends#new_all
    sms_sends_sms_sends           POST   /sms_sends/sms_sends(.:format)           sms_sends#create_all
    

    For a better readability, you can change your custom routes like so

    resources :sms_sends do
      get 'new_all', to: 'sms_sends#new_all', on: :collection
      post 'create_all', to: 'sms_sends#create_all', on: :collection
    end
    

    This will generate the path helpers like below

    new_all_sms_sends             GET    /sms_sends/new_all(.:format)      sms_sends#new_all
    create_all_sms_sends          POST   /sms_sends/create_all(.:format)   sms_sends#create_all