How to get the subdomain value from a url? - ruby-on-rails

how can I get the subdomain value in rails, is there a built-in way to do this?
e.g.
test123.example.com
I want the test123 part of the url.

Rails 3.0 has this capability built-in, you can access the subdomain from request.subdomain.
You can also route based on the subdomain:
class SupportSubdomain
def self.matches?(request)
request.subdomain == "support"
end
end
Basecamp::Application.routes do
constraints(SupportSubdomain) do
match "/foo/bar", :to => "foo#bar"
end
end
If you're using 2.3, you'll need to use a plugin such as subdomain-fu.

Use the following method inside your controller
request.subdomains
This Returns an array of subdomains

account_location is also a good plugin. After using it, you can find the account based on different subdomains. And you can find out subdomain from url just by writing request.subdomains(0).first in your code.

In case you are working with a string, and assuming it can be a true URI, you can do this to extract the subdomain.
require 'uri'
uri = URI.parse('http://test123.example.com')
uri.host.split('.').first
=> "test123"
https://stackoverflow.com/a/13243810/3407381

Simple in your controller just do the following
unless request.subdomains.any?
#No domains available redirect
redirect_to subdomain: 'www'
end

You can use the SubdomainFu plugin. This plugin gives you a method current_subdomain which returns the current_subdomain of your app.
You can also have a look at this Railscast
UPDATE
You can also use request.subdomains this will give you an array of subdomains.

For anyone looking to get the subdomains on localhost using WEBrick:
Put config.action_dispatch.tld_length = 0 into config/environments/development.rb and everything should work.
Link to SO post here:
Can I make Rails / WEBrick recognize entries in /etc/hosts as subdomains (instead of domains)?
Link to Github post:
https://github.com/rails/rails/issues/12438

current domain with subdomains:
"#{request.subdomain}.#{request.domain}"
# or
"#{request.subdomains.join(".")}.#{request.domain}"

A bit late to the party but here's what I used in older versions of rails.
subdomain = request.subdomains.join('.')
It should be backwards compatible in newer versions

Related

Accessing request context object in rails router

I need to create a few dynamic routes in my rails router in the following way:
Rails.application.routes.draw do
account = Account.find_by(
subdomain: request.subdomain,
domain: request.domain
)
EditableField.where(account_id: account.id).links.each do |link|
get link.link_href, to: link.method
end
end
As shown above, I need to determine the account based on the request domain and subdomain, however I cant find how to access the request object in the rails router. What is the correct way to do this ?
I would suggest using the rack-rewrite gem
https://github.com/jtrupiano/rack-rewrite
It is in lower level and give you much more options to do this kind of dynamic routing
And if you still want to do that in the routes.rb file, you can follow this answer https://stackoverflow.com/a/24411835/2529330
Enjoy :)

Rails, Devise and Dynamic Subdomains on Subdomain (e.g. user.beta.example.com) how to setup?

I'm using basecamp style subdomains, rails 3.2, devise 2, passenger standalone. Everything is working fine on *.example.com. Now i want to launch a staging environment on *.beta.example.com and not sure whats the best way to make it work.
The following method checks if user requests app.example.com (then he is redirected to sign in page) or someone's account (e.g. user1.example.com), otherwise badrequest is returned. (app_subdomain = 'app')
def validate_subdomain
if request.subdomain == Settings.app_subdomain
redirect_to(user_signed_in? ? users_accounts_path : new_user_registration_path)
else
head :bad_request unless current_account?
end
end
If i deploy it to *.beta.example.com then request.subdomain returns "app.beta" and validations no longer work.
What would be the most elegant and reusable way to solve it? Other than to strip environment's subdomain manually. Thanks
Option one: change request.subdomain to request.subdomains.first. Then only app from app.bla-bla-bla.anything.example.com will be recognized.
Option two: set config.action_dispatch.tld_length in config/environments/production.rb. Sets the TLD (top-level domain) length for the application. Defaults to 1.
Source on tld_length:
Rails 3.x TLD length
http://guides.rubyonrails.org/configuring.html
https://rails.lighthouseapp.com/projects/8994/tickets/5215-configurable-tld_length-for-subdomains

rails get app root/base url

