Rails Subdomain in Host Being Replaced - ruby-on-rails

Given the following config/routes.rb:
constraints subdomain: 'subdomain' do
get 'path', to: 'main#index', as: :sample
end
The following works:
Rails.application.routes.url_helpers.sample_url(host: "a.b")
# "http://subdomain.a.b/path"
The following fails:
Rails.application.routes.url_helpers.sample_url(host: "a.b.c")
# "http://subdomain.b.c/path"
Any way to fix it so subdomains don't replace existing subdomains in the host but instead are linked (i.e. http://subdomain.a.b.c/path)? I realize I can change the subdomain in the route to be subdomain.a - but that'd be a bit of a pain to maintain for multiple subdomains / deployments.

Looks like you need to examine tld_length:
:tld_length - Number of labels the TLD id composed of, only used if
:subdomain or :domain are supplied. Defaults to
ActionDispatch::Http::URL.tld_length, which in turn defaults to 1.
I'll test the specifics, but the issue looks like Rails is only allowing a tld (top level domain) length of 1, which means that you can only have a subdomain and 1 "other" element (subdomain.b.c / subdomain.a.b).
The fix should be to expand the tld_length, which according to this answer, can be done in the config settings /config/application.rb:
# config/application.rb
config.action_dispatch.tld_length = 2
Tests
Without tld_length:
c:\Dev\Apps\torches>rails c
Loading development environment (Rails 5.0.0.1)
irb(main):001:0> Rails.application.routes.url_helpers.sample_url(host: "a.b")
=> "http://subdomain.a.b/path"
irb(main):002:0> Rails.application.routes.url_helpers.sample_url(host: "a.b.c")
=> "http://subdomain.b.c/path"
irb(main):003:0>
With tld_length:
c:\Dev\Apps\torches>rails c
Loading development environment (Rails 5.0.0.1)
irb(main):001:0> Rails.application.routes.url_helpers.sample_url(host: "a.b")
=> "http://subdomain.a.b/path"
irb(main):002:0> Rails.application.routes.url_helpers.sample_url(host: "a.b.c")
=> "http://subdomain.a.b.c/path"
irb(main):003:0>

create config/initializers/host_name.rb file, where you can place a constant :
HOST_NAME = 'b.c'
then anywhere in your code :
Rails.application.routes.url_helpers.sample_url(host: HOST_NAME, subdomain: 'subdomain.a')
you can also create constants for your subdomains if you like

Related

Can I make Rails / WEBrick recognize entries in /etc/hosts as subdomains (instead of domains)?

