I've been trying to get Devise and subdomains to work together, by using one of the Subdomain plugins, but not managed to get there fully. Going to have a go using your approach now and see how I get on.
Keep up the great casts, they are always mega helpful!
Finally got Rails 3 working with RVM. Stopped using my local Passenger installation and now I'm really enjoying the flexibility of jumping around to different versions of Ruby/Rails.
Currently developing an app that requires account level subdomains and was unhappy with the options in Rails 2.3...
Looking forward to Rails 3 RC, thanks again for all the awesome screencasts!
Hi, Ryan.
I've wrote similar article some months ago (http://bit.ly/ajGym2 - sorry, only Russian version, but you can use Google Translate) but there are some problems with session sharing between subdomains in Opera browser - unfortunately Opera cannot read cookies from sibling domain - it means if you set cookie for dom1.example.com cookie cannot be read from dom2.example.com
There's a blog article on my.opera.com that describes how the Opera browser deals with cookie sharing between subdomains.
To summarize (very quickly) the article: any *.example.tld subdomains are considered as siblings (and can share domain=.example.tld cookies) if the example.tld domain has a registered IP address in DNS.
I really wish I had this to hand a couple of weeks ago when trying to figure out the subdomain stuff in Rails 3. This has helped me to tidy up my code somewhat.
I'd really like to see the ":subdomain" option on url helpers as a patch for Rails 3, will you be submitting? ...If not I may do so as it's super useful.
If you have to deal with various top level domains and third level assignments in parallel (.e.g. some have .com, some others co.uk) you may want to use the public suffix library from:
I just figured out how to get this working and blogged about it a couple of days before you did this! I like your solution more though. In case anyone is interested, I also blogged about how to test it with cucumber/capybara: http://mattbeedle.com/2010/07/04/testing-subdomains-with-cucumber-cabybara-and-rack-test
In Rails 3.0.0.rc there seems to be an issue using :domain => :all - it flips out with an InvalidAuthenticityToken error. Using :domain => ".smackaho.st" works for the time being.
Per https://rails.lighthouseapp.com/projects/8994/tickets/5147-the-all-domain-option-for-the-cookie-session-store-doesnt-allow-non-standard-tlds-like-local-or-couk
It's weird that in the session_store.rb file, :domain => :all doesn't work for me (in Edge). :domain => 'lvh.me' does work though... any insights about this?
:domain => :all doesn't work in the Rails 3 release candidate (it results in an InvalidAuthenticityToken error). The issue is resolved in Rails 3 master on GitHub with commit fd78bb72704554737117 by Bryce Thornton on 14 Aug 2010.
Thanks, Ryan! For anyone who needs more, I put together a Rails 3 example app (with a detailed walk-through tutorial) that shows how to set up subdomains in Rails 3 using Devise for authentication: http://github.com/fortuity/rails3-subdomain-devise (click above for the link). For anyone who needs a quick start for blog-style subdomains using Rails 3.
I'm struggling with one problem regarding subdomains and nested resources. As nested resources become top level resources with a subdomain, the following seems to work
resources :blogs do
resources :articles
resources :comments
end
constraints(Subdomain) do
match '/' => 'blogs#show'
resources :articles
resources :comments
end
which allows
personal.lv.me:3000/articles to correctly go to articles#index where I do a blog.find_by_subdomain as a before_filter.
However, the problem comes in a named route when I try generate a url. If I do
<%= link_to "View all articles", blogs_articles_path(@blog) %>
I will get lv.me:3000/blogs/1/articles which is correct.
However, if, as a user, I am browsing personal.lv.me:3000/ rails will generate personal.lv.me:3000/blogs/1/articles, which is incorrect as it should be personal.lv.me:3000/articles
I can rectify this by doing <%= link_to "View all articles", articles_path %>, and the path will be correct. But now it will be broken again if I browse without a subdomain.
Is there anyway to get rails to automatically remove the nested resource from the path if a subdomain is detected?
I'm not sure if you are still looking for the answer, but as I just went through this episode and I am going to use a similar functionality with subdomains, as you need, I guess I know the answer for your question.
First of all, you can not expect to have in return of _path helper methods anything with the host. Instead use the _url helper methods. That will lead you into the 2nd point.
Based on the root_url(:subdomain => @blog.name) used in the episode and thanks to the overridden url_for helper you can use the subdomain key in the options of any _url helper methods. Here we go:
I think you could also override blogs_articles_url helper method to be consistent with using nested resources way of creating urls. The below code is just an idea and should be re-factored to use all functionality of blogs_articles_url helper method, but for simplicity I put the below.
ruby
defblogs_articles_url(options = nil)
if options.kind_of?(Blog)
articles_url(:subdomain => options.try(:subdomain))
elsesuperendend
I think I would personally prefer to use articles_url with :subdomain option.
Hey, great tutorial on subdomains, is there a simple way to avoid carrying the subdomain around in all other matched or resourceful routes apart from root_url(), my navigation is full of links like:
http://personal.lvh.me:3000/terms/index
where I really want
http://lvh.me:3000/terms/index OR
http://www.lvh.me:3000/terms/index
There's one important thing to know if you want to share sessions between subdomains on localhost. Using :domain => ".lvh.me" not always works (in my case it didn't), so you have to configure your environment as described in http://blog.plataformatec.com.br/2009/12/subdomains-and-sessions-to-the-rescue/
Is there a way to setup a default subdomain for all helpers?
Let's say I have www.domain.com and foo.domain.com . I would like to all helper (links, forms, urls, ...) render by default with the www subdomain, despite the request was targeted to either host.
I tried set default_url_options to :subdomain => false (performing all needed steps) but couldn't make it.
I'm having a really hard time getting this to work with devise to share cookies and authentication info between sessions, has anybody had this type of problem before?
i had to overwrite url_for in application_helper not in application_controller .. is that new in rails 3.0.5 ?
Not sure why, but that is how it works ..
Tim,
I'm on Rails 3.0.5 and Ryan's instructions work for me precisely.
In Application Controller, you only need one line of code:
include UrlHelper
... an the rest is in UrlHelper.
I wish I could delete the post right above. It was a bad typing problem.
But I have another problem, a real one this time: flash messages are not working properly. I'm using Devise and everything is ticking right about the user, but I'm experiencing some funny behavior. When I create a new resource that is accessible through a subdomain, at the main domain, and redirect right after to this new resource, the flash message persists until I go to the main domain.
Beyond that, other flash messages, like editing this resource, don't appear at all.
Any ideas? I'm using Rails 3.0.7 and did everything that our best buddy Ryan did.
I've implemented the above and it works wonderfully, thank you!
My only issue is that while url_for is producing links correctly in development, in my test environment my links are coming out as www.example.com?subdomain=example. Any idea what I'm missing?
Does anyone have a problem with Internet Explorer? I couldn't get the session store accross subdomains working well...
It works fine most of the times, but sometimes it seems the session is different between subdomains... example: if I log out from subdomain1.domain.com and after that I visit subdomain2.domain.com for some reason I am still log in!
The behavior is strange, but it just happen in Internet Explorer =/ and, as I said before, it only occure sometimes...
Hello, I am trying to implement the subdomains on my app. I am using rails 3.1.rc5. The problem is that "constraints" in my route.rb does not work and i am redirected to my app root. However if I use "constraint" (singular), my subdomain is parsed and i am succesfully routed to the show action of the controller i wanted (SchoolsController). The problem with this is that when i do not use a subdomain and therefore wish to be redirected to the root of my app, i get an "ActiveRecord::RecordNotFound" because it cannot find a School with that subdomain.
I had to delete request.port_string from the with_subdomain join function in Rails 3.1 as the request.domain already included it, so I was getting :3000:3000
Hi, I am new on Rails and I really like this screen cast to implement on my first app. But wonder if this screen cast is applicable on a real domain, cause most of comments here are pointing to localhost.
I wan't to use it on my testing domain which is http://ngtv2.info/ and if possible, to have i.e. kingpangilinan.ngtv2.info
having issues testing my helpers using Test::Unit. It seems that when a helper method uses url_for (i.e. link_to) it doesn't call the modified url_for method in the UrlHelper module.
I've added
ruby
classGenericHelperTest < ActionView::TestCase
include UrlHelper
include Rails.application.routes.url_helpers
end
I seek advice about configuring the domain length, different for staging and production. I have an app that uses subdomain. The same app is hosted in a staging environment and production environment on the same server.
I am just running localhost via rails server, and somehow I can't get any of the subdomains to load any pages. So lets just say if I use user1.example.com:3000 (i run my development on a remote server), the page just doesn't load.
And example.com:3000 works. I've read multiple tutorials, but wasn't able to find an answer to this.
I've also tried this on my windows PC, and have set these in host file 127.0.0.1 subdomain1.localhost.local company.blog.local personal.blog.local, but this doesn't work either.
Pulling my hair out for this. Any help is appreciated!
What got me in this was editing my own /etc/host file to have '127.0.0.1' point to my own custom wildcard domain '*.local.me'
After some research, I discovered you can't have a wild card in your /etc/host file. When Ryan says to use 'lvh.me:3000', literally use that rather than editing your /etc/host file. You can then use your subdomains.
Hey,
When I first try lvh.me:3000, it is working fine. But now I have problem with lvh.me:3000 it does not work any more, do you know how to solve this. I've been try on google but I cannot found any solution.
Thx.
Thanks for this Ryan!
I've been trying to get Devise and subdomains to work together, by using one of the Subdomain plugins, but not managed to get there fully. Going to have a go using your approach now and see how I get on.
Keep up the great casts, they are always mega helpful!
Finally got Rails 3 working with RVM. Stopped using my local Passenger installation and now I'm really enjoying the flexibility of jumping around to different versions of Ruby/Rails.
Currently developing an app that requires account level subdomains and was unhappy with the options in Rails 2.3...
Looking forward to Rails 3 RC, thanks again for all the awesome screencasts!
Great vid, was meaning to have a look at the subdomains in rails3, but you just summed it up nicely.
Also plus points for picking up on smackaho.st :)
In this line of your code:
options[:host] = with_subdomain(options.delete(:subdomain))
what does options.delete() do? It doesn't seem intuitive, which is rare in Ruby.
--dhc
Is it possible to use domain size 0? I need to show different content depending on domain name, but the main part of the site is the same.
@dhc: It removes the passed element from the hash and returns it. See http://ruby-doc.org/core/classes/Hash.html#M002870
Hi, Ryan.
I've wrote similar article some months ago (http://bit.ly/ajGym2 - sorry, only Russian version, but you can use Google Translate) but there are some problems with session sharing between subdomains in Opera browser - unfortunately Opera cannot read cookies from sibling domain - it means if you set cookie for dom1.example.com cookie cannot be read from dom2.example.com
@Alexey Poimtsev:
There's a blog article on my.opera.com that describes how the Opera browser deals with cookie sharing between subdomains.
To summarize (very quickly) the article: any *.example.tld subdomains are considered as siblings (and can share domain=.example.tld cookies) if the example.tld domain has a registered IP address in DNS.
The reality is a little more complicated, so the
http://my.opera.com/yngve/blog/show.dml/267415 article deserves a read.
Thanks Ryan!
I really wish I had this to hand a couple of weeks ago when trying to figure out the subdomain stuff in Rails 3. This has helped me to tidy up my code somewhat.
I'd really like to see the ":subdomain" option on url helpers as a patch for Rails 3, will you be submitting? ...If not I may do so as it's super useful.
Thanks again.
@Alexander, I mention changing the top level domain size at the end of the episode. I haven't tested it, but passing "0" for the tld size should work.
@Jamie, I think the problem with adding a built-in :subdomain option is that the top level domain size is not easily configurable.
That said, I think a ticket on configuring the default tld size along with this would be great. I don't have plans to do this so feel free to.
I think
constraints(Subdomain) do
match '/' => 'blogs#show'
end
can be even shorter, like
constraints(Subdomain) do
root :to => 'blogs#show'
end
If you have to deal with various top level domains and third level assignments in parallel (.e.g. some have .com, some others co.uk) you may want to use the public suffix library from:
http://www.simonecarletti.com/blog/2010/06/public-suffix-list-library-for-ruby/
This is far better than hardcoding the length in your app and also used by browser vendors already.
hth,
Roland
I just figured out how to get this working and blogged about it a couple of days before you did this! I like your solution more though. In case anyone is interested, I also blogged about how to test it with cucumber/capybara: http://mattbeedle.com/2010/07/04/testing-subdomains-with-cucumber-cabybara-and-rack-test
I just get an error...
uninitialized constant Subdomain (NameError)
Great screencast as usual, thanks Ryan !
On Mac OS X, "*.127localhost.*" resolves to 127.0.0.1 too: it's really helpful to test applications against both subdomains and TLDs.
Thanks for this post, but it don't work for ActionMailer.
Here my path:
http://gist.github.com/478169
If you get the error
uninitialized constant Subdomain (NameError)
it seems that in the later versions of the Rails 3 beta or the edge version the routes file doesn't autoload /lib/subdomain.rb
Adding
require 'subdomain'
before the routes block fixes this.
Solves the problem for me.
In Rails 3.0.0.rc there seems to be an issue using :domain => :all - it flips out with an InvalidAuthenticityToken error. Using :domain => ".smackaho.st" works for the time being.
Per https://rails.lighthouseapp.com/projects/8994/tickets/5147-the-all-domain-option-for-the-cookie-session-store-doesnt-allow-non-standard-tlds-like-local-or-couk
@george (#35) : I agree.
It's weird that in the session_store.rb file, :domain => :all doesn't work for me (in Edge). :domain => 'lvh.me' does work though... any insights about this?
@docgecko (#2) : devise works fine for me here.
@Doug Mayer (#36):
@thb (#47):
:domain => :all doesn't work in the Rails 3 release candidate (it results in an InvalidAuthenticityToken error). The issue is resolved in Rails 3 master on GitHub with commit fd78bb72704554737117 by Bryce Thornton on 14 Aug 2010.
Thanks, Ryan! For anyone who needs more, I put together a Rails 3 example app (with a detailed walk-through tutorial) that shows how to set up subdomains in Rails 3 using Devise for authentication: http://github.com/fortuity/rails3-subdomain-devise (click above for the link). For anyone who needs a quick start for blog-style subdomains using Rails 3.
Hello Ryan. Great cast!
However I have faced some troubles with the routing. The line:
match '/' => 'blogs#show', :constraints => {:subdomains => /.+/}
gives out this error when not requesting a subdomain e.g. http://lvh.me:3000/
undefined method `match' for []:Array
Any ideas on what could be wrong?
Thanks
Rails 3 includes all helpers by default, so the include Urlhelper is not necessary.
Hi Ryan,
I'm struggling with one problem regarding subdomains and nested resources. As nested resources become top level resources with a subdomain, the following seems to work
resources :blogs do
resources :articles
resources :comments
end
constraints(Subdomain) do
match '/' => 'blogs#show'
resources :articles
resources :comments
end
which allows
personal.lv.me:3000/articles to correctly go to articles#index where I do a blog.find_by_subdomain as a before_filter.
However, the problem comes in a named route when I try generate a url. If I do
<%= link_to "View all articles", blogs_articles_path(@blog) %>
I will get lv.me:3000/blogs/1/articles which is correct.
However, if, as a user, I am browsing personal.lv.me:3000/ rails will generate personal.lv.me:3000/blogs/1/articles, which is incorrect as it should be personal.lv.me:3000/articles
I can rectify this by doing <%= link_to "View all articles", articles_path %>, and the path will be correct. But now it will be broken again if I browse without a subdomain.
Is there anyway to get rails to automatically remove the nested resource from the path if a subdomain is detected?
Joel,
I'm not sure if you are still looking for the answer, but as I just went through this episode and I am going to use a similar functionality with subdomains, as you need, I guess I know the answer for your question.
First of all, you can not expect to have in return of
_path
helper methods anything with the host. Instead use the_url
helper methods. That will lead you into the 2nd point.Based on the
root_url(:subdomain => @blog.name)
used in the episode and thanks to the overriddenurl_for
helper you can use thesubdomain
key in the options of any_url
helper methods. Here we go:I think you could also override
blogs_articles_url
helper method to be consistent with using nested resources way of creating urls. The below code is just an idea and should be re-factored to use all functionality ofblogs_articles_url
helper method, but for simplicity I put the below.I think I would personally prefer to use
articles_url
with:subdomain
option.Hope that helps.
Hey, great tutorial on subdomains, is there a simple way to avoid carrying the subdomain around in all other matched or resourceful routes apart from root_url(), my navigation is full of links like:
http://personal.lvh.me:3000/terms/index
where I really want
http://lvh.me:3000/terms/index OR
http://www.lvh.me:3000/terms/index
Thanks in advance!
Ryan has an example of setting the subdomain to false in the show notes. You can use it like this.
There's one important thing to know if you want to share sessions between subdomains on localhost. Using :domain => ".lvh.me" not always works (in my case it didn't), so you have to configure your environment as described in http://blog.plataformatec.com.br/2009/12/subdomains-and-sessions-to-the-rescue/
Is there a way to setup a default subdomain for all helpers?
Let's say I have www.domain.com and foo.domain.com . I would like to all helper (links, forms, urls, ...) render by default with the www subdomain, despite the request was targeted to either host.
I tried set default_url_options to :subdomain => false (performing all needed steps) but couldn't make it.
@Brian J. Cardiff #48
Try add ":subdomain => false" in you'r routes.rb for lines in which you want to use default subdomain.
Hi Ryan,
How would you approach writing a test case for this UrlHelper?
Seems that simply calling root_url(:subdomain => "sub") in a test doesn't make it use UrlHelper's url_for at all.
I'm having a really hard time getting this to work with devise to share cookies and authentication info between sessions, has anybody had this type of problem before?
thanks!
ok, update on my last comment, I neglected to remove the cookies that were previously there, everything is now functioning smoothly, thanks!
i had to overwrite url_for in application_helper not in application_controller .. is that new in rails 3.0.5 ?
Not sure why, but that is how it works ..
Tim,
I'm on Rails 3.0.5 and Ryan's instructions work for me precisely.
In Application Controller, you only need one line of code:
include UrlHelper
... an the rest is in UrlHelper.
Here is a nice solution how to test an app with subdomains using rspec http://stackoverflow.com/questions/2556627/rails-rspec-set-subdomain
I wish I could delete the post right above. It was a bad typing problem.
But I have another problem, a real one this time: flash messages are not working properly. I'm using Devise and everything is ticking right about the user, but I'm experiencing some funny behavior. When I create a new resource that is accessible through a subdomain, at the main domain, and redirect right after to this new resource, the flash message persists until I go to the main domain.
Beyond that, other flash messages, like editing this resource, don't appear at all.
Any ideas? I'm using Rails 3.0.7 and did everything that our best buddy Ryan did.
No need for lvh.me in development if you are using Pow. It handles subdomains automatically.
I've implemented the above and it works wonderfully, thank you!
My only issue is that while url_for is producing links correctly in development, in my test environment my links are coming out as www.example.com?subdomain=example. Any idea what I'm missing?
Does anyone have a problem with Internet Explorer? I couldn't get the session store accross subdomains working well...
It works fine most of the times, but sometimes it seems the session is different between subdomains... example: if I log out from subdomain1.domain.com and after that I visit subdomain2.domain.com for some reason I am still log in!
The behavior is strange, but it just happen in Internet Explorer =/ and, as I said before, it only occure sometimes...
Any ideas?
I am currently getting a
"can't convert Symbol into Integer"
error and I am not sure why...The offending lines are:
specifically the first line
Here is a pastie to my UrlHelper which is slightly modified...
http://pastie.org/private/nnfgboyxmarlcdh3nakokw
Solved it...
that needed to replace line 12 of the pastie code...
Hello, I am trying to implement the subdomains on my app. I am using rails 3.1.rc5. The problem is that "constraints" in my route.rb does not work and i am redirected to my app root. However if I use "constraint" (singular), my subdomain is parsed and i am succesfully routed to the show action of the controller i wanted (SchoolsController). The problem with this is that when i do not use a subdomain and therefore wish to be redirected to the root of my app, i get an "ActiveRecord::RecordNotFound" because it cannot find a School with that subdomain.
Anybody else having a similar issue? any ideas?
ok, I managed to fix it. I had to tell rails to load my lib directory in my
config/application.rb
file by adding these lines:and using:
in my
routes.rb
Hope this helps
You may want get wildcard to localhost working by
http://hints.macworld.com/article.php?story=2005110220352084&query=launchd+named+localhost
so, it's possible to localhost
my.dev.box.localhost, foo.localhost, so on
thanks for this episode
I had to delete request.port_string from the with_subdomain join function in Rails 3.1 as the request.domain already included it, so I was getting :3000:3000
Thanks! I was also getting the :3000:3000. This fixed it for me too.
Hi,
my issue is not really related to this railscast but I'm also getting :3000:3000 when using _url helpers.
What you did could solve this issue? So yes, could you explain, I don't find this 'with_subdomain' function anywhere.
Thanks.
Thanks heaps Ryan. I've built a subdomain-based link shortener with help from your screencast.
I just tried to replace the subdomain condition (before_filter)
with a routing contraint.
Unfortunately my controller specs fail. I had specs in place
that check that I get 404 when accessing certain actions
without a subdomain.
Having a look I can see that the contraint class is never called.
Seems the specs just ignore the contraint for some reason.
Works perfectly when I try it manually.
This might be a better solution anyway:
{
:get => "http://sub.test.host/invitations/new"
}.should route_to(:controller => "invitations", :action => "new")
{
:get => "http://test.host/invitations/new"
}.should_not be_routable
@ryan : Seems there is something wrong with the (reply/edit/delete) buttons, refreshing the page seems to fix it.
url_for
in Rails 3.0+ includes the :subdomain option, so you don't have to override the method any more.Hi, I am new on Rails and I really like this screen cast to implement on my first app. But wonder if this screen cast is applicable on a real domain, cause most of comments here are pointing to localhost.
I wan't to use it on my testing domain which is http://ngtv2.info/ and if possible, to have i.e. kingpangilinan.ngtv2.info
Even though I include this code in my routes.rb
I still get a Server not found Firefox can't find the server at kingpangilinan.ngtv2.info when I browse for http://kingpangilinan.ngtv2.info/
I wonder how I will implement it using my ngtv2.info instead of lvh.me:3000 or localhost:3000
It's now working for me, I wish I could delete this comment
Hi Ryan,
having issues testing my helpers using Test::Unit. It seems that when a helper method uses url_for (i.e. link_to) it doesn't call the modified url_for method in the UrlHelper module.
I've added
but that doesn't help.
Any hint?
Hi Ryan,
I seek advice about configuring the domain length, different for staging and production. I have an app that uses subdomain. The same app is hosted in a staging environment and production environment on the same server.
stagin paths:
http://staging.example.com
http://staging.example.info
http://staging.other-example.com
production paths:
http://example.com
http://example.info
http://other-example.com
The TLD length is 1, but how can i set the Domain length, so that in staging the domain length is 2 and in production the domain length is 1
Thanks in advance!
Marek
Testing subdomains in Rails with xip.io
http://www.chrisaitchison.com/2013/03/17/testing-subdomains-in-rails
Covers how to get Capybara to play nice without editing /etc/hosts
I use
request.subdomains.first
rather thanrequest.subdomain
as recommended by DHH: http://37signals.com/svn/posts/1512-how-to-do-basecamp-style-subdomains-in-railsIf you use
request.subdomain
and use an IP address as the URL,request.subdomain
will include the IP address.I am just running localhost via
rails server
, and somehow I can't get any of the subdomains to load any pages. So lets just say if I use user1.example.com:3000 (i run my development on a remote server), the page just doesn't load.And example.com:3000 works. I've read multiple tutorials, but wasn't able to find an answer to this.
I've also tried this on my windows PC, and have set these in host file
127.0.0.1 subdomain1.localhost.local company.blog.local personal.blog.local
, but this doesn't work either.Pulling my hair out for this. Any help is appreciated!
What got me in this was editing my own /etc/host file to have '127.0.0.1' point to my own custom wildcard domain '*.local.me'
After some research, I discovered you can't have a wild card in your /etc/host file. When Ryan says to use 'lvh.me:3000', literally use that rather than editing your /etc/host file. You can then use your subdomains.
Also, since we're on Rails 4 now, check out:
http://railscasts.com/episodes/123-subdomains-revised
I need Help...
http://stackoverflow.com/questions/25843339/rails-app-is-not-working-with-subdomain-on-production
Checkout
ngrok.com
Once setup, running a subdomain is as easy as:
ngrok -subdomain=mysubdomain 3000
https://mysubdomain.ngrok.com -> 127.0.0.1:3000
http://mysubdomain.ngrok.com -> 127.0.0.1:3000
I used it to test PayPal's IPN for recurring subscriptions.
Hey,
When I first try lvh.me:3000, it is working fine. But now I have problem with lvh.me:3000 it does not work any more, do you know how to solve this. I've been try on google but I cannot found any solution.
Thx.