In my app I have a few APIs that under api domain. Now in one of the API I want to generate a url that pointing to the main domain, say
test.com/blabla...
I tried to use url_for but seems the default root_url or request.host is in api domain. Url_for will make it to be
api.test.com/blabla..
while I want it to be
test.com/blabla...
Url_for can take a parameter
host: ...
to set it to be test.com/, the question is how can I get the root/base url (test.com) for host? root_url or request.host are all api.test.com.
Any ideas? Thanks.
Just so that it's useful to someone else , i came across this today
request.base_url
gives the full path in local as well as on live .
request.domain
gives just the domain name so it sometimes kinda breaks the link while redirecting
According to this you can do request.domain
Simplest alternative method:
include in you're class
include Rails.application.routes.url_helpers
create function or just use root_url to get app root/base url:
def add_host_prefix(url)
URI.join(root_url, url).to_s
end
finally: add
Rails.application.routes.default_url_options[:host] = 'localhost:3000'
in:
Your_project_root_deir/config/environments/development.rb
although helpers can be accessible only in views but this is working solution.
request.domain fails on CF it given domain url not base url

How do I write a full path in a controller in Rails 3?

I need to write the full path so need to know what the rails_root domain is. How do I do that? For example:
string = "{RAILS_ROOT}/vendors/#{#vendor.id}"
What is the equivalent of "RAILS_ROOT" to give me what the full domain is for my application? So that in development it would subsstitute localhost:3000 and on my heroku site the right full domain?
You should always avoid, if possible, hard-coding your path, because it is less flexible and more prone to result in broken links in the future. Plus, you can use Rails routing, which is an elegant way to generate everything cohesively in Rails without any need to create the composite parts yourself.
If you have your routes set up properly, you should be able to call:
link_to "View vendor", vendor_url(#vendor.id)
Vendor_url(#vendor.id) in Rails gives you your full URL, which you can then contain in your string variable. Here's how to generate the routes needed for the above:
# in routes.rb
resources :vendors
Try:
File.realpath(RAILS_ROOT)
You could access the request object. request.host_with_port would give you the hostname and port. request.protocol will give you the protocol (http:// or https://). request.fullpath will give you the path with query params.

Support for multiple domains/subdomains in Rails

I have a Rails app that has a similar setup to Tumblr, that is, you can have either:
(1) Subdomain hosting (your-username.myapp.com)
(2) Domain hosting (your-username.com)
Both would forward to a personalized website for that user, created with my application.
How can I accomplish this in Rails? I have been able to get (1) working with subdomain-fu, but I'm not sure how to get (2) working. Any pointers (plugins, gems, tutorials), etc. would be greatly helpful, I can't seem to find any.
Thanks!
The principle for domains is the same as the subdomain - find the domain, map to an account.
The details will depend on how your hosting is going to handle the DNS.
I am currently using Heroku and its wildcard service.
In this case, the domain is mapped with a cname to the subdomain hosted by my Heroku app. From here I can work out the associated account and details.
EDIT: I've found a much easier way: http://www.arctickiwi.com/blog/7-host-and-domain-based-routing-in-ruby-on-rails
Not exactly an answer but this is the best I can give. Maybe this'll help you too.
Ideally, this blog post from transfs.com and subdomain-fu should do the trick. I've been trying to implement it, however, and they don't seem to play nicely together.
Basically, if I don't include the intiializer, the subdomain route works fine. If I include the initializer, the subdomain route breaks (everything gets caught by map.root). I have a feeling it's with the way it builds the condition string in the initializer. If you can figure out how it breaks, then you'll have a working app.
My initializer:
module ActionController
module Routing
class RouteSet
def extract_request_environment(request)
env = { :method => request.method }
env[:domain] = request.domain if request.domain
env[:host] = request.host if request.host
env
end
end
class Route
alias_method :old_recognition_conditions, :recognition_conditions
def recognition_conditions
result = old_recognition_conditions
[:host, :domain].each do |key|
if conditions[key]
operator = "==="
if conditions[key].is_a?(Regexp)
operator = "=~"
end
result << "conditions[:#{key.to_s}] #{operator} env[:#{key.to_s}]"
end
end
result
end
end# end class Route
end
end
My routes (just for development). You'll see my local development domain, stiltify.dev. Sorry, I tried to make it look good in here but I couldn't get the code block to look nice. I put it on pastie instead: http://pastie.org/940619.
The comments section in Ryan Bates' screencast was very helpful, and got me to figure out the subdomain => false and the other errors they were getting into. Still didn't fix the problem though!

Resources