Helps
"Can I use
after_initializeto set up nested associations for use withController#newactions?"
Not recommended. It is better to write a custom #new_for_form method in your model that pre-populates your instance variables with the 1 or more nested objects. That way you can test drive it, too.
"DelayedJob YAML parser in Ruby 1.9 is having issues."
The compiled-in psych library has issues, use the tenderlove/psych gem instead. You have to use Bundler, however. Invoking require "psych" will use the compiled-in version.
"RubyMine is not honoring a DVORAK keyboard layout properly (it is mapping keyboard shortcuts to the QWERTY layout)"
Use a hardware dongle.
"Jenkins is trying to kill off Postgres?"
Does anyone have Jenkins CI working with Postgres? It seems that after a build is complete, some java deep down inside Hudson is trying to parse the process table, and it is choking on the Postgres entries. (Postgres re-writes ARGV[0] to display status info, you can't rely on it be the original command line.) It remains a mystery why Jenkins would even need this information.
"Is anyone using Chrome in CI? The windows are transparent"
Sounds pretty. Odd, but pretty.
Interesting
"brew info ... is your friend"
Can't remember how to start or stop a daemon under OS X? If you installed it via Homebrew you are in luck:
brew info <foo>
Will print out the original install instructions, including exact lines to pass to launchctl(1), etc.
"More 'special' keywords to avoid in your models:
targetandsource"
ActiveRecord Polymorphic Associations use a method called target internally. If you have an attribute in your model / database, also called target, then strange things will happen.
"Paperclip's
<model>.attachment.exists?is slow; it goes out to S3 (or whatever the store is)"
And it happens in strange places. Be warned. Or mock out your network calls.
Interesting Things
- A certain Pivotal project runs 'bundle update' often, since they have a shared gem that gets updated a lot. They were wondering why it was so slow, and supposed it was due to slowness at rubygems.org, and thought a local mirror would help. They were wrong. Turns out the slowness is in the implementation of rubygems, whereby a 110K list of gems is marshalled and unmarshalled.
Helps
- Bundler + Heroku gotcha: Deploys to Heroku can break if you are using Bundler v1.0.6 in your local development environment (as of this writing, Heroku is using v1.0.3). Apparently the
--deploymentswitch is being stripped off andGemfile.lockis rebuilt. If the file differs from what's in the git repository, the deploy will fail with a somewhat mysterious error message. Work-around: Specify the bundler gem version to v1.0.3 (perhaps even up to v1.0.5) in yourGemfile.
Interesting Things
- nginx may write temporary files to local disk, especially for large files (>64K). You should make sure that
proxy_temp_pathis writable. You can also control the size when this happens by adjustingproxy_temp_file_write_size. The more interesting thing is that if the directory is not writable, you won't see an error message in the logs, butstraceis still your friend.
Helps
"Should I include
Gemfile.lockin a repository for a gem?"
- Yes, but don't include it in the gemspec, that way it won't be distributed with the gem.
- Bundler doesn't look at lock files in dependent gems anyway.
- It makes less sense for a gem since you wouldn't want to lock down the environment for all of your gem's users.
"What library should I use for GUIDs?"
- uuidtools
- universally unique identifiers may have trouble in other universes, please use caution when crossing these boundaries ;-)
Interesting:
bundle install --without testexcludes the test group in your Gemfile from the install. It works well for reducing the size of your Heroku slug. However, there's a glitch with this option on Heroku -- when you specify it, Heroku reinstalls every included gem every time you deploy. It does respect your Gemfile.lock, so you're trading a smaller slug for a longer deploy.Pivotal's open source CIMonitor project now supports OpenID! Thanks Tyler and Josh.
Arel has a bug that makes it difficult to use in
rails console. Every time you add a predicate, the number of internal objects in the Arel result increases exponentially. So, by the time you have 5 or 6 predicates, the console finishes generating the expression more or less instantly, and then spends 15+ minutes callingto_son the resulting Arel object in order to display it to you. tl;dr: when you're playing with Arel in rails console, end every line with; nilto avoid having it print out the result. The exponential object explosion will be fixed in Rails 3.1.
Help:
Do people put bundler in the Gemfile?
Yes. Bundler is smart enough to omit it from the cache. It does, however, still follow the rules for version. We recommend using ~> 1.0.0 as the version string, because 1.x is supposed to be backwards-compatible with the current Gemfile format.
If you instead use = 1.0.0 and your managed hosting environment updates bundler to something more recent, things will ASPLODE.
Interesting:
- Tech talk that was going to be today has moved to Thursday, due mostly to noise concerns. See you tomorrow.
Ask for Help
- How to specify compile flags when installing the mysql gem with Bundler 1.0.0RC1?
Don't. Instead use version 2.8.1 of the mysql gem and ensure mysql_config is on your PATH.
Interesting Things
- The team whose CI build was running Bundler too many times addressed this by wrapping
bundle installin a conditional usingbundle check.
This saved about three minutes of build time (from what used to be 11ish runs of bundle install instead of bundle check.)
- Websocksets are easy, use them if you need to 'push' to your webapp and your server can handle many persistent connections.
This was in reaction to some recent conversation between Pivots about Pusher, which will keep persistent connections on your behalf.
This said, here's a quote from websockets.org:
WebSockets represent an alternative to Comet and Ajax. However, each technology has its own unique capabilities. Learn how these technologies vary so you can make the right choice.
If you are using Bundler to lock and package your gem dependencies in your app (which you should), here's some tips on making everything automatic in your Capistrano deploy.
Refer to the Bundler Documentation for instructions on how to use Bundler to properly package your gems and check everything in.
Once this is done, however, you still must ensure that two things are done on every machine to which you will deploy:
- Bundler is installed
- You run 'bundle install' on every deploy to install the packaged gems on the local machine (and compile any gems with native dependencies)
Here's the Capistrano magic to accomplish these two tasks automatically on every deploy:
before "deploy:bundle_install", "deploy:install_bundler"
after "deploy:update_code", "deploy:bundle_install"
namespace :deploy do
desc "installs Bundler if it is not already installed"
task :install_bundler, :roles => :app do
sudo "sh -c 'if [ -z `which bundle` ]; then echo Installing Bundler; sudo gem install bundler; fi'"
end
desc "run 'bundle install' to install Bundler's packaged gems for the current deploy"
task :bundle_install, :roles => :app do
run "cd #{release_path} && bundle install"
end
end
Oh, and for you GemInstaller users out there - here's an easy way to generate a Bundler Gemfile from your geminstaller.yml config:
geminstaller --bundler-export > Gemfile
You'll probably still need some tweaks, but this will get you started. Just make sure you upgrade to GemInstaller 0.5.5 first (0.5.4 forgot to put the 'source' line in the Gemfile).
Happy Bundling! -- Chad
P.S. There is a similar article here, which includes tasks to symlink your .bundle dir into the Capistrano shared directory, but my deploy was pretty fast anyway, so I didn't worry about it. YMMV.
Responding to my last post, Josh pointed out what should probably be obvious: It's likely a bad idea to bundle bundler. There's a potential for version conflicts.
For our second attempt, we're
As a second attempt, we're now cribbing from the continuous integration setup from the Rails project. So far, so good:
Our RAILS_ROOT/cruise_config.rb...
require 'fileutils'
Project.configure do |project|
project.build_command = 'sudo gem update --system && ruby lib/cruise/build.rb'
end
And, the referenced lib/cruise/build.rb (the important parts)...
#!/usr/bin/env ruby
require 'fileutils'
include FileUtils
def root_dir
@root_dir ||= File.expand_path(File.dirname(__FILE__) + '/../..')
end
def rake(*tasks)
tasks.each { |task| return false unless system("#{root_dir}/bin/rake", task, 'RAILS_ENV=test')}
end
build_results = {}
cd root_dir do
build_results[:bundle] = system 'gem bundle' # bundling here, rather than in a task (not in Rails context)
build_results[:spec] = rake 'cruise:spec'
end
failures = build_results.select { |key, value| value == false }
if failures.empty?
exit(0)
else
exit(-1)
end
Thanks go to
- Josh Susser for help via email
- John Pignata for suggesting we look at the Rails project
- Rails team for the reference scripts
More comments and suggestions are encouraged.
On a current project, we've just switched from GemInstaller to Bundler for managing our application's gems.
All in all, the transition was painless... in our development environments. Of course, in order to keep things on running smoothly on the continuous integration box, we amended our rake cruise:spec task to start by running sh "gem bundle".
So, wonderful! Any changes to our gem dependency list will picked up when cruise starts and made available for that "build"; there's no need to log in and make any manual updates. Right?
Not quite. We're using the disable_system_gems option and, in that case, Bundler (very intentionally) modifies your GEM_PATH such that only "vendor'd" gems are available to the application. Which of course means that Bundler itself, being "a gem to bundle gems", is unavailable when that sh "gem bundle" command is run.
Our solution: bundle Bundler, obviously! That's right, in our Bundler Gemfile we've included gem "bundler". Now, after a single manual execution of gem bundle to pick up the bundled Gem Bundler gem bundle (heh), any subsequent Gemfile changes (to gems other than Bundler) get picked up at the start of the build... and we're cruisin'
Have another solution? Please let us know in the comments.
