Rails allows you to specify middlewares for specifying a route just like the Phoenix pipeline

In phoenix framework

a conveyor, we can enable the option middlewares for some routes, such as:

defmodule HelloPhoenix.Router do
  use HelloPhoenix.Web, :router

  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_flash
    plug :protect_from_forgery
    plug :put_secure_browser_headers
  end

  pipeline :api do
    plug :accepts, ["json"]
  end

  scope "/", HelloPhoenix do
    pipe_through :browser # Use the default browser stack

    get "/", PageController, :index
  end

  scope "/api", HelloPhoenix do
    pipe_through :api
  end
end

      

if the request is from /api

, will only run the plug :accepts, ["json"]

middleware

if the request is from /

, will trigger a session, flash, ... etc. middlewares

how to do it on rails if i use grape

to build api and rails to create web page and provide intermediate middleware between each other?

+3


source to share


3 answers


Unlike Phoenix apps, you cannot (easily) change which middleware is used to query in Rails. The best way to get this behavior in a Rails application is to make the controllers for a specific route inherit from a common base controller, and then define the behavior of those specific controllers in that base controller.

Using the above example of routes /api

traversing various "middleware" you can have a controller like this:

module API
  class BaseController < ActionController::API
    # things unique to API routes go here
  end
end

      

Inside this controller, you can write callbacks before_action

that provide things like:

  • Incoming requests only JSON
  • Requests are authenticated using a specific token

Then you can inherit this controller for all API controllers:

module API
  class PostsController < API::BaseController
  end
end

      

With regular controllers, you can do all the usual things:

class ApplicationController < ActionController::Base
  # things unique to non-api routes go here
end

      



And then:

class PostsController < ApplicationController
end

      

You could of course segment it more; perhaps you might have a different route, for example /accounts/1/posts

where you have to be authenticated as a user of that account to view messages. You can use the same approach:

module Accounts
  class BaseController < ActionController::Base
     # find account, check if the user is authenticated, etc.
  end
end

      

and

module Accounts
  class PostsController < Accounts::BaseController
  end
end

      


So, in short: Rails doesn't let you do this at the routing level (easily), but you can do the same at the controller level.

+5


source


The solution I was looking for was something big along this line:

application.rb:

# after Bundler.require(...)
require_relative '../lib/engines/website/lib/website'

      

Library / Engines / Site / Library / website.rb:

require_relative "website/engine"

module Website; end

      

Library / engines / site / Library / site / engine.rb:



module Website
  class Engine < ::Rails::Engine
    middleware.use ActionDispatch::Cookies
    middleware.use ActionDispatch::Session::CookieStore
    middleware.use ActionDispatch::Flash
  end
end

      

config /routes.rb:

mount Website::Engine => "/website"

      

And everything for a website goes into a typical directory structure in the engine directory:

lib
  engines
    website
      app
        assets
          ...
        controllers
          ...
        views
          ...
      config
        routes.rb
      lib
        website
        website.rb

      

Ref: Create 2 intermediate stacks in your Rails application

+1


source


I'm sure you can achieve this result by configuring the Rack middleware stack, but it won't be configurable in a rails application. Sometimes it is enough to have unnecessary middleware for some routes.

Pretty much every application I've seen uses the same middleware for every request.

And yes, Phoenix behaves better here, Rails behaves in earlier versions, so it's hard to change things now.

0


source







All Articles