How do I explicitly set a rails engine routing proxy? - ruby-on-rails

On my Rails 5.0.7 application I have Thredded (0.15.4) mounted as an engine in a namespace.
#routes.rb
namespace :home do
mount Thredded::Engine => "/communities", as: "thredded"
end
This allows me to access /home/communities to pull up the thredded interface.
Unfortunately, this also leads to unexpected behavior. The rails route proxy is not thredded as expected, but rather home_thredded. If I wanted to access a named route inside my engine, I need to do home_thredded.root_path instead of thredded.root_path
This is especially troublesome because thredded.root_path is actually referenced in the code of the thredded gem itself, which now throws an error.
Is there some way to explicitly set the routing proxy to avoid needing to include the namespace in the routing proxy?
A few things that I've considered and rejected:
I could directly edit the code in the offending file of the gem, but that would be annoying to maintain.
I could also write a decorator that overwrites the offending method so that it uses the correct rails routing proxy, but that would still mean that I would have to use the home_thredded.some_path anywhere rather than the expected thredded.some_path
I could not namespace the engine. This could work, but it would break the naming conventions of the rest of the application.

Have you tried:
scope :home do
mount Thredded::Engine => "/communities", as: "thredded"
end
That should add /home to your URI Pattern but leave your Controller#Action and Prefixs unchanged.

Related

Accessing engine routes from Rails.application.routes.url_helpers

I would like to know how to access engine routes by using Rails.application.routes.url_helpers.
I have a factory object that creates a string including a dynamically generated url. Currently, I can generate urls by using Rails.application.routes.url_helpers.(INSERT PATH NAME).
However, it can only access the routes in the main app. I cannot access the routes of engines mounted on the main app.
Things I have tried
I've tried to use Rails.application.routes.engine_name where engine_name is the name under which the engine is mounted on the main app.
I've tried to use MyEngine::Engine.routes.url_helpers to access the routes in the Engine. It works, but I would like to use Rails.application.routes.url_helpers because there are many factory objects like this one, and they are all inheriting from the superclass that delgates url_helper to Rails.application.routes.
Any suggestions? Let me know if any clarification is needed.
You have to use engine route proxy method.
From your example call the url helper using the following syntax as example:
my_engine_engine.articles_path
To rename the proxy method helper, just edit the routes config file inside your rails application:
mount MyEngine::Engine => '/app', :as => 'my_engine'
so you can now call the previous example:
my_engine.articles_path
Assuming that your engine namespace is EngineName, it should be:
EngineName::Engine.routes.url_helpers.some_engine_path

Routes in Engine mounted on subdomain do not inherit the constraints

