Skip to content

Commit

Permalink
Add with_prefix and with_suffix to define_enum_for
Browse files Browse the repository at this point in the history
In Rails 5, the `enum` macro received two new options: `_prefix` and
`_suffix`. These options change the names of the methods that are
generated from the given enum values. This commit adds qualifiers to the
`define_enum_for` matcher so that they can be tested.
  • Loading branch information
mcmire committed Jan 26, 2018
1 parent 4ddd89e commit d7c36c5
Show file tree
Hide file tree
Showing 3 changed files with 465 additions and 6 deletions.
118 changes: 117 additions & 1 deletion lib/shoulda/matchers/active_record/define_enum_for_matcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,55 @@ module ActiveRecord
# backed_by_column_of_type(:string)
# end
#
## ##### with_prefix
#
# Use `with_prefix` to test that the enum is defined with a `_prefix`
# option (Rails 5 only). Can take either a boolean or a symbol:
#
# class Issue < ActiveRecord::Base
# enum status: [:open, :closed], _prefix: :old
# end
#
# # RSpec
# RSpec.describe Issue, type: :model do
# it do
# should define_enum_for(:status).
# with_values([:open, :closed]).
# with_prefix(:old)
# end
# end
#
# # Minitest (Shoulda)
# class ProcessTest < ActiveSupport::TestCase
# should define_enum_for(:status).
# with_values([:open, :closed]).
# with_prefix(:old)
# end
#
# ##### with_suffix
#
# Use `with_suffix` to test that the enum is defined with a `_suffix`
# option (Rails 5 only). Can take either a boolean or a symbol:
#
# class Issue < ActiveRecord::Base
# enum status: [:open, :closed], _suffix: true
# end
#
# # RSpec
# RSpec.describe Issue, type: :model do
# it do
# should define_enum_for(:status).
# with_values([:open, :closed]).
# with_suffix
# end
# end
#
# # Minitest (Shoulda)
# class ProcessTest < ActiveSupport::TestCase
# should define_enum_for(:status).
# with_values([:open, :closed]).
# with_suffix
# end
#
# @return [DefineEnumForMatcher]
#
Expand All @@ -98,6 +147,23 @@ def description
description = "define :#{attribute_name} as an enum, backed by "
description << Shoulda::Matchers::Util.a_or_an(expected_column_type)

if options[:expected_prefix]
description << ', using a prefix of '
description << "#{options[:expected_prefix].inspect}"
end

if options[:expected_suffix]
if options[:expected_prefix]
description << ' and'
else
description << ', using'
end

description << ' a suffix of '

description << "#{options[:expected_suffix].inspect}"
end

if presented_expected_enum_values.any?
description << ', with possible values '
description << Shoulda::Matchers::Util.inspect_value(
Expand All @@ -121,14 +187,28 @@ def with(expected_enum_values)
with_values(expected_enum_values)
end

def with_prefix(expected_prefix = attribute_name)
options[:expected_prefix] = expected_prefix
self
end

def with_suffix(expected_suffix = attribute_name)
options[:expected_suffix] = expected_suffix
self
end

def backed_by_column_of_type(expected_column_type)
options[:expected_column_type] = expected_column_type
self
end

def matches?(subject)
@record = subject
enum_defined? && enum_values_match? && column_type_matches?

enum_defined? &&
enum_values_match? &&
column_type_matches? &&
enum_value_methods_exist?
end

def failure_message
Expand Down Expand Up @@ -168,6 +248,10 @@ def normalized_expected_enum_values
to_hash(expected_enum_values)
end

def expected_enum_value_names
to_array(expected_enum_values)
end

def expected_enum_values
options[:expected_enum_values]
end
Expand Down Expand Up @@ -238,6 +322,38 @@ def model
record.class
end

def enum_value_methods_exist?
passed = expected_singleton_methods.all? do |method|
model.singleton_methods.include?(method)
end

if passed
true
else
@failure_reason =
if options[:expected_prefix]
if options[:expected_suffix]
'it was defined with either a different prefix, a ' +
'different suffix, or neither one at all'
else
'it was defined with either a different prefix or none at all'
end
elsif options[:expected_suffix]
'it was defined with either a different suffix or none at all'
end
false
end
end

def expected_singleton_methods
expected_enum_value_names.map do |name|
[options[:expected_prefix], name, options[:expected_suffix]].
select(&:present?).
join('_').
to_sym
end
end

def to_hash(value)
if value.is_a?(Array)
value.each_with_index.inject({}) do |hash, (item, index)|
Expand Down
4 changes: 4 additions & 0 deletions spec/support/unit/helpers/active_record_versions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ def active_record_version
Tests::Version.new(::ActiveRecord::VERSION::STRING)
end

def active_record_enum_supports_prefix_and_suffix?
active_record_version >= 5
end

def active_record_supports_has_secure_password?
active_record_version >= 3.1
end
Expand Down
Loading

0 comments on commit d7c36c5

Please sign in to comment.