Rails: Per-environment initializers? - ruby-on-rails

I'd like the code in one of my initializers (in config/initializers/) to be run only for the :development environment, but not :test or :production. What's the best way to do that?
Pasting it into config/environments/test.rb seems unclean, and I don't quite like wrapping the entire initializer file in an if Rails.env == 'development' do ... end statement. Is there some canonical way to do this?
(Background: To speed up test load times, I'm trying to move the Barista gem into the :development group of my Gemfile, but config/initializers/barista_config.rb calls Barista.configure, so now it chokes on that in test (and production) mode.)

I'm pretty sure your only two options are putting the configuration code in config/environments/development.rb or wrapping your initializer code with your if block. You can tighten up your second option by doing if Rails.env.development?, though.

I don't know if this is a good idea, but it's a different idea.
You could create a config/initializers/development directory (or config/environments/development/initializers), put your barista_config.rb in that directory, and then include anything in that directory from config/environments/development.rb.
I don't know if that's a good idea or not but it's at least a third option...just in case you're still thinking about this problem three and a half years after asking the question.

Barista has a config setting for this:
Barista.configure do |c|
c.env = :development
end
This will only recompile coffescript into js in dev mode and should speed up your tests.
Make sure you run:
rake barista:brew
before checking your code in.
https://github.com/Sutto/barista

Related

Ruby on Rails: configure web_console in initializer

I am using the web_console gem and I would like to add some IPs to the whitelist. For reasons that would probably go to far to explain, can't simply add something to the config/application.rb or config/environments/development.rb. However I can create an initializer config/initializers/.
I simple tried this in config/initializers/99-webconsole.rb, but while the file is loaded (--> debug message is shown), the web console does not seem to pick up my settings.
Rails.application.configure do
config.web_console.whitelisted_ips = '10.10.0.0/16'
p "Debug: this is loaded."
end
I assume it's related to some kind of race condition? Providing the same line in config/environments/development.rb works, but as said, I sadly can not change that file.
Based on this code https://github.com/rails/web-console/blob/e3dcf4c588af526eafcf1ce9413e62d846599538/lib/web_console/railtie.rb#L59
maybe there is a code in your initializer that configuring config.web_console.permissions, so your whitelisted_ips config is ignored
whitelisted_ips is also deprecated
and have you checked that you are using v4.2.0, the permissions was buggy and fixed by this commit https://github.com/rails/web-console/commit/6336c89385b58e88b2661ea3dc42fe28651d6296

Access APP_CONFIG['var'] inside routes? or supply routes with variables?

I need to do in rails 4 supply some ip address to set a constraint on certain routes.
Is there a way to get this data from a config file without harcoding it into the routes file?
Im using a yaml file and initializer for app variables like:
APP_CONFIG = YAML.load_file("#{Rails.root}/config/application.yml")[Rails.env]
so normally I could do:
constraints(:ip => %w[APP_CONFIG['app_url']]) do
.. my routes..
end
This fails in the routes.rb is there a way to fix this?
The routes.rb file is a ruby file which is instantiated once, and loaded into memory.
You can just add the ruby code inside it and it will be executed once:
Rails.application.routes.draw do
app_config = YAML.load_file("#{Rails.root}/config/application.yml")[Rails.env]
constraints(:ip => %w[app_config['app_url']]) do
.. my routes..
end
end
This will instantiate the routes.rb file with the variable loaded from the yml and available throughout your rails routes app. You don't even need to use a env variable. Local variable seems a better idea.
You can also put logic inside and make it environment dependant:
if Rails.env.production?
app_config = YAML.load_file("#{Rails.root}/config/application.yml")[Rails.env]
constraints(:ip => %w[app_config['app_url']]) do
.. my routes..
end
else
.. my routes ...
end
Taking a look at the initialization process of rails (http://guides.rubyonrails.org/initialization.html). You'll see that routing is actually loaded quite early (and earlier than application.rb or other initializers). It has therefore not yet loaded this file.
A way round this would be to place this into your boot.rb:
# Set up gems listed in the Gemfile.
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
#Now load app config:
require 'yaml'
APP_CONFIG = YAML.load_file(File.expand_path('../../config/application.yml', __FILE__))
I believe you are running into a load order issue. You could probably hack around this, but...
I would highly recommend using Figaro to solve this problem. It is a gem specifically designed for rails configuration and will work nicely with 12 factor app deployments (like Heroku): https://github.com/laserlemon/figaro
I am using Figaro in the app I am currently working on and was able to confirm access to the env variables within my routes file. I believe this gem will solve your current issue and other config issues you don't even know you have yet!

Local gem class is not found in Rails application

I have written a generator which creates the following ruby file and folder:
app/tests/test.rb
in the test.rb file I have a Test class which looks like this:
class Test < MyCustomModule::MyCustomClass::Base
...
end
Now, I want to use its functionality in one of the show.html.erb files creating new instance like this:
Test.new(...).render(...).html_safe
but I am getting the following error:
uninitialized constant MyCustomModule::MyCustomClass::Base
I have use the following answer to link my gem and my rails application. It seems to work as I am able to use the generator, but the gem module and class are not seen in the rails application.
Could anyone tell how to fix this issue?
I have try to follow the tips posted here but still nothing changed:
Adding config.autoload_paths += Dir["#{config.root}/lib/**/"] in application.rb file
I have created my gem structure looking at CarrierWave gem, so the naming should be correct
I try to disable config.threadsafe! but it is already disabled since config.cache_classes and config.eager_load are set to false in development
DEPRECATION WARNING: config.threadsafe! is deprecated. Rails
applications behave by default as thread safe in production as long as
config.cache_classes and config.eager_load are set to true.
Also, looking at adding-asset-to-your-gems rails documentation, it is said that:
A good example of this is the jquery-rails gem which comes with Rails
as the standard JavaScript library gem. This gem contains an engine
class which inherits from Rails::Engine. By doing this, Rails is
informed that the directory for this gem may contain assets and the
app/assets, lib/assets and vendor/assets directories of this engine
are added to the search path of Sprockets.
So, I have done this, and put my model class file in assets folder, but the result is the same.
The following screenshots demonstrate my real case:
The screenshot below displays my gem file structure
Here you can see how I am loading the gem in my Rails application Gemfile:
gem 'thumbnail_hover_effect', '0.0.3', github: 'thumbnail_hover_effec/thumbnail_hover_effec', branch: 'master'
Then I am using the gem generator a ruby file with a cutstom name in app/thumbnails/test.rb folder with the following code:
class Test < ThumbnailHoverEffect::Image::Base
...
end
and trying to use the Test class gives me uninitialized constant ThumbnailHoverEffect::Image::Base error.
Back in the gem files, these are how the thumbnail_hover_effect file looks like
require 'thumbnail_hover_effect/version'
require 'thumbnail_hover_effect/engine'
require 'thumbnail_hover_effect/image'
module ThumbnailHoverEffect
# Your code goes here...
end
and hoe the image file looks like:
module ThumbnailHoverEffect
#
class Image
...
end
end
From what you've posted here there is no ThumbnailHoverEffect::Image::Base defined. Rails autoloading conventions (which you should not be depending on a gem btw, more on that later) would be looking for this file in thumbnail_hover_effect/image/base.rb, but the directory structure you printed does not have that. Of course you could define the class in thumbnail_hover_effect/image.rb and it would work, but the abridged snippet you posted does not show that. So where is ThumbnailHoverEffect::Image::Base defined?
If it's in thumbnail_hover_effect/image/base.rb then that would indicate the file is not being loaded. You can sanity check this by putting a puts 'loading this stupid file' at the top of thumbnail_hover_effect/image/base.rb. That will allow you to bisect the problem by seeing whether there is a problem with your definition of the class, or whether the problem is with loading the proper files. Debugging is all about bisecting the problem.

sandbox testing environments exist for TDD'ing command line application

I'm writing a command line command but want to TDD it. I'll be creating and deleting files and was wondering if there's a sandbox testing gem or something like that. I'm using ruby and rspec.
Depends on what you're trying to do, but I test most of my command line Ruby by mocking out the file system and STDIN/STDOUT. Using dependency injection I often end up with something along these lines:
describe Add do
it 'writes the result to standard out' do
console = mock('STDOUT')
console.should_receive(:puts).with('5')
Add.new(console).execute(3,2)
end
end
class Add
def initialize(out = STDOUT)
#out = out
end
def execute(command_line_args)
#out.puts(command_line_args.inject(:+))
end
end
Add.new.execute(ARGS)
By using default values I can inject in the test, but leave it out of the production code.
Hope that helps!
Brandon
The template generated by the newgem install_cucumber generator uses a pattern that I like quite a bit. Have a look at the support/env.rb and support/common.rb files it creates:
https://github.com/drnic/newgem/blob/master/rubygems_generators/install_cucumber/templates/features/support/env.rb.erb
https://github.com/drnic/newgem/blob/master/rubygems_generators/install_cucumber/templates/features/support/common.rb
Use of it in test looks like this:
in_tmp_folder do
# The current directory is now a generated tmp folder.
# If you stick to relative paths, everything you do in here should be safe
end
The files linked to above are for using this in cucumber tests, but it could easily be adapter to whatever framework you're using. The env.rb above deletes the tmp folder before each test starts.
You might also want to take a look at the sandbox gem.
gem install sandbox
Example usage is here: https://github.com/bdimcheff/sandbox

Rails 3 Initialization Order

Can someone please point me in the right direction for the order in which rails modules get instantiated.
The main things I'm trying to find are:
1) When do gems get loaded?
2) When do config/initializers/* get loaded?
3) When do named routes in routes.rb get processed?
Answering your question is easy by adding some puts statements in your Rails application. (It seems like a lot of people are reluctant to dig in and do this, but I really recommend it!) So, by experimentation and observation alone, here is the order of the things you mentioned:
boot.rb
config/initializers/*
routes.rb
Here is a little more detail:
1. boot.rb
This loads the application gems by using bundler:
require 'rubygems'
# Set up gems listed in the Gemfile.
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
2. config/initializers/*
They run in alphabetical order.
If you are curious what triggers this, take a look at engine.rb in the railties source code. (It is useful to know that a Rails Application is a subclass of a Rails Engine.)
initializer :load_config_initializers do
config.paths["config/initializers"].existent.sort.each do |initializer|
load(initializer)
end
end
3. routes.rb
By observation, I see that route drawing (specification) occurs next.
But looking at the details is more involved, so if you are interested I would read SO: Controlling routes loading order from Engines and perhaps take a look at the :add_routing_paths initializer in engine.rb.
Check out this insanely detailed (and long) piece of documentation on the initialization process:
http://guides.rubyonrails.org/initialization.html
I started a console in Rails 3 and here is the order:
script/rails
config/boot.rb
config/application.rb
config/environment.rb
config/initializers/*.rb (In alphabetic order)
I really don't know but logically in this order
gems
initializers
routes
1) The only way I know how to edit gems is by editing the source file themselves. Moreover rails itself and basically everything with rails is a gem so I'm sure they are loaded first
2) Initializers are probably loaded second, or at least considering the three things you mentioned, because they might load information or modules that routes with resources and associations need.
3) Process of elimination
In terms of inner order it's probably abc
Don't take this seriously though :)

Resources