Reputation: 378
I made a small DRY plugin that I want to use in some of my classes (like theatre, coffeeshop, restaurant, etc) later on. All those classes consist of an address and therefore, I made an Address model plugin with an act_as_address method that are to be called by those classes to avoid writing duplicate code.
The classes will consist of some validations on the address fields (like presence and length) and I used class_eval inside the act_as_address in the Address model to write those validations to the classes. However, it does not seem to work.
Here is my code and tests:
# structure.sql
create table addresses (
some_info varchar(25)
# other attrs
);
create table theatres (
id integer,
primary key (id)
) inherits (addresses);
# act_as_address.rb
module Address
module ActsAsAddress
extend ActiveSupport::Concern
include do
end
module ClassMethods
def acts_as_address
class_eval do <<-EVAL
validates :some_info, presence: true
# some other validations, methods etc.
EVAL
end
end
end
end
end
ActiveRecord::Base.send :include, Address::ActsAsAddress
# theatre.rb
class Theatre < ActiveRecord::Base
acts_as_address
end
# address.rb
require 'address/acts_as_address'
module Address
end
# acts_as_address_test.rb
require File.expand_path('../test_helper', __FILE__)
class ActsAsAddressTest < ActiveSupport::TestCase
test "should not be valid" do
assert_not Theatre.create(:some_info => nil).valid?,
"some_info was valid with nil value"
end
end
And the result of the test is as following:
1) Failure:
ActsAsAddressTest#test_should_not_be_valid [acts_as_address_test.rb:16]:
some_info was valid with nil value
Could anyone help me out here? Is class_eval the problem here? I am using Ruby on Rails 4.
Upvotes: 1
Views: 159
Reputation: 1121
You may be able to do this:
module Address
module ActsAsAddress
extend ActiveSupport::Concern
module ClassMethods
def acts_as_address
validates :some_info, presence: true
end
end
end
end
Upvotes: 2