Class: Ratatouille::Ratifier

Inherits:
Object
  • Object
show all
Defined in:
lib/ratatouille/ratifier.rb

Overview

Ratifier acts as a clean room in which to perform validations.

Instance Attribute Summary (collapse)

Instance Method Summary (collapse)

Constructor Details

- (Ratifier) initialize(obj, options = {}, &block)

A new instance of Ratifier

Parameters:

  • obj (Hash, Array)

    Object to validate

  • options (Hash) (defaults to: {})


11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/ratatouille/ratifier.rb', line 11

def initialize(obj, options={}, &block)
  @errors = { "/" => [] }
  @ratifiable_object = obj
  self.name = options[:name]

  parse_options(options)

  case obj
  when Hash  then extend Ratatouille::HashMethods
  when Array then extend Ratatouille::ArrayMethods
  end

  unless @is_a.nil?
    is_a?(@is_a, &block)
  else
    instance_eval( &block ) if block_given?
  end

  cleanup_errors

  @errors.freeze
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

- (Object) method_missing(id, *args, &block)

Override Method Missing for a Ratifier to generate errors for invalid methods called on incorrect objects (hash validation on arrays, etc.) as well as some catch-all methods for boolean validations (is_* and is_not_*)



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
226
227
228
229
230
# File 'lib/ratatouille/ratifier.rb', line 196

def method_missing(id, *args, &block)
  parse_options(args.first)

  unless @skip == true
    case
    when @unwrap_block == true
      # Perform no validation logic
      # Skip to block evaluation
    when id.to_s =~ /^is_not_(.*)$/
      if @ratifiable_object.respond_to?("#{$1}?")
        if @ratifiable_object.send("#{$1}?") == true
          validation_error("#{name} is #{$1}")
          return
        end
      end
    when id.to_s =~ /^is_(.*)$/
      if @ratifiable_object.respond_to?("#{$1}?")
        if @ratifiable_object.send("#{$1}?") == false
          validation_error("#{name} is not #{$1}")
          return
        end
      end
    else
      begin
        super
        return
      rescue Exception => e
        validation_error("#{id} is not supported for the given object (#{@ratifiable_object.class})")
        return e
      end
    end

    instance_eval(&block) if block_given?
  end#skip
end

Instance Attribute Details

- (Object) errors (readonly)

Returns the value of attribute errors



5
6
7
# File 'lib/ratatouille/ratifier.rb', line 5

def errors
  @errors
end

- (Object) ratifiable_object (readonly) Also known as: ro

Returns the value of attribute ratifiable_object



6
7
8
# File 'lib/ratatouille/ratifier.rb', line 6

def ratifiable_object
  @ratifiable_object
end

Instance Method Details

- (void) cleanup_errors

This method returns an undefined value.

If there are no errors in the errors hash, empty it out.



86
87
88
89
90
# File 'lib/ratatouille/ratifier.rb', line 86

def cleanup_errors 
  @errors = {} if errors_array.empty?
rescue Exception => e
  validation_error("#{e.message}", '/')
end

- (Array) errors_array(item = @errors)

Parameters:

  • item (Hash) (defaults to: @errors)

    Hash to act upon.

Returns:

  • (Array)


95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/ratatouille/ratifier.rb', line 95

def errors_array(item = @errors)
  all_errs = []

  case item
  when Array
    item.each_with_index do |e,i|
      item_errs = case e
      when Hash, Array then errors_array(e)
      when String then e
      else []
      end

      all_errs << namespace_error_array(item_errs, "#{i}")
      all_errs.flatten!
    end
  when Hash
    item.each_pair do |k,v|
      pair_errs = case v
      when Hash, Array then errors_array(v)
      when String then v
      else []
      end

      all_errs << namespace_error_array(pair_errs, k)
      all_errs.flatten!
    end
  end

  return Array(all_errs)
end

- (void) is_a?(klass = nil, &block)

This method returns an undefined value.

Method to check if ratifiable_object matches given class. Will not validate without class.

