Posts Tagged ‘Ruby’
July 4th, 2011
Yes its 2011 and Rails 3 has been out for a year but as far as I can tell, and many git reset --hard HEAD attempts later, haml requires the gem haml-rails to generate views. Even though Google may show results from 2010 they are still relevant. But haml --rails isn't what you want.
So Haml configuration in my Rails 3.0.9 project looks like (only relevant parts shown)...
#Gemfile
⋮
gem 'haml'
group :development do
gem 'haml-rails'
⋮
end
#./config/application.rb
⋮
module IlkContent
class Application < Rails::Application
⋮
config.generators do |g|
g.template_engine :haml
⋮
end
end
⋮
July 3rd, 2011
Suppose you're generating some sample data for your project as part of your `db:populate` rake task and part of that generation involves creating one hundred or so user records with varying bits of generated data. Then you want to associate each of these user records with other users so you execute an innocent `User.all` - its okay, this is a rake task we're only going to run in development.
Except you start getting error messages like `You have a nil object when you didn't expect it!` on `User.all.each do |user|`. Hopping into `rails c` and running `User.all` gives you a dump of the user table. Placing a `pp "User count #{User.count}"` right before the `User.all` returns 100, and looking in the logs you're even seeing the `SELECT` statement executing.
So what gives?
After a bit of debugging I was able to discern a hidden error message in all of this: "MySQL server has gone away." Oh, how kind of it to simply go away. There a number of reasons for this and in this particular case I am going to guess - and yes this is most definitely a guess - that its the packet too large problem. (And the more I think about this, the more I think that it cannot be this problem because the entire table size is 64KB. But I'm going to go with this for now.)
My brew installed MySQL server isn't running with a set `max_allowed_packet` value, so it defaults to 1MB. I'm theorizing that the returned data exceeded 1MB so the connection was dropped. This can be configured around by running `mysql max_allowed_packet=16M` or setting it in an option file but I don't like that approach. I went for chunking the result set up into smaller pieces - which is okay, this is a rake utility task after all - and it ended up looking like this:
#./lib/tasks/populate.rake
# before
User.all.each do |user|
⋮
end
#./lib/tasks/populate.rake
# after
users = []
10.times { |n| users.concat User.where("id % 10 = #{n}") }
users.each do |user|
⋮
end
The above after code works for this project; YMMV so smaller chunks may be necessary.
If someone has a better grasp on what's really going on here, please do enlighten me.
June 30th, 2011
I have a couple rake tasks and I want to write specs for them. Yes, I should extract the programming logic from the rake tasks and encapsulate that logic into appropriate class methods. However this doesn't mean that I shouldn't be able to RSpec rake tasks.
I found an older post that got me 90% of the way to what I needed. The problem is that I suspect some sort of static file name caching is going on behind the scenes in rake so using `#rake_require` in an RSpec context isn't performing the functionality I was expecting. I tried moving between `before :all do` and `before` blocks, nesting `describe` blocks and all sorts of other craziness. I had 3 different specs and the first spec would always pass and the other two would fail; I could freely re-arrange the spec order and always the spec defined first would pass. This was maddening.
Turns out I just had to use `load` instead of `#rake_require`.
Here's what my now working spec ended up looking like, for the curious:
#./spec/lib/tasks/rake_tasks_spec.rb
require 'spec_helper'
require 'rake'
describe "rake" do
before do
@rake = Rake::Application.new
Rake.application = @rake
# previously was trying
# Rake.application.rake_require "tasks/get_comic"
load Rails.root + 'lib/tasks/get_comic.rake'
Rake::Task.define_task(:environment)
end
describe "task get_comic" do
it "should have 'environment' as a prerequisite" do
@rake['get_comic'].prerequisites.should include("environment")
end
it "works when expected input is received" do
comic = Comic.new {|c| c.comic_id = 12}
comic.should_receive(:save).and_return(true)
result = Ilk::Parser::Result.new { |r| r.comic_id = 12 }
result.should_receive(:to_model).and_return(comic)
Ilk::Parser.should_receive(:parse).with(Ilk::Constants::COMIC_URL + '12').and_return(result)
Comic.should_receive(:find_by_comic_id).with(12).and_return(nil)
@rake['get_comic'].invoke('12')
end
it "raises an error when there was a problem parsing" do
Ilk::Parser.should_receive(:parse).with(Ilk::Constants::COMIC_URL + '12').and_return(nil)
-> { @rake['get_comic'].invoke('12') }.should raise_error
end
end
end
June 8th, 2011
By default when you `gem install` something you're going to get the RDoc (generated HTML documentation based on the source code) and ri (index for viewing the documentation offline) that comes along with it. You could:
#console
$ gem install terminitor --no-rdoc --no-ri
... if you aren't worried about the documentation. The problem is, of course, remembering to add those command line arguments every time. Fortunately there is an easy solution - like all good Unix utilities `gem` will read `/etc/gemrc` or `~/.gemrc` for default configuration options. The RC files are in YAML format; to globally disable rdoc and ri generation during gem installation for just yourself:
#~/.gemrc
gem: --no-rdoc --no-ri
To understand exactly what you are turning off read: Ruby ri Tool. Honestly since I've just now bothered to read how to use `ri` I will probably leave it on for my workstations and just turn it off for my servers.
For other things you can do in your `.gemrc` file read the documentation.
June 8th, 2011
I assume this patch is going to end up in 1.9.3 but in the mean time: How To Get That Edge Ruby Faster-Loading-Hotness in Ruby 1.9.2 Now
Very easy to do, even for someone fairly new to Ruby, like me. You'll end up having to change your `.rvmrc` file to `rvm use ruby-1.9.2-p180-patched` and do the necessary steps to populate the new gemset (`gem install bundler ; bundle install`).
My guard/rspec/spork/growl went from a 1-2 second delay to pretty much instantaneous when saving a spec or associated controller/model/helper. `bundle exec rake cucumber` also doesn't feel nearly as sluggish.