How to perform URL redirects properly? - url

In the action class, I have this one at the end of the function:
$this->redirect("/myproject_dev.php/login/");
In which I hard code the development project name in the url. of course it works while I'm doing development but when it comes to production, I need to remove that.
so, how do I find out the project name ("myproject_dev.php") in the code? so that I can do this:
$this->redirect($myProjectDevName . "login/");
or.. is there a smart way to handle this?
thanks.
------ ADDition ---
so, I used the public_path as suggested. but it only returns the root path.
I'm wondering if there is a function that when I run in development mode:
http://mydomain.com/myproject_dev.php/whatever
in its action class:
$this->redirect(public_path('login'));
and result in
http://mydomain.com/myproject_dev.php/login
while if I run in production:
http://mydomain.com/whatever
the action class is unchanged:
$this->redirect(public_path('login'));
it will return this:
http://mydomain.com/login
or.. how to get the application name and symfony environment name?
:)

You should use the symfony routing system and call a routing rule from your routing.yml:
$this->redirect('#login');
This way it becomes separate of your environment and you wan't need to change anything when you're ready to move to production.

you could try
public_path()
http://www.symfony-project.org/api/1_4/UrlHelper#method_public_path

try this put this in your function
$this->redirect("MODULENAME/ACTION");
ex: $this->redirect("pim/admin");
this will redirect you to the pim module admin action...

Related

Where is a logical place to put a file flag?

In a Ruby on Rails application, where would the most logical place be to put a "file flag."
I am attempting to externalize configuration and allow the presence of a file to be the deciding factor on whether or not something shows on the webapp.
Right now, I have a file here:
lib/
deployment_enabled
Model deployment.rb
class Deployment...
...
def deployment_enabled?
Dir["#{Rails.root}/lib/deployment_enabled"].any?
end
end
Now this works of course, but i'm not sure this follows the MVC paradigms, since the lib directory should consist of scripts. I could put it in config, but again - not sure it belongs there as rails uses this for rails specific configuration, not necessarily the webapp.
I could of course put this in our database, but that require a new table to be created, and that seems unnecessary.
Where's the most logical place to put this flag file? Does Rails have a directory that's created during the generation to put these sort of files?
I suggest using the Rails tmp directory for this purpose. Then:
File.exist?("#{Rails.root}/tmp/deployment_enabled")
Phusion Passenger use this kind of mechanism too.
https://www.phusionpassenger.com/library/walkthroughs/basics/ruby/reloading_code.html#tmp-always_restart-txt
I recommend that you follow the Twelve-Factor App guidelines and keep your code separate from your configuration. In this case you are really talking about a simple boolean value, and the presence of the file is just the mechanism you use to define the value. This should be done instead through an environment variable.
Something like:
DEPLOYMENT_ENABLED=1 RAILS_ENV=production rails server
You would then use an initializer in Rails to detect the value:
# config/initializers/deployment.rb
foo if ENV['DEPLOYMENT_ENABLED']
The value can still be modified at runtime, e.g., ENV['DEPLOYMENT_ENABLED'] = 0.

Mock Rails 4 application config custom value

In Rails::Application, I add a custom configuration using...
config.x.cache_config = config_for(:cache)
In my tests, I want to see how code using this behaves depending on how the configuration is defined in cache.yml. To set the various conditions in my rspec tests, I want to do something like...
allow(Rails.application.config.x).to recieve(:cache_config).and_return({})
But this doesn't work. It gets an error stating
#<Rails::Application::Configuration::Custom ... > does not implement: cache_config
After much digging and testing in pry, I figured this out.
Short answer:
allow(Rails.application.config.x).to receive(:method_missing).with(:cache_config).and_return({})
Everything in this statement has to be exact except...
replace :cache_config with the name of your custom configuration key
replace {} in the and_return({}) with the mock value you want to set for the key
Longer answer:
If you want to dig into why this is, since it is not at all obvious, check out the code at...
Custom class in Rails::Application::Configuration
Creation of #x for custom configs in Rails::Application::Configuration
In case this helps anyone using Mocha, I ended up doing this in a helper
Rails.application.config.x.stubs(:my_config).returns(true)
yield
Rails.application.config.x.unstub(:my_config)
The method_missing trick above didn't work for some reason (guessing to do with differences in the way the stubbing is implemented), failing with an error message about the Configuration::Custom class not responding to method_missing the first time it was referenced for a different piece of config.
Adding to the above answer(s), if you want to stub nested config, then you have to make sure that you're allow-ing the second-last piece in the config to receive(:method_missing), as such:
allow(Rails.application.config.x.foo.bar).to receive(:method_missing).with(:foobar).and_return(:baz)
The above code stubs the Rails.application.config.x.foo.bar.foobar config to return :baz.

