Accessing URL/URI information in Rails in the environments file? - ruby-on-rails

How would I access the domain name from Rails inside the environments/deveopment.rb? I want to find out whether or not I am on localhost or a real domain. Thank you!

The environment files are not processed on every request- only at startup, so there wouldn't be any particular context at the time they are processed. This is really the job for a separate environment instead of having dev do double duty.
If you just want to check against the hostname or something though, you can do something like (assuming you're on a unix-like system):
my_host = `hostname`.chomp
and test against that, which may solve your problem.

Related

Possible to have more than one redirect_uri?

I would like to be able to redirect to a development environment in addition to the production environment. Is it possible to specify more than one redirect_uri? Specifically, I would like to be able to redirect to localhost.
Thanks!
You need to do like me, create several apps, one for each environment.

better way to configure the email address with rails application

Currently, I'm working on the application which is developed in rails 3* and ruby 1.9.3. I have configured some email address in the initializers section as YML file for each environments.
But, the requirement is keep on changing (but it'll happened every month 1 or 2 times) that need to add/remove the email address from the configuration. Hence, I need to restart the server on every changes. Because, I configured those address in the initializers.
Is there any better way to handle this situation?
If you want to change the email without re-deploying / restarting the server, you can always create a Email model and persist it to the database. By adding a current field / column (boolean value) and a scope scope :current, -> { where(current: true) } you can access the email via Email.current.first.address, for instance. You might need to ensure that one and only one 'current' Email object ist present at any given time.
edit
creating a model does not mean you have to create UI for it. Just use the console to change the email if you have to.
the configuration and models are loaded at startup, and if you don't want to do any reloading in production, which is slow and not recommended, you have to use the DB for persistence.
if you really want to go down the "reload" route, set config.cache_classes = true in config/environments/production.rb and specify the email in a constant outside the config directory (in some model or controller) like this EMAIL = 'whatever#email.com'. You would have to change the production code on each production machine, without a server restart. Sounds very hacky. Look into zero-downtime deploys à la Github for a more elegant solution. Redeploying should be cheap and painless.

How to get domain/subdomains of an app outside of controllers/views?

How can I get the domain and subdomains of my application without being in a controller/view?
The reason for needing this is that I am subscribing to process_action.action_controller notifications within an initializer, and I need my applications' url from within that initializer.
If the host part of the URL (domain, subdomain) is dynamic ... which is to say "depends on the request" then, of course, the only way to get it is within the context of the request itself, which the controllers and views know about.
So I am assuming the application has a known host, perhaps dependent upon runtime environment (production, test, development, etc.), or maybe based on the server environment, but otherwise static. In this case, you could define a custom config variable containing the name, as noted in the more recent answer from Jack Pratt on this SO question: How to define custom configuration variables in rails.

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!

Subdomains and locally installed Rails app

I can't figure out what I'm overlooking, perhaps it's obvious or lack of understanding.
The app I'm working with uses subdomains which on the hosting server work properly. I figured locally installing would kick up some issues around routing, so I read up on making changes to /etc/hosts and using the Ghost gem. Both seem to work fine i.e. localhost:3000/ becomes myapp.local:3000 but I don't understand how to go about logging into a subdomain account. Here's an example...
myapp.local:3000/session/new = the default login page for the app
myapp.local:3000/signup = default signup page
I can create an account here e.g. Sub1
The thank you page is shown w/ the reference to sub1.myapp.com which points to the hosted app (the local db shows this domain as well)
sub1.myapp.local manually added to /etc/hosts and dscacheutil -flushcache
sub1.myapp.local:3000/session/new is the subdomain
login attempts return that this isn't a valid domain. This seems to make sense because the local db shows the url as sub1.myapp.com on the hosting server.
So my question is whether there's a local workaround that I can use for development or have I totally missed a fundamental concept along the way?
you might just want to try putting the actual dot com in your /etc/hosts file.
ie:
127.0.0.1 sub1.myapp.com
127.0.0.1 myapp.com
127.0.0.1 anyothersubdomains.myapp.com
what this usually does is trick your computer into thinking it is the host of all of those, so you can't go to the real site anymore in a web browser.
if you do want it to be .local, presumably so that you can refer to the real online site while working on a local copy, you should probably take a look in app/controllers/application_controller.rb (sometimes application.rb) and look for logic in there that helps determine what to do depending on the subdomain. maybe its hard coded to only look for a .com or something.
If you are using the webrick server or something like Puma for development you can use lvh.me to access your subdomains. e.g.
http://sub.lvh.me:3000/
http://lvh.me:3000/ is equal http://localhost:3000/

Resources