Module: Remarkable::DSL::Optionals
- Defined in:
- lib/remarkable/dsl/optionals.rb
Overview
This module is responsable for create optional handlers and providing macro configration blocks. Consider the matcher below:
class AllowValuesForMatcher < Remarkable::ActiveRecord::Base
arguments :collection => :attributes, :as => :attribute
optional :message
optional :in, :splat => true
optional :allow_nil, :allow_blank, :default => true
end
This allow the matcher to be called as:
it { should allow_values_for(:email).in("[email protected]", "[email protected]").(:invalid).allow_nil }
It also allow macros to be configured with blocks:
should_allow_values_for :email do |m|
m. :invalid
m.allow_nil
m.in "[email protected]"
m.in "[email protected]"
end
Which could be also writen as:
should_allow_values_for :email do |m|
m. = :invalid
m.allow_nil = true
m.in = [ "[email protected]", "[email protected]" ]
end
The difference between the them are: 1) optional= always require an argument even if :default is given. 2) optional= always overwrite all previous values even if :splat is given.
Blocks can be also given when :block => true is set:
should_set_session :user_id do |m|
m.to { @user.id }
end
I18n
Optionals will be included in description messages if you assign them properly on your locale file. If you have a validate_uniqueness_of matcher with the following on your locale file:
description: validate uniqueness of {{attributes}}
optionals:
scope:
positive: scoped to {{inspect}}
case_sensitive:
positive: case sensitive
negative: case insensitive
When invoked like below will generate the following messages:
validate_uniqueness_of :project_id, :scope => :company_id
#=> "validate uniqueness of project_id scoped to :company_id"
validate_uniqueness_of :project_id, :scope => :company_id, :case_sensitive => true
#=> "validate uniqueness of project_id scoped to :company_id and case sensitive"
validate_uniqueness_of :project_id, :scope => :company_id, :case_sensitive => false
#=> "validate uniqueness of project_id scoped to :company_id and case insensitive"
Interpolation options
The default interpolation options available are “inspect” and “value”. Whenever you use :splat => true, it also adds a new interpolation option called {sentence}.
Given the following matcher call:
validate_uniqueness_of :id, :scope => [ :company_id, :project_id ]
The following yml setting and outputs are:
scope:
positive: scoped to {{inspect}}
# Outputs: "validate uniqueness of project_id scoped to [ :company_id, :project_id ]"
positive: scoped to {{value}}
# Outputs: "validate uniqueness of project_id scoped to company_idproject_id"
positive: scoped to {{value}}
# Outputs: "validate uniqueness of project_id scoped to company_id and project_id"
Interpolation keys
Three keys are available to be used in I18n files and control how optionals are appended to your description:
* <tt>positive</tt> - When the optional is given and it evaluates to true (everything but false and nil).
* <tt>negative</tt> - When the optional is given and it evaluates to false (false or nil).
* <tt>not_given</tt> - When the optional is not given.
Defined Under Namespace
Modules: ClassMethods
Constant Summary collapse
- OPTIONAL_KEYS =
[ :positive, :negative, :not_given ]
Class Method Summary collapse
-
.included(base) ⇒ Object
:nodoc:.
Instance Method Summary collapse
-
#description(options = {}) ⇒ Object
Overwrites description to support optionals.
-
#translate_optionals_with_namespace(optional, key, options = {}) ⇒ Object
:nodoc:.
Class Method Details
.included(base) ⇒ Object
:nodoc:
104 105 106 |
# File 'lib/remarkable/dsl/optionals.rb', line 104 def self.included(base) #:nodoc: base.extend ClassMethods end |
Instance Method Details
#description(options = {}) ⇒ Object
Overwrites description to support optionals. Check optional
for more information.
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 |
# File 'lib/remarkable/dsl/optionals.rb', line 196 def description(={}) #:nodoc: = super() .strip! optionals = self.class.matcher_optionals.map do |optional| if @options.key?(optional) value = @options[optional] defaults = [ (value ? :positive : :negative) ] # If optional is a symbol and it's not any to any of the reserved symbols, search for it also defaults.unshift(value) if value.is_a?(Symbol) && !OPTIONAL_KEYS.include?(value) defaults << '' = { :default => defaults, :inspect => value.inspect, :value => value.to_s } if self.class.matcher_optionals_splat.include?(optional) value = [ value ] unless Array === value [:sentence] = array_to_sentence(value, true) end translate_optionals_with_namespace(optional, defaults.shift, ) else translate_optionals_with_namespace(optional, :not_given, :default => '') end end.compact << ' ' << array_to_sentence(optionals) .strip! end |
#translate_optionals_with_namespace(optional, key, options = {}) ⇒ Object
:nodoc:
227 228 229 230 231 232 233 234 235 236 237 238 239 |
# File 'lib/remarkable/dsl/optionals.rb', line 227 def translate_optionals_with_namespace(optional, key, ={}) #:nodoc: scope = "#{matcher_i18n_scope}.optionals.#{optional}" translation = Remarkable.t key, .merge!(:scope => scope) return translation unless translation.empty? parent_scope = scope.split('.') parent_scope.delete_at(-3) translation = Remarkable.t key, .merge!(:scope => parent_scope) return translation unless translation.empty? nil end |