Search code examples
ruby-on-rails-3ruby-on-rails-4routesportingcustom-routes

ruby on rails - routes error porting from 3.x to 4.x


i've started porting one of my apps from rails 3.x to rails 4.x....

when i start the app in development, i receive a route definition related error:

=> Booting WEBrick
=> Rails 4.2.5 application starting in development on http://localhost:3000
=> Run `rails server -h` for more startup options
=> Ctrl-C to shutdown server
Exiting
/home/francesco/.rvm/gems/ruby-2.2.2@Best-i-gest_v2/gems/actionpack-4.2.5/lib/action_dispatch/routing/route_set.rb:549:in `add_route': Invalid route name, already in use: 'app_settings'  (ArgumentError)
You may have defined two routes with the same name using the `:as` option, or you may be overriding a route already defined by a resource with the same naming. For the latter, you can restrict the routes created with `resources` as explained here: 
http://guides.rubyonrails.org/routing.html#restricting-the-routes-created
.....

here part of my routes.rb file containing the routes marked as double defined:

.....
get 'app_settings' => 'admin/app_settings#index', :as => 'app_settings'
put 'app_settings' => 'admin/app_settings#index', :as => 'app_settings'
post 'app_settings' => 'admin/app_settings#index', :as => 'app_settings'
post 'app_settings/upload' => 'admin/app_settings#upload_logo', :as => 'app_settings/upload'
.....

i've defined these routes because i'm going to manage all actions related to application setting using the 'index' action only (the app has a single db record storing all settings, this record is automatically created at the first time the user will load page, then updated when it saves) as you can see here:

# only one record here! it will store all the application settings
def index
  # manages all the controller actions inside the index...
  if request.get?
    # this is a get request... returns the first settings record or a new one if none exists!
    @app_settings = !AppSettings.all.first.nil? ? AppSettings.all.first : AppSettings.new
  elsif request.post?
    # this is a post request, the settings record will be created
    @app_settings = AppSettings.new(params[:app_settings])
    @app_settings.save
  elsif request.put?
    # this will update the existing app_settings record
    @app_settings = AppSettings.find_by_id(params[:app_settings][:id].to_i)
    @app_settings.update_attributes(params[:app_settings])
  end

  # renders the index page
  render "index"
end

i'm looking for a way to correct the routes.rb file (keeping my controller and view as is!!) or an alternative way to manage this issue!!

waiting your suggestions, many thanks in advance for your time,

francesco


Solution

  • Seems like you have way too much logic in one method. I'm fairly sure even in rails 3 that wasn't acceptable.

    What about using rest route ( resources as described in the rails routing guide )

    resources :app_settings, only: [:index, :update, :create]
    

    This will create three routes for index (geT), update (patch), create (post).

    Your controller will now look like this:

    def index
      @app_settings = !AppSettings.all.first.nil? ? AppSettings.all.first : AppSettings.new
    end 
    
    def create
      @app_settings = AppSettings.new(params[:app_settings])
      @app_settings.save
    end
    
    def update
      @app_settings = AppSettings.find_by_id(params[:app_settings][:id].to_i)
      @app_settings.update_attributes(params[:app_settings])
    end
    

    There will also be no need to use render 'index' ... rails will automatically look for /app/app_settings/index.html.erb