Skip to content

Mounting

Alexander Popov edited this page Feb 9, 2021 · 1 revision

Mount controllers in an application class by mount method:

# foo_controller.rb

module MyProject
  class FooController < Flame::Controller
    def hello_world
      'Hello, world!'
    end

    def my_name(name, last_name = nil)
      "My name is #{name} #{last_name}"
    end
  end
end
# application.rb

module MyProject
  class Application < Flame::Application
    mount FooController
    ## GET '/foo/hello' => `FooController#hello`
    ## GET '/foo/my_name/:name/:?last_name' => `FooController#my_name`
  end
end

Namespace path is a controller class name without Controller or Ctrl suffix by default, but it can be changed via PATH constant inside controller:

# foo_controller.rb

module MyProject
  class FooController < Flame::Controller
    PATH = '/bar'
  end
end

or at mounting:

# application.rb

module MyProject
  class Application < Flame::Application
    mount FooController, '/bar'
    ## GET '/bar/hello' => `FooController#hello`
    ## GET '/bar/my_name/:name/:?last_name' => `FooController#my_name`
  end
end

You can specify controller as its downcased name without suffix as symbol:

# application.rb

module MyProject
  class Application < Flame::Application
    mount :foo
  end
end

By default, paths are the same as methods names and HTTP method is GET, but there is also defaults for the REST scheme:

# users_controller.rb

module MyProject
  class UsersController < MyProject::Controller
    # GET /
    def index
      view # `index` view by default
    end

    # GET /new
    def new
      view # `new` view by default
    end

    # POST /
    def create
      Model.create(model_params)

      redirect :index
    end

    # GET /:id
    def show(id)
      @model = Model.first(id)

      view # `show` view by default
    end

    # GET /edit/:id
    def edit(id)
      @model = Model.first(id)

      view # `show` view by default
    end

    # PUT /:id
    def update(id)
      @model = Model.first(id)

      if @model.update(model_params)
        redirect :show, id: id
      else
        view :show, error: @model.errors
      end
    end

    # PATCH /:id
    def patch(id)
      # the same, as update, but partially
    end

    # DELETE /:id
    def delete(id)
      @model = Model.first(id)
      @model.destroy
      redirect :index
    end

    private

    def model_params
      params[:model]
    end
  end
end

For others HTTP methods or action-paths you can specify it in the controller:

# foo_controller.rb

module MyProject
  class FooController < Flame::Controller
    get '/hello', def hello_world
      'Hello, world!'
    end

    def my_name(name, last_name = nil)
      "My name is #{name} #{last_name}"
    end

    post def bye
      'Bye!'
    end
  end
end

or in a block while mounting:

mount ParentController do
  get '/hello', :hello_world
    ## `get` - HTTP-method
    ## '/hello' - new URL-path
    ## :hello_world - controller's method name
  post :bye
    ## `post` - HTTP-method
    ## URL-path as method-name by default
    ## :bye - controller's method name

    ## if you don't refine all public-method of controller (as `:my_name` for now)
    ## remain actions will be mount automatically
    ## (REST-matching, or with GET HTTP-method and path as method-name)

  # You can mount nested controllers
  mount NestedController, '/some_nested' # path will be '/parent/some_nested'
end

But don't forget about arguments while refining path!

# controller.rb

  def hello(first_name, last_name = nil)
  end

# application.rb

  ## default path => '/hello/:first_name/:?last_name'
  ##   :first_name - required argument
  ##   :?last_name - not required
  get '/hello_world/:first_name/:?last_name', :hello

Since version 5 you don't have to mount all controllers manually: there is a support of automatic nested mounting. For example, if you have MyProject::Site::Controller (base, without actions, but with specific hooks and plugins), MyProject::Site::IndexController and a lot of MyProject::Site::FooController — they all will be mounted by:

# application.rb

  mount :site

And if you have a parallel namespace with controllers, for example MyProject::API::Controller, just add mount :api, that's all. But don't forget to require them, there is Flame::Application.require_dirs for such things.