How to resolve Rails model namespace collision

2020-02-08 18:39发布

The story so far:

I have a rails app with a model named "Term". All is well until trying to install Cucumber. Upon running

rake cucumber

I get

Term is not a class (TypeError)

This happens because Cucumber includes another gem, 'term-ansicolor' (to do the nifty colored text output in the console), and term-ansicolor defines a module named "Term". Cucumber includes term-ansicolor before including the Rails models, thus "Term" is already defined as a module when loading the "Term" model. Top-level modules and classes cannot have the same names in Ruby, thus the collision.

Preferring not to rename the model, I set about patching the term-ansicolor gem. This proved harder than I thought. I changed the Term module name to "ANSITerm", but I can't figure out how to get Cucumber to load my modified gem, which I've put into RAILS_ROOT/vendor/gems/term-ansicolor.

Any ideas? Am I barking up the wrong tree?

3条回答
我命由我不由天
2楼-- · 2020-02-08 19:12

Here's what I did:

sudo gem uninstall term-ansicolor
sudo gem uninstall cucumber

Download sources for term-ansicolor and cucumber from github
Search term-ansicolor source for "module Term" and replace with "module ANSITerm"
Search cucumber source for "include Term" and replace with "include ANSITerm"
Search cucumber source for "::Term" and replace with "::ANSITerm"

sudo gem install term-ansicolor from my local repository
sudo gem install cucumber from my local repository

Now I have two gems to maintain, but that seems easier than changing all the model references in my app.

Comments/suggestions welcome.

查看更多
够拽才男人
3楼-- · 2020-02-08 19:24

I did get a namespace collision with my application model Node and Capybara::Node in my specs. It was sufficient for me to explicitly state toplevel namespace in specs to fix the problem:

it "should find the specified node scoped under the current user" do
  ::Node.should have_received(:find_by_id_for_user).with(node.id, user)
end
查看更多
Melony?
4楼-- · 2020-02-08 19:34

Two solutions:

1) Change your app's Term model to be something else.

2) Patch term-ansicolor to have a namespaced Term and use that gem instead.

查看更多
登录 后发表回答