I'm trying to use subdomains locally for a Rails app so I added the following line to my /etc/hosts file:
# add 'test' subdomain for localhost
127.0.0.1 test.localhost
Now I can point my browser to test.localhost:3000 and it hits my Rails app.
However, Rails or WEBrick interprets the whole darn thang as the domain:
# logging in the controller
logger.debug("domain: '#{request.domain}', subdomain: '#{request.subdomain}'")
# output in the console
domain: 'test.localhost', subdomain: ''
Is there an easy way to get WEBrick Rails to interpret test as the subdomain?
Thanks!
Update
I ended up making a before_action as a workaround.
def set_domain_and_subdomain
#domain = request.domain
#subdomain = request.subdomain
# HACK: force /etc/hosts subdomains
if Rails.env.development?
if m = request.domain.match(/([^\.]+).localhost/)
#subdomain = m[1]
#domain = 'localhost'
end
end
end
But I'm still curious if there's a way to do this universally on my computer (i.e. in `/etc/hosts or something)
Pretty late to find this post, but for posterity: https://github.com/rails/rails/issues/12438
Setting the top level domain length (TLD) allowed request.subdomain to target the subdomain as you'd expect.
I put config.action_dispatch.tld_length = 0 into config/environments/development.rb and everything worked swimmingly.
Remember to restart your server

Rails 3.1.0 default_url_options for custom paths

In my routes.rb I have a custom path defined:
match "foo/copy" => "foo#copy", :via => [ :post ], :as => "copy_foo"
I have an initializer in my config/initializers directory named https_by_default.rb, which contains one line:
Rails.application.routes.default_url_options[:protocol] = 'https'
If I run rails console and type Rails.application.routes.default_url_options, it returns {:protocol => 'https} as expected.
But in my view where I am using the generated custom path _url helper, it doesn't generate the URL with https. <%= copy_foo_url() %> in the ERB returns http://localhost:3000/foo/copy.
What am I missing in order to get my named routes helpers to respect default_url_options?
You should use the following instead:
<%= copy_foo_path() %>
And in your application config file add.
config.force_ssl = true
This enables ssl on all your Rails environments. If you want to enable ssl on your production environment only, then just add the line to your production config file.

why doesn't this routing work on heroku but works locally?

I have the following in my routes.rb file for Rails 3:
13 namespace :user do
14 root :to => "users#profile"
15 end
I get this error on heroku:
ActionController::RoutingError (uninitialized constant User::UsersController):
I already restarted the application.
I am doing this because I am using devise and this is what it says on the wiki:
https://github.com/plataformatec/devise/wiki/How-To:-Redirect-to-a-specific-page-on-successful-sign-in
The problem is that Rails is expecting there to be a controller within a module called Users because that's what namespace :user infers. Perhaps you meant to use scope instead of namespace?
scope :path => "user" do
root :to => "users#profile"
end
Note: in this situation if you've only got one route it would not be wise to use scope, but if you've got multiple ones with the /user prefix then it would be fine to. If you only had one, I would do this instead:
get '/user', :to => "users#profile"
Heroku environments run in production mode. When you run locally, you run in development mode, which accounts for at least one difference. Try this instead:
RAILS_ENV=production bundle exec rails s
and see if you notice the same error.

RoR: Sinatra producing error "uninitialized constant"

I'm new to Ruby on Rails (formerly and currently PHP expert) so forgive my ignorance but I'm trying to get Sinatra working as middleware to redirect some old urls since I tried the gem rack-rewrite and couldn't get that to work either.
I am using code samples from ASCIIcast so in my routes.rb I have the following:
root :to => HomeApp
(^ I'm redirecting the root only for testing)
In my lib folder I have home_app.rb
class HomeApp < Sinatra::Base
get "/" do
"Hello from Sinatra"
end
end
When I start the server (or if its already running) it produces the error:
routes.rb:10: uninitialized constant HomeApp
Which seems that it just isn't aware of the lib/home_app.rb file.
I have included Sinatra in my Gemfile and ran bundle install and confirms it is included.
I just want to reroute old urls from my old site to my new ruby app but can't get any of this middleware/rack stuff working. All documentation assumes you aren't a total newb or is for RoR pre-3.0.
You don't need to use Sinatra if you want to redirect some URLs. You can use the new redirect method. See the Rails Dispatch article.
match "/stories/:year/:month/:day/:name" => redirect("/%{name}")
constraints :user_agent => /iPhone/, :subdomain => /^(?!i\.)/ do
match "*path" => redirect {|params, req| "http://i.myapp.com/#{req.fullpath}" }
end
In your specific case, the problem is that the HomeApp class is not loaded. Either add the /lib folder to your load path changing application.rb
config.autoload_paths += %W( #{config.root}/lib )
or require the file.

Sinatra app as Rails 3 subpath

I'm trying to get a sinatra app as a subpath in my rails 3 app.
Specifically, the resque queuing system has a sinatra based web interface that I would like to have accessible through /resque on my usual rails app.
You can see the project here: http://github.com/defunkt/resque
I found some people talking about adding a rackup file and doing this sort of thing:
run Rack::URLMap.new( \
"/" => ActionController::Dispatcher.new,
"/resque" => Resque::Server.new
)
But I don't really know where to put that or how to make it run. My deployment is with passenger, but it would me nice to also have it running when I run 'rails server' too. Any suggestions?
--edit--
I've made some progress by putting the following in config/routes.rb:
match '/resque(/:page)', :to => Rack::URLMap.new("/resque" => Resque::Server.new)
Which seems to work pretty well, however it loses the public folder, (which is defined within the gem I guess), and as a result, there is no styling information, nor images.
You can setup any rack endpoint as a route in rails 3. This guide by wycats goes over what you are looking for and many of the other things you can do in rails3:
http://yehudakatz.com/2009/12/26/the-rails-3-router-rack-it-up/
For example:
class HomeApp < Sinatra::Base
get "/" do
"Hello World!"
end
end
Basecamp::Application.routes do
match "/home", :to => HomeApp
end
Yehuda (/Scott S)'s solution doesn't work for me with Rails 3.0.4 and Sinatra 1.2.1... setting :anchor => false in the matcher is the key:
# in routes.rb
match "/blog" => MySinatraBlogApp, :anchor => false
# Sinatra app
class MySinatraBlogApp < Sinatra::Base
# this now will match /blog/archives
get "/archives" do
"my old posts"
end
end
(answer c/o Michael Raidel - http://inductor.induktiv.at/blog/2010/05/23/mount-rack-apps-in-rails-3/)

Resources