I'm trying to use an initializer in Rails 4.2 to add a method to an ActiveRecord model. However, simply reopening the class in the initializer breaks the existing attribute accessors.
class Thing < ActiveRecord::Base
class CreateThings < ActiveRecord::Migration
create_table :things do |t|
t.timestamps null: false
require File.expand_path("../../test_helper", __FILE__)
class ThingTest < ActiveSupport::TestCase
test "the truth" do
thing = Thing.new
thing.test_field = 1
❯❯❯ rtest test/models/thing_test.rb
NoMethodError: undefined method `test_field=' for #<Thing:0x00000101464658>
test/models/thing_test.rb:6:in `block in <class:ThingTest>'
The key thing is that you're not reopening the class: you're defining a new one. In development and in tests your classes are loaded when they are first used. By defining
Thing in your initializer you prevent your thing.rb file from ever being loaded.
When you use
Thing.class_eval you're not defining a new class so rails loads
Thing from thing.rb: at this point your are adding to
Thing rather than replacing it.