Module: Remarkable::ActiveRecord::Matchers
- Defined in:
- lib/remarkable/active_record/matchers/have_index_matcher.rb,
lib/remarkable/active_record/matchers/have_scope_matcher.rb,
lib/remarkable/active_record/matchers/association_matcher.rb,
lib/remarkable/active_record/matchers/have_column_matcher.rb,
lib/remarkable/active_record/matchers/have_default_scope_matcher.rb,
lib/remarkable/active_record/matchers/validate_associated_matcher.rb,
lib/remarkable/active_record/matchers/validate_uniqueness_of_matcher.rb,
lib/remarkable/active_record/matchers/allow_mass_assignment_of_matcher.rb,
lib/remarkable/active_record/matchers/have_readonly_attributes_matcher.rb,
lib/remarkable/active_record/matchers/accept_nested_attributes_for_matcher.rb
Defined Under Namespace
Classes: AcceptNestedAttributesForMatcher, AllowMassAssignmentOfMatcher, AssociationMatcher, HaveColumnMatcher, HaveDefaultScopeMatcher, HaveIndexMatcher, HaveReadonlyAttributesMatcher, HaveScopeMatcher, ValidateAssociatedMatcher, ValidateUniquenessOfMatcher
Instance Method Summary collapse
-
#accept_nested_attributes_for(*args, &block) ⇒ Object
Ensures that the model accepts nested attributes for the given associations.
-
#allow_mass_assignment_of(*attributes, &block) ⇒ Object
Ensures that the attribute can be set on mass update.
-
#belong_to(*associations, &block) ⇒ Object
Ensure that the belongs_to relationship exists.
-
#have_and_belong_to_many(*associations, &block) ⇒ Object
Ensures that the has_and_belongs_to_many relationship exists, if the join table is in place and if the foreign_key column exists.
-
#have_column(*args, &block) ⇒ Object
(also: #have_columns, #have_db_column, #have_db_columns)
Ensures that a column of the database actually exists.
-
#have_default_scope(*args, &block) ⇒ Object
Ensures that the model has a default scope with the given options.
-
#have_index(*args, &block) ⇒ Object
(also: #have_indices, #have_db_index, #have_db_indices)
Ensures the database column has specified index.
-
#have_many(*associations, &block) ⇒ Object
Ensures that the has_many relationship exists.
-
#have_one(*associations, &block) ⇒ Object
Ensures that the has_many relationship exists.
-
#have_readonly_attributes(*attributes, &block) ⇒ Object
(also: #have_readonly_attribute)
Ensures that the attribute cannot be changed once the record has been created.
-
#have_scope(*args, &block) ⇒ Object
Ensures that the model has a named scope that returns an Relation object capable of building into relational algebra.
-
#validate_associated(*args, &block) ⇒ Object
Ensures that the model is invalid if one of the associations given is invalid.
-
#validate_uniqueness_of(*attributes, &block) ⇒ Object
Ensures that the model cannot be saved if one of the attributes listed is not unique.
Instance Method Details
#accept_nested_attributes_for(*args, &block) ⇒ Object
Ensures that the model accepts nested attributes for the given associations.
Options
-
allow_destroy
- When true allows the association to be destroyed -
accept
- attributes that should be accepted by the :reject_if proc -
reject
- attributes that should be rejected by the :reject_if proc
Examples
should_accept_nested_attributes_for :tasks
should_accept_nested_attributes_for :tasks, :allow_destroy => true
:accept and :reject takes objects that are verified against the proc. So having a model:
class Projects < ActiveRecord::Base
has_many :tasks
accepts_nested_attributes_for :tasks, :reject_if => proc { |a| a[:title].blank? }
end
You can have the following specs:
should_accept_nested_attributes_for :tasks, :reject => { :title => '' } # Passes
should_accept_nested_attributes_for :tasks, :accept => { :title => 'My task' } # Passes
should_accept_nested_attributes_for :tasks, :accept => { :title => 'My task' },
:reject => { :title => '' } # Passes
should_accept_nested_attributes_for :tasks, :accept => { :title => '' } # Fail
should_accept_nested_attributes_for :tasks, :reject => { :title => 'My task' } # Fail
You can also give arrays to :accept and :reject to verify multiple attributes. In such cases the block syntax is more recommended for readability:
should_accept_nested_attributes_for :tasks do
m.allow_destroy(false)
m.accept :title => 'My task'
m.accept :title => 'Another task'
m.reject :title => nil
m.reject :title => ''
end
132 133 134 |
# File 'lib/remarkable/active_record/matchers/accept_nested_attributes_for_matcher.rb', line 132 def accept_nested_attributes_for(*args, &block) AcceptNestedAttributesForMatcher.new(*args, &block).spec(self) end |
#allow_mass_assignment_of(*attributes, &block) ⇒ Object
Ensures that the attribute can be set on mass update.
Examples
should_allow_mass_assignment_of :email, :name
it { should allow_mass_assignment_of(:email, :name) }
69 70 71 |
# File 'lib/remarkable/active_record/matchers/allow_mass_assignment_of_matcher.rb', line 69 def allow_mass_assignment_of(*attributes, &block) AllowMassAssignmentOfMatcher.new(*attributes, &block).spec(self) end |
#belong_to(*associations, &block) ⇒ Object
Ensure that the belongs_to relationship exists. Will also test that the subject table has the association_id column.
Options
-
:class_name
- the expected associted class name. -
:foreign_key
- the expected foreign key in the subject table. -
:dependent
- the expected dependent value for the association. -
:readonly
- checks wether readonly is true or false. -
:validate
- checks wether validate is true or false. -
:autosave
- checks wether autosave is true or false. -
:counter_cache
- the expected dependent value for the association. It also checks if the column actually exists in the table. -
:polymorphic
- if the association should be polymorphic or not. When true it also checks for the association_type column in the subject table.
Plus all supported sql conditions options: :select, :conditions, :order, :limit, :offset, :include, :group, :having.
Examples
should_belong_to :parent, :polymorphic => true
it { should belong_to(:parent) }
188 189 190 |
# File 'lib/remarkable/active_record/matchers/association_matcher.rb', line 188 def belong_to(*associations, &block) AssociationMatcher.new(:belongs_to, *associations, &block).spec(self) end |
#have_and_belong_to_many(*associations, &block) ⇒ Object
Ensures that the has_and_belongs_to_many relationship exists, if the join table is in place and if the foreign_key column exists.
Options
-
:class_name
- the expected associted class name. -
:join_table
- the expected join table name. -
:foreign_key
- the expected foreign key in the association table. -
:uniq
- checks wether uniq is true or false. -
:readonly
- checks wether readonly is true or false. -
:validate
- checks wether validate is true or false. -
:autosave
- checks wether autosave is true or false.
Plus all supported sql conditions options: :select, :conditions, :order, :limit, :offset, :include, :group, :having.
Examples
should_have_and_belong_to_many :posts, :cars
it{ should have_and_belong_to_many :posts, :cars }
213 214 215 |
# File 'lib/remarkable/active_record/matchers/association_matcher.rb', line 213 def have_and_belong_to_many(*associations, &block) AssociationMatcher.new(:has_and_belongs_to_many, *associations, &block).spec(self) end |
#have_column(*args, &block) ⇒ Object Also known as: have_columns, have_db_column, have_db_columns
Ensures that a column of the database actually exists.
Options
-
All options available in migrations are available:
:type, :default, :precision, :limit, :scale, :sql_type, :primary, :null
Examples
should_have_column :name, :type => :string, :default => ''
it { should have_column(:name, :type => :string) }
it { should have_column(:name).type(:string) }
59 60 61 |
# File 'lib/remarkable/active_record/matchers/have_column_matcher.rb', line 59 def have_column(*args, &block) HaveColumnMatcher.new(*args, &block).spec(self) end |
#have_default_scope(*args, &block) ⇒ Object
Ensures that the model has a default scope with the given options.
Options
All options that the default scope would pass on to find: :conditions, :include, :joins, :limit, :offset, :order, :select, :readonly, :group, :having, :from, :lock.
Examples
it { should have_default_scope(:conditions => {:visible => true}) }
it { should have_default_scope.conditions(:visible => true) }
Passes for:
default_scope :conditions => { :visible => true }
If you set two different default scopes, you have to spec them separatedly. Given the scopes:
default_scope :conditions => { :visible => true }
default_scope :conditions => { :published => true }
Then we have the matchers:
should_have_default_scope :conditions => { :visible => true } # Passes
should_have_default_scope :conditions => { :published => true } # Passes
should_have_default_scope :conditions => { :published => true,
:visible => true } # Fails
62 63 64 |
# File 'lib/remarkable/active_record/matchers/have_default_scope_matcher.rb', line 62 def have_default_scope(*args, &block) HaveDefaultScopeMatcher.new(*args, &block).spec(self) end |
#have_index(*args, &block) ⇒ Object Also known as: have_indices, have_db_index, have_db_indices
Ensures the database column has specified index.
Options
-
unique
- when supplied, tests if the index is unique or not -
table_name
- when supplied, tests if the index is defined for the given table
Examples
it { should have_index(:ssn).unique(true) }
it { should have_index([:name, :email]).unique(true) }
should_have_index :ssn, :unique => true, :limit => 9, :null => false
should_have_index :ssn do |m|
m.unique
m.limit = 9
m.null = false
end
64 65 66 |
# File 'lib/remarkable/active_record/matchers/have_index_matcher.rb', line 64 def have_index(*args, &block) HaveIndexMatcher.new(*args, &block).spec(self) end |
#have_many(*associations, &block) ⇒ Object
Ensures that the has_many relationship exists. Will also test that the associated table has the required columns. It works by default with polymorphic association (:as does not have to be supplied).
Options
-
:class_name
- the expected associted class name. -
:through
- the expected join model which to perform the query. It also checks if the through table exists. -
:source
- the source of the through association. -
:source_type
- the source type of the through association. -
:foreign_key
- the expected foreign key in the associated table. When used with :through, it will check for the foreign key in the join table. -
:dependent
- the expected dependent value for the association. -
:uniq
- checks wether uniq is true or false. -
:readonly
- checks wether readonly is true or false. -
:validate
- checks wether validate is true or false. -
:autosave
- checks wether autosave is true or false.
Plus all supported sql conditions options: :select, :conditions, :order, :limit, :offset, :include, :group, :having.
Examples
should_have_many :friends
should_have_many :enemies, :through => :friends
should_have_many :enemies, :dependent => :destroy
it{ should have_many(:friends) }
it{ should have_many(:enemies, :through => :friends) }
it{ should have_many(:enemies, :dependent => :destroy) }
249 250 251 |
# File 'lib/remarkable/active_record/matchers/association_matcher.rb', line 249 def have_many(*associations, &block) AssociationMatcher.new(:has_many, *associations, &block).spec(self) end |
#have_one(*associations, &block) ⇒ Object
Ensures that the has_many relationship exists. Will also test that the associated table has the required columns. It works by default with polymorphic association (:as does not have to be supplied).
Options
-
:class_name
- the expected associted class name. -
:through
- the expected join model which to perform the query. It also checks if the through table exists. -
:source
- the source of the through association. -
:source_type
- the source type of the through association. -
:foreign_key
- the expected foreign key in the associated table. When used with :through, it will check for the foreign key in the join table. -
:dependent
- the expected dependent value for the association. -
:validate
- checks wether validate is true or false. -
:autosave
- checks wether autosave is true or false.
Plus all supported sql conditions options: :select, :conditions, :order, :limit, :offset, :include, :group, :having.
Examples
should_have_one :universe
it{ should have_one(:universe) }
278 279 280 |
# File 'lib/remarkable/active_record/matchers/association_matcher.rb', line 278 def have_one(*associations, &block) AssociationMatcher.new(:has_one, *associations, &block).spec(self) end |
#have_readonly_attributes(*attributes, &block) ⇒ Object Also known as: have_readonly_attribute
Ensures that the attribute cannot be changed once the record has been created.
Examples
it { should have_readonly_attributes(:password, :admin_flag) }
23 24 25 |
# File 'lib/remarkable/active_record/matchers/have_readonly_attributes_matcher.rb', line 23 def have_readonly_attributes(*attributes, &block) HaveReadonlyAttributesMatcher.new(*attributes, &block).spec(self) end |
#have_scope(*args, &block) ⇒ Object
Ensures that the model has a named scope that returns an Relation object capable of building into relational algebra.
Options
-
with
- Options to be sent to the named scope
All options that the named scope would scope with Arel: :where, :having, :select, :group, :order, :limit, :offset, :joins, :includes, :lock, :readonly, :from
Matching is done by constructing the Arel objects and testing for equality.
Examples
it { should have_scope(:visible, :where => {:visible => true}) }
it { should have_scope(:visible).where(:visible => true) }
Passes for
scope :visible, where(:visible => true)
Or for
scope :visible, lambda { where(:visible => true) }
Or for
def self.visible
where(:visible => true)
end
You can test lambdas or methods that return ActiveRecord#scoped calls by fixing a defined parameter.
it { should have_scope(:recent, :with => 5) }
it { should have_scope(:recent, :with => 1) }
Passes for
scope :recent, lambda {|c| limit(c)}
Or for
def self.recent(c)
limit(c)
end
95 96 97 |
# File 'lib/remarkable/active_record/matchers/have_scope_matcher.rb', line 95 def have_scope(*args, &block) HaveScopeMatcher.new(*args, &block).spec(self) end |
#validate_associated(*args, &block) ⇒ Object
Ensures that the model is invalid if one of the associations given is invalid. It tries to build the association automatically. In has_one and belongs_to cases, it will build it like this:
@model.build_association
@project.build_manager
In has_many and has_and_belongs_to_many to cases it will build it like this:
@model.association.build
@project.tasks.build
The object returned MUST be invalid and it’s likely the case, since the associated object is empty when calling build. However, if the associated object has to be manipulated to be invalid, you will have to give :builder as option or a block to manipulate it:
should_validate_associated(:tasks) do |project|
project.tasks.build(:captcha => 'i_am_a_bot')
end
In the case above, the associated object task is only invalid when the captcha attribute is set. So we give a block to the matcher that tell exactly how to build an invalid object.
The example above can also be written as:
should_validate_associated :tasks, :builder => proc{ |p| p.tasks.build(:captcha => 'i_am_a_bot') }
Options
-
:builder
- a proc to build the association -
:message
- value the test expects to find inerrors[:attribute]
. Regexp, string or symbol. Default =I18n.translate('activerecord.errors.messages.invalid')
Examples
should_validate_associated :tasks
should_validate_associated :tasks, :builder => proc{ |p| p.tasks.build(:captcha => 'i_am_a_bot') }
should_validate_associated :tasks do |m|
m.builder { |p| p.tasks.build(:captcha => 'i_am_a_bot') }
end
it { should validate_associated(:tasks) }
it { should validate_associated(:tasks, :builder => proc{ |p| p.tasks.build(:captcha => 'i_am_a_bot') }) }
95 96 97 |
# File 'lib/remarkable/active_record/matchers/validate_associated_matcher.rb', line 95 def validate_associated(*args, &block) ValidateAssociatedMatcher.new(*args, &block).spec(self) end |
#validate_uniqueness_of(*attributes, &block) ⇒ Object
Ensures that the model cannot be saved if one of the attributes listed is not unique.
Requires an existing record in the database. If you supply :allow_nil as option, you need to have in the database a record which is not nil in the given attributes. The same is required for allow_blank option.
Notice that the record being validate should not be the same as in the database. In other words, you can’t do this:
subject { Post.create!(@valid_attributes) }
should_validate_uniqueness_of :title
But don’t worry, if you eventually do that, a helpful error message will be raised.
Options
-
:scope
- field(s) to scope the uniqueness to. -
:case_sensitive
- the matcher look for an exact match. -
:allow_nil
- when supplied, validates if it allows nil or not. -
:allow_blank
- when supplied, validates if it allows blank or not. -
:message
- value the test expects to find inerrors[:attribute]
. Regexp, string or symbol. Default =I18n.translate('activerecord.errors.messages.taken')
Examples
it { should validate_uniqueness_of(:keyword, :username) }
it { should validate_uniqueness_of(:email, :scope => :name, :case_sensitive => false) }
it { should validate_uniqueness_of(:address, :scope => [:first_name, :last_name]) }
should_validate_uniqueness_of :keyword, :username
should_validate_uniqueness_of :email, :scope => :name, :case_sensitive => false
should_validate_uniqueness_of :address, :scope => [:first_name, :last_name]
should_validate_uniqueness_of :email do |m|
m.scope = name
m.case_sensitive = false
end
228 229 230 |
# File 'lib/remarkable/active_record/matchers/validate_uniqueness_of_matcher.rb', line 228 def validate_uniqueness_of(*attributes, &block) ValidateUniquenessOfMatcher.new(*attributes, &block).spec(self) end |