*_url helpers don't work with varying subdomain levels - ruby-on-rails

I've got a site with an api subdomain. On the same domain where the site is located, I've also got a dev subdomain with, you guessed it, a development version of the site.
My issue is that this dev version of the site also has an api subdomain (ie: api.dev.example.com. The routes work without issue using a regex to match the last segment of the subdomain against api (/api(?:\..*)?/), but the *_url helpers do not generate what I would like. Instead of spitting out http://api.dev.example.com/somepath, they spit out http://dev.example.com/somepath.
I'm looking for a solution that doesn't require special handling of the dev site vs the prod site. Subdomain sniffing based on requests so some such nonsense does not appeal to me.
Relevant routes.rb content:
constraints subdomain: /api(?:\..*)?/, format: 'json', protocol: 'http://' do
get '/' => 'example#index'
post '/create', to: 'example#create', as: :api_create_example
end

You can pass the subdomain to the url helper:
fear_and_loathing_in_las_vegas_url(subdomain: 'api.dev')
This will generate http://api.dev.example.com/fear_and_loathing_in_las_vegas

Related

Vue.js router with Ruby on Rails routes

I'm currently working on a application with a Ruby on Rails backend and Vue.js frontend. It's a single page application. I'm using the webpacker gem to build my main JS file.
I've added vue-router and and a couple frontend routes. I'm able to navigate using <router-link> which correctly renders the appropriate component. What I can't figure out is how do I setup my frontend routes so that someone can directly navigate to a URL without hitting my Rails routes.
For example if I type /sample-route I'd like to hit my Vue.js route and not my Rails route. I still want to be able to make API calls to my Rails routes as well. For example /api/users.
My problem was solved by adding <router-view></router-vew> into my main Vue.js component.
Here's my rails routes file as well:
Rails.application.routes.draw do
namespace :api do
# api routes here
end
root 'application#index'
get '/*path', to: 'application#index'
end
Depending on how many routes you have, you can add your Vue routes to routes.rb and send them to your root Vue application route. e.g. Webpacker is rendering your js pack with controller#action vue_controller#app. Your Vue app router uses /user/profile. In routes.rb, add a route:
get "/user/profile" => "vue_controller#app" # <- The controller action rendering your Vue pack
If it seems unmaintainable to redefine every Vue route in routes.rb, you may want to look into a universal fallback route that sends them to the vue app controller action. As long as you don't change the route, but just respond with the Vue controller action, the Vue router will take care of rendering the right components for that route when the page loads.
In Rails 4, you can use something like the answers in this SO question to help you out with setting up a "catch-all" route Rails catch-all route.
EDIT: Using a catch all route does lead to some problems with 404's. If the user requests a route that doesn't exist, the Rails app will still send them the Vue pack. To fix this, you would need to add some unknown route handling in your Vue router to render something like a 404 page.
There is one more approach which will be useful and handles sub-routes as well (having separate vue apps per page in a single rails app):
routes.rb
Rails.application.routes.draw do
# this route entry will take care of forwarding all the page/* urls to the index
get 'page_controller/*path', to: 'page_controller#index', format: false
end
Additionally, please handle the api and index routes separately based on the design.
vue-routes.js
const router = new VueRouter({
mode: 'history',
base: '/page_url',
routes: [
...
]
});

Rails routes: redirect a wild card route

I have a website built in Ruby on Rails and a blog built in WordPress. The url for the main site will be example.com and the url for the blog is blog.example.com. Because of the way search engines index sites and the preference for a directory blog as opposed to a subdomain blog, I want to implement a permanent redirect so that example.com/blog/anything will redirect to blog.example.com/anything regardless of how many slashes or parameters the url contains. So even example.com/blog/a/b/c/d/e?google=true should redirect to blog.example.com/a/b/c/d/e?google=true
So far the following works if there is only one directory after blog:
get '/blog/:what', to: redirect('http://blog.codeundercover.com/%{what}')
I, however, need this to work regardless of what text comes after /blog. How do I do this?
Your route is not using a wildcard route. Instead, it's what the Rails Routing Guide refers to as a Static Segment
You'll want to use Wildcard Globbing instead:
get '/blog/*what', to: redirect('http://blog.codeundercover.com/%{what}'), constraints: { what: /.*/ }
get "/blog(/*what)", to: redirect("http://blog.codeundercover.com/%{what}")

Rails configure application to have url prefix

I feel like this should not be all that difficult, but I cannot find any solutions that seem to work with Rails4
My setup
I have a proxy server (Kong) that directs to various services behind it based on path.
myapp.com/app1/ is redirected to http://app1_address:PORT/ (notice /app1 is stripped)
same for myapp.com/app2
app2 is a Rails 4 application and it works just fine when browsing to specific, but its relative routing is completely off. For example, link_to or url_for links to controllers or actions all redirect to the wrong links.
For example, I have a logout link that has a path of /logout on app2, but redirecting the user to /logout is incorrect. They need to be routed to /app2/logout. How can I configure the Rails app to add a prefix to all routes?
I have tried:
config.action_controller.relative_url_root = '/app2'
As well as this:
config.relative_url_root = '/app2'
And this in config.ru
map <MyAppName>::Application.config.relative_url_root || "/" do
run Rails.application
end
Any ideas for how to make this work?
You should use a scope in your routes:
Rails.application.routes.draw do
scope ENV["PROXY_PATH"] do
# your routes..
end
end
This way you'll have to set the ENV variable:
$ export PROXY_PATH=app2
$ bin/rails s

Routing a folder to another URL

I Recently migrated a website from PHP to rails. NEwt to the website they was a wordpress that is staying. the urls were as follow :
www.thedomain.com / #former PHP now rails
www.thedomain.com/blog/ #the wordpress.
now that the website is in Rails, i cannot just put a php wordpress in the blog folder.
I tried to go to a blog.thedomain.com solution using thoses route (actual domain names i use in dev as i am trying to make it work) :
namespace :blog do
match'', to: redirect {|params,request| "http://blog.fakefake1111/#{params[:path]}#{request.path}"}, via: :all
match '*path', to: redirect {|params,request| "http://blog.fakefake2222/#{params[:path]}"}, via: :all
end
It doesnt quite work, as the params are ignored and the first one add /blog/ at the end of the URL.
How can i make it work?
I will use the alias capability of apache to do it. I do not really need to use rails for that.

devise confirmation_url in HTTPS

My website is entirely SSL, so I would like to have also the urls generated by devise (3.2.2) for Email verification to be https://....
currently the urls are generated by:
confirmation_url(#resource, :confirmation_token => #token)
which produces nice urls like:
http://example.com/users/confirmation?confirmation_token=zqfHS35ckLQZscSbsgMm
I would like the url to be
https://example.com/users/confirmation?confirmation_token=zqfHS35ckLQZscSbsgMm
Also, currently the email verification doesn't work, because nginx operates a redirect to the https equivalent to every page, and for some reasons things get messed up and the https version is a corrupted url, like:
https://example.com/users/confirmation?confirmation_token=zqfHS35ckLQZscSbsgMm?confirmation_token=zqfHS35ckLQZscSbsgMm
for some reasons nginx redirects to this corrupted url, so Unicorn can't but reject the request.
any clues?
You can either specify the protocol in the email template, as you did in your own answer, or you can specify it as a default in the mailer. The simplest way to do this, if you are happy for all emails to use https links, is to add it to your app config. For example, in your production.rb:
config.action_mailer.default_url_options = {:protocol => 'https', :host => 'example.com'}
I know it doesnt matter any more if you're going straight to https, but your url after the nginx redirect from http to https looks like it's appending the query string to the entire url, so it would be worth fixing that so it works in all cases even if you don't need it for the emails any more. If you're using a return 301 … statement in the nginx config, perhaps there's a trailing $query_string or $args you don't need - for example, if you're using $request_uri that already has the GET parameters in it.
Also, I don't think you will find confirmation_url defined directly anywhere. If you try rake routes you'll probably see one of them is:
user_confirmation GET /users/confirmation(.:format) {:controller=>"devise/confirmations", :action=>"show"}
which means that there will automatically be a user_confirmation_url helper available as with routes in general. I think devise then allows you to use confirmation_url due to its clever tracking of the scope you're using ('user' in this case), though I must admit I haven't looked at the code enough in devise's routing to know exactly how it does it for the routes.
I changed the method call to:
confirmation_url(#resource, :confirmation_token => #token, protocol: "https")
and that started generating correctly the urls with https as required.
I couldn't find the definition of confirmation_url anywhere in the devise code though.

Resources