Reputation: 1766
I'm building a custom validation method for use in my rails app. The type of validator I want to build compares a column in the model where the validator is called to columns in other tables. The following is a code example that illustrates the pattern of the validator I am trying to build.
module ActiveModel
module Validations
module ClassMethods
# example: validate_a_column_with_regard_to_other_tables :column, tables: { table_one: :some_column }
def validate_a_column_with_regard_to_other_tables(*attr_names)
validates_with WithRegardToOtherTablesValidator, _merge_attributes(attr_names)
end
end
class WithRegardToOtherTablesValidator < EachValidator
def validate_each(record, attribute, value)
# compare record, attribute or value to all records that match table: :column in :tables
end
end
end
end
It is possible to test this using the models that exist in the app and schema. However, this is not a good way to test the validator because it would describe the validator as being dependent on models that it is not dependent on.
The only other way I can think of is to create a set of mock up models in the test.
class ValidateModel < BaseModel
validate_a_column_with_regard_to_other_tables :column, :tables { compare_to_model: :some_column }
end
class CompareToModel < BaseModel
attr_accessor :some_column
end
However, it is not possible to validate that :column has something to do with :some_column in :compare_to_model because :compare_to_model is not part of the schema.
How do you create a mock model that is part of your schema in tests? Or is there a better way to test a custom validator function like this?
Upvotes: 4
Views: 149
Reputation: 5479
If you're using rspec
you could set up something like this:
before(:all) do
ActiveRecord::Migration.create_table :compare_to_model do |t|
t.string :some_column
t.timestamps
end
end
it "validates like it should" do
...
end
after(:all) do
ActiveRecord::Migration.drop_table :compare_to_model
end
before(:all)
it is a "global" setup so the data would persist from one it
to the other, you might want to wrap each it
with a transaction and roll it back after or instead have a before(:each)
that will clean the table.Upvotes: 1