maikovich
maikovich

Reputation: 378

Ruby on Rails plugin - Adding validation in class doesn't work properly

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

Answers (1)

Dan Draper
Dan Draper

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

Related Questions