Parameters:

  • klass (Class) (defaults to: nil)


132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/ratatouille/ratifier.rb', line 132

def is_a?(klass=nil, &block)
  if klass.nil?
    validation_error("must provide a Class for is_a?")
    return
  end

  unless klass === @ratifiable_object
    validation_error("object not of type #{klass}")
    return
  end

  instance_eval(&block) if block_given?
rescue Exception => e
  validation_error("#{e.message}", "/")
end

- (Boolean) is_boolean(options = {}, &block)

Check if ratifiable object is a TrueClass or FalseClass. Any other class will result in a failed validation.

Returns:

  • (Boolean)


153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/ratatouille/ratifier.rb', line 153

def is_boolean(options={}, &block)
  parse_options(options)

  unless @skip == true
    unless @unwrap_block == true
      case @ratifiable_object
      when TrueClass, FalseClass 
        # OK to enter block
      else 
        validation_error("#{name} is not a boolean")
        return
      end
    end

    instance_eval(&block) if block_given?
  end
rescue Exception => e
  validation_error("#{e.message}", "/")
end

- (String) name

Name of instance

Returns:



41
42
43
# File 'lib/ratatouille/ratifier.rb', line 41

def name
  @name ||= @ratifiable_object.class.to_s
end

- (String) name=(namein)

Set name of instance

Parameters:

Returns:

  • (String)

    name of Ratatouille::Ratifier instance



50
51
52
53
54
55
56
# File 'lib/ratatouille/ratifier.rb', line 50

def name=(namein)
  case namein
  when String
    @name = namein unless namein.blank?
  end
  @name
end

- (Array) namespace_error_array(arr = [], namespace = "")

Properly prepend namespace definition to array of errors

Parameters:

  • arr (Array) (defaults to: [])
  • namespace (String, Symbol) (defaults to: "")

Returns:

  • (Array)


238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
# File 'lib/ratatouille/ratifier.rb', line 238

def namespace_error_array(arr=[], namespace="")
  errs_out = Array(arr).collect do |e|
    split_err = e.split("|")

    ctxt, err = "", e
    ctxt, err = split_err if split_err.size == 2

    case namespace
    when String  
      ctxt = "#{namespace}#{ctxt}" unless namespace =~ /^\/.?/
    when Symbol 
      ctxt = ":#{namespace}#{ctxt}"
    end

    if ctxt =~ /^\/.?/
      "#{ctxt}|#{err}" 
    else
      "/#{ctxt}|#{err}"
    end
  end

  return Array(errs_out)
end

- (Object) parse_options(options = {})

Parse out common options into instance_variables for use within the validation methods defined in various places.

Parameters:

  • options (Hash) (defaults to: {})

Options Hash (options):

  • :is_a (Class) — default: nil
  • :required (Boolean) — default: false
  • :skip (Boolean) — default: false
  • :unwrap_block (Boolean) — default: false

    Perform block validation only – skip method validation logic.



183
184
185
186
187
188
189
190
# File 'lib/ratatouille/ratifier.rb', line 183

def parse_options(options={})
  if Hash === options
    @is_a =         options.fetch(:is_a, nil)
    @required =     options.fetch(:required, false)
    @skip =         options.fetch(:skip, false)
    @unwrap_block = options.fetch(:unwrap_block, false)
  end
end

- (Boolean) valid?

Does the object pass all validation logic?

Returns:

  • (Boolean)


78
79
80
# File 'lib/ratatouille/ratifier.rb', line 78

def valid?
  @errors.empty?
end

- (void) validation_error(err_in, context = "/")

This method returns an undefined value.

Add validation error. Useful for custom validations.

Parameters:



63
64
65
66
67
68
69
70
71
72
# File 'lib/ratatouille/ratifier.rb', line 63

def validation_error(err_in, context="/" )
  case err_in
  when String
    return if err_in.blank?
    @errors[context] = [] unless @errors[context]
    @errors[context] << err_in
  end
rescue Exception => e
  @errors[context] << "#{e.message}"
end