bundle exec rails … executes Bundler.setup 3 times Permalink for this post
I'm adding some new features to Forkchop using Ember, ember-rails, and the associated active_model_serializers. The only hiccup is that I'm using Mongoid, and Active Model Serializers only hooks into Active Record when it loads. This means that Rails doesn't automatically look for the appropriate serializer when using render json: @object.
To remedy this, I added the following lines from this Gist to config/initializers/mongoid_active_model_initializers:
Mongoid::Document.send(:include, ActiveModel::SerializerSupport)
Mongoid::Criteria.delegate(:active_model_serializer, to: :to_a)I usually bundle all of a Rails project's JavaScript together. Occasionally, only a few pages need a large JavaScript library, and I don't want it to have to be downloaded on every page of the application. In these situations, I don't require the large library file or it's dependencies in application.js so it won't be bundled with the rest of the project's scripts. I'll add a script tag for the library to just the pages that need it, which works locally in development mode. And then inevitably I deploy and the additional files can't be found on the server because they haven't been precompiled.
It is in the docs, but I always seem to forget that for Sprockets to precompile anything other than application.js, the additional files must be specifed in config/application.rb:
config.assets.precompile += ['another_file.js']That's all there is to it.
TL;DR: don’t run
bundle execbeforerailscommand, rails already checks the presence of Bundler through the Gemfile and sets up everything according to it without the overhead ofbundle exec.railscommand is the only exception to the rule.
script/rails is the way to go.
A nice post by John Nunemaker on designing the public APIs for Gauges. I like his approach to serializing data using serialization objects.
It's surprising how many useful tips I find posted as Gists.
Includes how to fix the asset pipeline when upgrading from Rails 3.1.0rc4 to 3.1.0rc5, both locally and on Heroku.
On most webpages there are a number of what I call 'page attributes'. These are little bits of data that have to be set based on the context of the app: the page title, a body class, etc.
It's easy enough to just use content_for to handle this scenario:
# in a view template
content_for(:title, 'Epic Page Title')
# in the page layout
yield :titleBut I've found I often want to define these things at a higher level, perhaps at the controller level, either using a class method or inside an action body like this:
class UnicornsController
page_attr :body_class, 'unicorns'
def party
# such a special action deserves a special class
page_attr :body_class, 'unicorn-party'
end
endOr even in a view:
<%- page_attr :body_class, 'out-of-control-unicorn-shindig' -%>This is a contrived example, but the idea is page attributes are inherited the way one would expect (controller class -> controller action -> template), while potentially being overridden at the lower levels. Here's the code:
# in app/controllers/application_controller.rb
include PageAttributes
# in config/initilizers/requires.rb
require 'page_attributes'
# in lib/page_attributes.rb
module PageAttributes
def self.included(base)
base.helper_method :page_attr
base.class_attribute :page_attributes
base.page_attributes = {}
base.class_eval do
def self.page_attr(key, value)
self.page_attributes[key] = value
end
end
end
protected
def page_attr(key, value=nil)
@page_attributes ||= {}
if value.nil?
@page_attributes[key] || self.class.page_attributes[key]
else
@page_attributes[key] = value
end
end
endI've been looking at ways to get the test suite for a project I'm working on running faster, and I came across slides from a presentation that present several ways to speed up tests. In particular, there are some environment variables that you can use to control the behavior of REE's garbage collector. I've found that using the values suggested in the slides decreases my test run times by 20-30%:
export RUBY_HEAP_MIN_SLOTS=1000000
export RUBY_HEAP_SLOTS_INCREMENT=1000000
export RUBY_HEAP_SLOTS_GROWTH_FACTOR=1
export RUBY_HEAP_FREE_MIN=500000
export RUBY_GC_MALLOC_LIMIT=1000000000I saved this script to my path, and when I want run Ruby with these settings, I prepend the command I'm running with 'rmem'. Or, as suggested by the slides, you can add the settings to your profile. Be careful, as they cause Ruby processes to use significantly more memory.
Thanks to Andriy Tyurnikov and Tobias Schmidt for recently adding support for the Ukraine and Germany, respectively. And to the others that have fixed bugs or brought issues to my attention.
Carmen is a collection of country and state names and abbreviations, along with replacements for the state_select and country_select plugins that leverage this data.
I have been integrating a lot of well built HTML templates into Rails applications this week. I've found Haml to be the best templating language, and I like to convert preexisting templates to use it as I add them to a project.
The Haml gem installs a command line executable that performs this conversion, html2haml. The program takes whatever is passed as standard input, performs the conversion, and writes the result to standard out. For a while I was using command this in combination with the pbcopy/pbpaste commands (I work on a Mac) to apply this to the content of the clipboard:
pbpaste | html2haml | pbcopyThis worked, but the extra copying and pasting was annoying. So I made a TextMate command to eliminate the tedium:

