0

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

coppola_f
  • 15
  • 6

2 Answers2

1

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

Alexandre Voyer
  • 809
  • 6
  • 11
0

ok guys, i've solved... many thanks to Alexandre and Ryan who guided me in solving this issue.....

well, Alexandre sure you're right!! too much logic inside a single action so... here is the new version of my files:

routes.rb:

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

# site admin area
namespace :admin do
  resources :app_settings, only: [:index, :update, :create]
  resources :users
  ......

end
.....

as you can see, i've inserted app_settings route inside the admin namespace ..

app_settings_controller.rb:

# app_settings security settings - used for declarative authorization
filter_access_to [:index, :create, :update], :require => :manage
filter_access_to :upload_logo, :require => :manage

# app_settings index method (this replaces the show method so all actions will be managed in the index view page)
def index
  # this is a get request... returns the first settings record or a new one if none exists!
  @app_settings = !AppSettings.first.nil? ? AppSettings.first : AppSettings.new(id: 1)
  @app_settings.save
end 

# app_settings create method
def create
  # this is a post request, the settings record will be created
  @app_settings = AppSettings.new(app_settings_params)
  @app_settings.save
  # renders the index page
  render "index"
end

# app_settings update method
def update
  # this will update the existing app_settings record
  @app_settings = AppSettings.find_by_id(params[:app_settings][:id].to_i)
  @app_settings.update_attributes(app_settings_params)
  # renders the index page
  render "index"
end
......

as you can see, i've implemented your solution keeping the index view as only view used by the app, just for not changing too much inside the app.... i've fixed the declarative_authorization section accordingly with the modifications you've suggested and simplified the creation of the new record as Ryan suggested but adding a little extra (i've specified the record id and then saved the record itself) all to prevent another issue in my view where the form_for is declared as follows:

<!-- application settings edit form -->
<%= form_for [:admin, @app_settings] do |app_sett| %>
.....

.....
<% end %>

so many thanks again to you all!!

hoping to continue learning from you all the times i read a page of this site!!

regards,

francesco

coppola_f
  • 15
  • 6
  • Instead of rendering index I would just redirect to it if I was you, that way you won't get "do you want to re-submit the form" when a user presses F5 to refresh the page :) – Alexandre Voyer Jan 03 '16 at 16:22
  • And you can also use flash messages to show user that the process succeeded :) Good luck! – Alexandre Voyer Jan 03 '16 at 16:23