近&況

Recent Posts
Edit

A collision between Yard and FactoryGirl

2016-12-27
Tech

Today I encountered a curious error on running tests of a Rails app.

(snip)/gems/yard-0.8.7.6/lib/yard/globals.rb:16:in `log': wrong number of arguments (given 1, expected 0) (ArgumentError)

Solution

I did not indend to use yard while testing. By checking Gemfile.lock, I found pry-doc was the only gem depends on yard. The error was removed by fixing Gemfile to exclude pry-doc from the "test" group.

gem "pry-doc", group: "development"

But why?

FactoryGirl uses method_missing to collect model attributes. In the following example, name and log should result in an invocation of method_missing.

FactoryGirl.define do
  factory :server, class: Server do
    name "server1"
    log "working fine."
  end
end

However, when Yard is loaded, log is treated as an invocation of Kernel#log defined in lib/yard/globals.rb. This is how the ArgumentError is raised.

Points

  1. It is good to check that your Gemfile does not load unnecessary library.
  2. You should be careful when defining a method on the toplevel -- it may result in an unexpected behavior.
  3. method_missing makes your DSL compact but a little fragile. This conflict did not happen if FactoryGirl used a particular method (say, attr) to declare model attributes (and personally I prefer this style because it is clear that which identifier is code and which is data).
FactoryGirl.define do
  factory :server, class: Server do
    attr :name, "server1"
    attr :log, "working fine."
  end
end