开发者

RoR 3, Passenger, Relative URLs, and helper methods such as root_url

I'm really struggling to understand the routing behaviour I'm seeing with a Rails 3 app as it relates to Passenger and routing helper methods. Here's a quick overview:

When a user registers for my site, one of the things I'd like to do is send out a verification email to make sure the user has submitted a valid email address. So, I set up mailer to send the user a URL with some sort of magic token, thereby proving that they have received the email I sent. The URL in the body of the email is generated via a routing helper method (in this case, verify_url("a1b2c3") ) and the URL is stuffed into the email appropriately as:

http://localhost:3000/verify/a1b2c3

This all works great under localhost:3000 without a hitch. So, like a responsible developer, the next thing I do is move my app to my remote QA environment and verify that everything still works. My hosting provider uses Passenger, and I have it set up so that my QA environment can be accessed as follows:

http://my.url/qa

This is done by setting RailsBaseURI to /qa in the appropriate .htaccess file. So, I'm trying to register for the site in my QA environment, and I'm hoping that the helper method verify_url generates the following URL:

http://my.url/qa/verify/a1b2c3

However, this is what I get instead:

http://my.url/verify/a1b2c3

Notice the distinct lack of reference to the 'qa' path? I've scoured various blogs and manuals looking for an开发者_运维问答 answer, and I've seen the following suggestions:

  • Set an environment variable such as ENV['RAILS_RELATIVE_URL_ROOT']
  • Set ActionController::Base.relative_url_root in my environment/qa.rb
  • Add a map to my config.ru to initialize my app under a particular path
  • Wrap my routes in a scope

However, each of these seems either to be deprecated (the first two options), or ends up producing redundant path info (the second two options) as follows:

http://my.url/qa/qa/verify/a1b2c3

Can anyone tell me the proper way to set this up, such that when I call verify_url("a1b2c3"), I'm actually getting the proper URL, including the relative path for my QA environment? Ideally, I'd want to be able to set this in environments/qa.rb somehow, such that I don't have to change my app at all when moving from one environment to the next.

Thanks in advance!


I would dismiss the whole /qa/ and move the staging to a subdomain like http://qa.my.url/ Otherwise you will have to make changes to the code that might affect production in a negative way.

Update

I've ignored the the fact that you wanted to use those routes in emails. In this case you will have to set :host in the url helper:

verify_url(:id=>"a1b2c3", :host=>"qa.my.url")

To cut down the amount of changes you would have to make once you go into production, I would suggest you define a constant in an initializer (in /path/to/app/config/initializers/my_host.rb):

MY_HOST = 'qa.my.url'

After that you could call verify_url in your email templates like so:

verify_url(:id=>"a1b2c3", :host=>MY_HOST)

Once you go into production, change the MY_HOST constant and you won't have to worry about the templates.

In my views I never use the *_url helpers, only the *_path ones to circumvent this issue.


After spending a little time with the ActionMailer docs, it turns out that there is an even easier solution, at least for what I am looking to accomplish. Wukerplank definitely answered my question, but it seems that I wasn't quite asking the right question. :-)

The only time I really need to see the fully qualified URL is when I'm working within a mailer, right? Otherwise, paths work just fine. Well, it turns out that ActionMailer allows you to specify default url options on a per-environment basis. In my environments/development.rb config file, I now have the following:

config.action_mailer.default_url_options = { :host => 'localhost:3000' }

When I move to my QA environment, I just need to tell Passenger that I'm running from QA, and have something like this environments/qa.rb config:

config.action_mailer.default_url_options = { :host => 'qa.my.url' }

That way, the code doesn't have to change one bit between environments, and thus, I really don't care what domain, subdomain, or port I'm running on... It just works. Hope this helps someone else in the future. Thanks!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