Sha256: 19bb0bab5a700c1bc7fa3053e5ee95032e8887cec20ac71b8cfd7644f9328d6d

Contents?: true

Size: 1.47 KB

Versions: 3

Compression:

Stored size: 1.47 KB

Contents

%%{
  machine validator;

  # http://www.postgresql.org/docs/current/static/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
  operator = [*/+\-];
  number   = '-'? digit+ ('.' digit+)?;
  word     = [a-z_][a-z_0-9]*;
  group    = '(' @{ fcall rest; };
  # The ternary operator is not SQL, but it is Ruby and JavaScript.
  ternary  = word space* '<' space* number space* '?' space* number space* ':' space* number;
  factor   = number | word | ternary | group;
  # Strong difference to prevent SQL comments.
  expr     = (space* factor (space* operator space* factor)* space*) -- '--';
  rest    := expr ')' @{ fret; };

  main := expr;
}%%

module CitizenBudgetModel
  # Validates the format of simple mathematical equation.
  class EquationValidator < ActiveModel::EachValidator
    %% write data;
    #% # fix highlighting

    # Returns whether an equation is valid.
    #
    # @param [String] value an equation
    # @return [Boolean] whether the equation is valid
    # @see http://stackoverflow.com/questions/12015684/simple-ragel-example-that-balances-parentheses
    def self.valid?(value)
      data = value.unpack('c*')
      stack = []

      %% write init;
      %% write exec;

      # Ensure all parentheses are closed and the state machine is in a final state.
      top.zero? && cs >= validator_first_final
    end

    def validate_each(record, attribute, value)
      record.errors.add(attribute, :invalid, options.merge(value: value)) unless self.class.valid?(value)
    end
  end
end

Version data entries

3 entries across 3 versions & 1 rubygems

Version Path
citizen_budget_model-0.0.4 app/validators/citizen_budget_model/equation_validator.rl
citizen_budget_model-0.0.3 app/validators/citizen_budget_model/equation_validator.rl
citizen_budget_model-0.0.2 app/validators/citizen_budget_model/equation_validator.rl