Setup
Our current Rails app is made out of sub-apps that are mounted as engines. Typically these engines are mounted on a subdomain in the main routes.rb file as follows
mount MySubApp::Engine => '/', as: :sub_app, constraints: {subdomain: 'sub_app'}
The Problem
Routes within MySubApp's routes.rb file do not get the subdomain when using the named _url helpers. For example the following in apps/my_sub_app/config/routes.rb
MySubApp::Engine.routes.draw do
resources :foos
end
gives us sub_app.foo_url(5) but it results in
http://www.example.com/foos/5
when we want
http://sub_app.example.com/foos/5
tl;dr
How can I get the engine's mounting constraints passed to its named routes?
EDIT: A Workaround
While I'd still prefer a better solution, the following will work. You can wrap all the routes in each of the sub apps routes.rb files that could be mounted on a subdomain like so
MySubApp::Engine.routes.draw do
constraints Rails.application.routes.named_routes[:sub_app].constraints do
resources :foos
end
end
EDIT 2: A much less desirable workaround
A commenter (since deleted?) pointed out you can pass a subdomain option to the helpers but we'd like to avoid having to use sub_app.foo_url(5, {subdomain: 'sub_app'}) for every cross subdomain link. Even if we moved the subdomain name into an ENV var and made a wrapper, this is not DRY.
check out the guide it says you can do it by
namespace :Engine do
resources :controller, :methods
end
the Engine is just name spacing your code
#Aaron not sure if you ever got this fixed, but look into the
config.action_dispatch.tld_length
setting (on the engine's config). I'm not sure how it'll react with engines, but in our case it lets us handle the case of sub-subdomains for our staging server (so when we use the _url helpers with the staging server it correctly does subdomain.staging.domain.com, rather than subdomain.domain.com).

Rails URL and Path Helpers in Engines Like Spree

I'm trying to use some URL and/or path helpers in my Rails 4 Engine views such as resource_url or resource_path. These engines are configured a bit differently than the typical --mountable tutorial out there. In fact, they more closely resemble how Spree does it, without the Spree::ENGINE_NAME namespace.
Like Spree's architecture, I'm attempting to create core engine that my other engines depend on. For example, my backend engine's routes.rb file looks like this:
Core::Engine.add_routes do
# Check to see if the request comes in on a subdomain
# The Subdomains class passed into constraints()
# is a class defined in lib/subdomain.rb
constraints(Subdomain) do
match '/manage' => "manage#index", :via => [:get]
end
end
In a view inside my backend engine, I'd like to be able to use some URL/path helpers to do something like this:
<%= link_to manage_path, manage_path %>
This doesn't work, because I'm drawing the routes on the core engine. So, I must use
<%= link_to core_engine.manage_path, core_engine.manage_path %>
Spree somehow gets around this, but I'm not sure how. For example, in backend/app/views/spree/admin/products/index.html.erb:
<%= link_to product.try(:name), edit_admin_product_path(product) %>
Notice, the edit_admin_product_path, but no mention of this actually being drawn on the core engine.
Any ideas?
We get around this by drawing all the routes on the core engine using add_routes which exists for reasons I won't go into here because it's a long tangent. Necessary evil for this kind of work, though.
The isolate_namespace method within Core::Engine scopes everything to the spree namespace. If you're inside a controller that's been drawn underneath the Spree::Core::Engine routes and you want to reference a route for another controller also drawn under that route then you can leave off the spree. prefix on the routing helper.
If you're routing to a different engine, then you will need to have the prefix: main_app. or whatever.
The Engines Guide explains this in greater detail, and I'd recommend reading that.

Changing admin route from 'admin/' to 'customadmin/'

All. I've googled this quite a bit and I haven't found anything that'll work.
I want to change the admin route to something other than "admin". In this case, we'll just use "customadmin" as the desired name.
I've been toying with two solutions. One uses rewrites with Nginx, the other uses the routes in the spree application. Maybe, I should use both.
I'm doing this for the SSL layer, so in my 443 server section, (for the Nginx Solution) I tried the following:
locaton /customadmin/
{
rewrite ^/customadmin/(.*)$ /admin/$1 permanent;
}
Cool. That maps customadmin to all the admin routes. But What I don't want is for any random user to even get to the /admin section. Also, If I'm mapping 'customadmin' to 'admin' it'll probably create some sort of error.
Ideas:
*Should I use the 'internal' property? That is, in the admin location block, only go somewhere if the request is internal (or from a rewrite)
*Is there a way to namespace /admin in my spree application so that it uses 'customadmin' instead? I know it can be done (somewhat) by doing the following:
Spree::Core::Engine.routes.append do
scope :customadmin do
namespace :admin do
resources :my_model
resources :my_other_model
end
end
end
Environment Specs:
Spree: 2.1.2
Ruby: ruby-2.0.0-p353
rails: 4

Prepend path prefix to all rails routes

I have a setup where nginx serves a rails application inside a specific subfolder
eg. http://myserver/railsapp/ and everything inside gets proxied to rails, if the first subfolder is different, it servers static files from another folder.
I haven't been able to find how to specify this behaviour in rails in an intelligent way. I mean, what I want is to specify an option like Rails.server_prefix = /railsapp so that all the routes get prepended automagically, both on the incoming requests and on the generated links.
You probably want to use the router's scope method with the :path argument:
Rails.application.routes do
scope(:path => '/railsapp') do
# the rest of your routes go here
end
end
See the docs for more info.

Resources