How to add a new action to the existing controller?

When you repeat the generate command with another method's name, you can skip overwriting the existing controller and it's test implementation. That will automatically add the route and create a view. After that you have to add the method manually to the controller because that action didn't touch the controller file.

Rails 6.1 additional info is in the comments below.


Example:

one method called new was already created in the controller when it was initially created:

$ rails generate controller Person new
... successfully created the controller, it's route and view ...

when trying to add a new method:

$ rails generate controller Person all
Running via Spring preloader in process 28648
    conflict  app/controllers/person_controller.rb
Overwrite ../app/controllers/person_controller.rb? (enter "h" for help) [Ynaqdh] h
    Y - yes, overwrite
    n - no, do not overwrite
    a - all, overwrite this and all others
    q - quit, abort
    d - diff, show the differences between the old and the new
    h - help, show this help
Overwrite ../app/controllers/person_controller.rb? (enter "h" for help) [Ynaqdh] n
        skip  app/controllers/person_controller.rb
       route  get 'person/all'
      invoke  erb
       exist    app/views/person
      create    app/views/person/all.html.erb
      invoke  test_unit
    conflict    test/controllers/person_controller_test.rb
Overwrite ../test/controllers/person_controller_test.rb? (enter "h" for help) [Ynaqdh] n
        skip    test/controllers/person_controller_test.rb
      invoke  helper
   identical    app/helpers/person_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    coffee
   identical      app/assets/javascripts/person.coffee
      invoke    scss
   identical      app/assets/stylesheets/person.scss

def hello
  @hello = "hello"
end

def goodbye
  @goodbye = "goodbye"
end

then in /config/routes.rb

get 'foo/hello'       ## foo is the name of your controller
get 'foo/goodbye'

Remember to create the views too: views/foo/hello.html.erb that may look like this:

Say <%= @hello %>

views/foo/goodbye.html.erb that may look like this:

 Say <%= @goodbye %>

Add a new action is simple. All you have to do is add a method on your controller, like, for example:

# app/controllers/dummy_controller.rb
def get_back
  logger.warn "It works!"
  redirect_to :back
end

Now, to be able to access this action throgh a URL, you need to have a route for that. This is done in your config/routes.rb file. You can add it as a hard route, like

get '/go_back', to: "dummy#get_back"

This is the simplest possible route. But you might want it to behave like a restful route. This is useful if you are doing an action over one or more models. So in your route file, you will have something like this:

resources :dummy do
  collection do
    get 'get_back'
  end
end

This allows you to accept a get method over a collection. You will have the helper dummy_go_back_url, and to get to this page the url is /dummies/go_back.

This is for acting over a collection of resources. If you are acting on one specific object, you should specify a member action:

resources :dummy do
  member do
    get 'get_back'
  end
end

Since a member action is for only one object, you will have a url like /dummies/123/go_back. This automatically will set the variable params[:id] in your controller to 123, allowing you to easily fetch your object. Also, the helper method dummy_go_back_path is defined, and received one object or id as parameter to generate the correct url.

These are the most simple routes you can have, but you can look in routing outside in from rails guides as a reliable source of information.