I am currently working on a Rails engine that will duplicate the host app's routings under a certain scope. So if a route get '/posts', to: 'posts#index', as: 'posts'
exists in the original application, this route should also be available under the engine mount get '/mount/posts'
, but should point to the same Contoller#Action in the host application.
However, I don't have access to the final application, so the routes have to be generated dynamically.
The following is my current approach, but maybe it works better in another way?
# lib/embed_me.rb
require "embed_me/engine"
module EmbedMe
# defines a scoped route under which the embedded content can be found
mattr_accessor :scope_name, default: :embed
end
# lib/embed_me/engine.rb
module EmbedMe
class Engine < ::Rails::Engine
isolate_namespace EmbedMe
initializer "embed_me", before: :load_config_initializers do |app|
Rails.application.routes.append do
mount EmbedMe::Engine, at: EmbedMe.scope_name
end
end
end
end
# config/routes.rb
EmbedMe::Engine.routes.draw do
match '/*path', to: 'application#index', via: :all
end
# app/controllers/embed_me/application_controller.rb
module EmbedMe
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
def index
# will validate existance of route, or raise ActionController::RoutingError
path = Rails.application.routes.recognize_path(params[:path])
controller = path[:controller]
action = path[:action]
# how to call original action?
end
end
end
I can't use redirect_to("/#{params[:path]}")
because it would change the URL to the unscoped URL.
I can't use render(action: action, controller: controller)
, because only the corresponding views will be rendered, but the logic in the controller will be skipped. (or I have done something fundamentally wrong?)
I can't use main_app.resource_path
because the routes are not static and vary from application to application.
I have also looked at Link and Link, but couldn't really get that to work either