The actual command is this (it's a bit hard to see above):
echo $TM_SELECTED_TEXT | html2hamlYou could add a key binding as well, but so far I haven't bothered to.
In the optimization phase of a project, one of the first things I do is look for pages that could benefit from the use of ActiveRecord's eager loading. Since named_scopes were introduced in Rails 2.1, most of my model loading has involved a chain of scopes, and it is always frustrating to have to change
@blogs = Blog.published.activeto
@blogs = Blog.published.active.scoped(:include => [:slugs, :topic => :slugs])It's a small difference, but one I've never really liked. It seems like an obvious choice would be to add a named_scope to all subclasses of ActiveRecord::Base and have that handle the :include parameter. I finally wrote the 11 lines of code required to do this today:
module ActiveRecord
module EagerLoadScope
def self.included(base)
base.named_scope :eager_load, lambda { |*inclusion|
{:include => inclusion}
}
end
end
end
ActiveRecord::Base.class_eval { include ActiveRecord::EagerLoadScope }And now that line looks like this:
@blogs = Blog.published.active.eager_load(:slugs, :topic => :slugs)Again, it's a small improvement, but one I consider worthwhile.
Most of my recent projects have involved working with a front end developer, who would provide HTML/CSS templates with dummy content to be integrated into a Rails backend. During the process of wiring up the views, I often wish to hide a section of a template or partial until the models and controllers are setup to support them.
I've started using this little view helper to hide code in a view, while providing a console message to remind me to go back and address the issue when the time is right:
def hide(&block)
if Rails.env == 'development'
match, file, line = caller.first.match(/([^:]+):(\d+).+/).to_a
Rails.logger.info "** Hiding content on line #{line} of #{file}"
end
endIt's simple to use, especially in HAML:
- hide do
= some_view_code_that_will_not_executeThe helper will print something like this to your console:
** Hiding content on line 14 of /Users/jimb/Projects/demo/app/views/objects/show.html.hamlPassenger 2.2.3 came out this week, and while up until now I was using the Ubuntu packages from Brightbox (great blokes, really), I was having some problems with serving caches files and I didn't want to wait for the package to be updated. The package itself can be found on Github if you'd like to see it in more detail.
I used a combination of two guides to get everything working: one at Slicehost's wiki and another blog post by someone whose name may or may not be Johnny Pez.
It can be a little confusing to jump back and forth between the two, so I've posted a compiled set of steps here. After working through this article, you can continue on with the second Slicehost article for setting up the rest of your environment.
I'm going to assume you have Ruby and RubyGems installed. If not, do that first before continuing.
Install the Passenger gem:
sudo gem install passengerThen you need to build the nginx extension, which will be needed when we compile it.
cd `passenger-config --root`
sudo rake nginxYou'll need to install nginx's prerequisites:
sudo apt-get install libpcre3 libpcre3-dev libpcrecpp0 libssl-devThen, download the nginx source and unpack it. Everyone seems to be using the legacy stable version of nginx, and I haven't tried any of the newer ones yet.
wget http://sysoev.ru/nginx/nginx-0.6.37.tar.gz
tar xzvf nginx-0.6.37.tar.gzNow we need to configure nginx.
cd nginx-0.6.37
./configure --sbin-path=/usr/local/sbin --with-http_ssl_module \
--add-module=`passenger-config --root`/ext/nginxYou can change the configure flags if you want (see the comments on the Slicehost article), but I've left them alone so the rest of Slicehost's articles can be followed without modification.
Assuming the configure succeeded, all that's left is to compile and install.
make
sudo make installTo make sure everything is working, start nginx:
sudo /usr/local/sbin/nginxVisit your server's IP, and you should see the nginx welcome screen. This is good! Kill nginx:
sudo kill `cat /usr/local/nginx/logs/nginx.pid`Now continue on with the Slicehost series to complete your nginx configuration. You'll also probably want to mirror the default configuration layout (these articles specify Intrepid, but the steps will be pretty close on most recent versions of Ubuntu).
This is a little hack I came up with today when I got tired of duplicating logic in scopes and accessor methods. If I define a method in a model like this:
class Submarine < ActiveRecord::Base
named_scope :on_surface, :conditions => {:location => 'surface'}
named_scope :submerged, :conditions => {:location => 'under water'}
endI think I should be able to interrogate the model to see if it is in these scopes without needing to define Submarine#on_surface? or Submarine#submerged? This is what I want to be able to do:
sub = Submarine.first => #<Submarine id: 1, location: 'surface'>
sub.on_surface? => true
sub.submerged? => falseInterrogation will allow for exactly this. The first version would fire a database query on each call, but I've since added in an attempt at parsing simple conditions against a model's attributes, with a fallback to the database for complicated conditions.
The largest problem with this approach is an object's state is not always in sync with the database. I've thought about this a lot, and at this point I think it's best to raise an exception when using these methods on dirty objects. I think handling dirty objects is beyond the scope of this little hack.
In Rails 2.3 you can cause your plugins to be reloaded with each request by adding this to your development.rb file:
config.reload_plugins = trueThis was possible before, but it required altering Dependencies.load_once_paths and other black magic. I've always had issues with these approaches, and so it's nice to see official support for such a useful feature.
On a recent project I became tired of state select and country select, the ubiquitous Rails plugins for providing a list of state or country names in views. I didn't like that their data was defined in code. Or that their data was defined in the view, so validating a model field against them was messy.
I started to refactor country select by moving the list of countries into a Geography module. But then I needed a list of states, and their abbreviations, and it struck me as odd that I needed two plugins that worked differently in order to provide what seemed to be some very basic functionality to my app.
Carmen is the result of my frustration: a small unified library that handles country and state names and abbreviations. It stores its data lists in YAML, so it's easy to edit and add new state lists.
Carmen's primary use is providing a list of countries (or states within country), and, optionally, their abbreviations.
Carmen::states('US') => [['Alabama', 'AL'], ['Arkansas', 'AR'], ... ]
Carmen::state_names('US') => ['Alabama', 'Arkansas', ... ]
Carmen::state_codes('US') => ['AL', 'AR', ... ]Similar methods are available for countries. It also has some convenience methods to assist in converting between names and abbreviations:
Carmen::country_name('US') => 'United States'
Carmen::country_code('Canada') => 'CA'
Carmen::state_code('Manitoba', 'CA') => 'MB'
Carmen::state_name('AZ', 'US') => 'Arizona'Any of the state methods that require a country code will use a default country code if none is supplied. This defaults to 'US', but can be easily changed for those outside the US:
Carmen.default_country = 'CA'And of course, it's simple to use Carmen in your model validations:
class Address < ActiveRecord::Base
validates_inclusion_of :country, :in => Carmen::country_codes
endCarmen also supplies view helpers that work the same as those in country select or state select, so it should be a drop in replacement in most cases. I've posted the docs, and the code is on Github.
If you do what I do and keep your Rails plugins in separate git repos using git submodules, you will encounter a git error if you've made changes to the local repositories for a plugin and try to deploy without pushing the changes up to the server:
fatal: reference is not a tree: 17f1db7f33c986f0d4a9dc0c5846322095cda96bTo resolve this, cd into the relevant directory (vendor/plugins/whatever/) and push to the repo. It seems obvious, but I've made this mistake once or twice.
A not-so-well known feature of ActiveSupport is its ability to handle blocks as definitions for custom date and time formats. Here's one I just added to a project to give nice short dates, stripping out any leading zeros:
ActiveSupport::CoreExtensions::Date::Conversions::DATE_FORMATS.merge!(
:shorty => lambda {|date| date.strftime("%m/%d/%y").gsub(/0?(\d+)\/0?(\d+)\/(\d+)/, '\1/\2/\3')}
)You can drop that in your environment.rb; a better option is to place it in a file inside config/initializers.
It seems like every project I've worked on recently involves some kind of markup processing. Here's what I've been using to test my markup processing:
module Spec
module Matchers
module Markup
class MatchMarkup
def initialize(expected)
@expected = expected
end
def matches?(target)
@target = target
standardize(@target).eql?(standardize(@expected))
end
def failure_message
"expected\n#{@target}\nto match\n#{@expected}"
end
def negative_failure_message
"expected\n#{@target}\nto not match\n#{@expected}"
end
# alphabetize the order of attributes
def standardize(markup)
clean_whitespace(markup).gsub(/( [a-zA-Z_]*="[^"])+"/) do |match|
' ' + match.strip!.split(' ').sort.join(' ')
end
end
def clean_whitespace(markup)
markup.
gsub(/\s+/, ' '). # cleanup whitespace
gsub(/>\s/, '>'). # kill space after tags
gsub(/\s</, '<'). # space before tags
gsub(/\s\/>/, '/>'). # space inside self-closing tags
strip
end
end
def match_markup(markup)
MatchMarkup.new(markup)
end
end
end
endThis matcher does two things that are helpful. It standardizes the order of attributes, which is crucial since most of the time HTML attributes are specified in Ruby using a hash and therefore their eventual order can't be guaranteed. It also removes all whitespace, so your specs can be easier on you.
Here's a totally contrived example:
it "should wrap with a div" do
input = <<-HTML
<p>
In order to attain the greatest possible clearness,
let us return to our example of the railway carriage supposed
to be travelling uniformly.
</p>
HTML
output = <<-HTML
<div class="klass" id="div_3">
<p>
In order to attain the greatest possible clearness,
let us return to our example of the railway carriage supposed
to be travelling uniformly.
</p>
</div>
HTML
wrap_with_div(input, :class => 'klass', :id => 'div_3').should match_markup(output)
end
So far I've seen Yehuda Katz's and Aaron Patterson's, both of which I would recommend.
Also note that audio-only downloads are offered, which I find convenient as a frequent podcast listener.