Rails - Add a route prefix to a specific directory

I have a messy rails 3 application that's come from a different developer and I need to refactor it.
What I want to do is move the contents of "app" into a subfolder called "classic".
app/classic
And then have all URL's with a classic prefix such as
localhost:3000/classic/wills/new
Route to controllers inside of the "app/classic" folder.
And then every regular url that does not contain the classic prefix - route in the standard way to app/
Is it possible to do this? The only thing I've discovered so far is that I can add a scope inside of my routes file.
scope(:path => '/classic')
But all that does is require a prefix for every URL. I'm really not sure how to go about this!
This is a route namespace. Take a look at this section in Rails Routing from the Outside In: http://guides.rubyonrails.org/routing.html#controller-namespaces-and-routing
namespace :classic do
# your routes here
end
This will do 3 things -
the path to the controller files need to be under /app/controllers/classic/
the name of the controllers need to change to Classic::ControllerName
the url is now /classic/controller/action
This sounds like what you want, but you can modify this to get just the parts you want if you don't want all 3.
In route.rb file:
#Of course, you have to configure the right http method.
get 'wills/new' => 'wills#new', as: 'to_classic_wills_new'
Hope this helps!

Random method named cv_member_url()

I'm a total noob to rails and I'm trying to understand a project I'm working on. I've found a method named cv_member_url in one of the views, but I can't for the life of me figure out where it is defined... One thing I do know about rails is that it is a very flexible language so it could be some sort of gem creating this method.
Any ideas where this method may have come from? (or better yet, how I can add others)
Thank you!
Do you have a model called CvMember? If so, the method is probably a named route for that model. See here for more info:
http://guides.rubyonrails.org/routing.html#paths-and-urls
To see all your named routes, you can run
rake routes
Those are named routes which are automatically defined based on what you have in routes.rb. *_url should be used in the controller, and *_path should be used in the views. Here's some more info from the official rails guide.
Assuming you can run this in development: You should put a breakpoint on it and step inside. Most likely it is dynamically defined or maybe in plugin.

Rails - How to obtain an absolute URL for the site? https://example.com

For one of my models I have a method:
def download_url
url = xxxxx
end
which works nicely to make /xxxx/xxxx/3
What i want to do is updated this to include an absolute URL so I can use this method in an email:
https://example.com/xxxx/xxxx/3
But I don't want to hard code. I want it to be an environment var so it works on dev & production
Emails are effectively views, and can use helpers. The model shouldn't really have any knowledge about the views - instead, you should use url_for or one of its descendant methods in the email view template to generate a URL. Those helpers can generate absolute URLs based on the location that the application is running (and associated configuration - you'll want to set config.action_mailer.default_url_options[:host] in your environment file) without having to mess with environment variables and the like.
I would define the domain as a constant in development.rb & production.rb:
APP_DOMAIN = "https://mysite.com"
And then just use this constant in your method within the model:
def download_url
"#{APP_DOMAIN}/download/#{id}"
end
It may be ugly, but it's necessary. Rails apps don't and shouldn't know their root URL. That's a job for the web server. But, hardcoding sucks...
If you're using capistrano or some other deployment method, you can define the server host in a variable and write it out to a file that you can read from the app.

Resources