module Datoki::Def_Field

Attributes

fields[R]
fields_as_required[R]
ons[R]
table_name[R]

Public Instance Methods

allow(sym) click to toggle source
# File lib/datoki.rb, line 136
def allow sym
  fields[@current_field][:allow][sym] = true;
end
create(raw) click to toggle source
# File lib/datoki.rb, line 492
def create raw
  raw[:create] = self.to_s
  new raw
end
disable(*props) click to toggle source
# File lib/datoki.rb, line 446
def disable *props
  props.each { |prop|
    case prop
    when :min, :max
      field.delete prop
    when :strip, :null
      field[:allow][prop] = false
    else
      field[:cleaners][prop] = false
    end
  }
end
enable(*props) click to toggle source
# File lib/datoki.rb, line 435
def enable *props
  props.each { |prop|
    case prop
    when :strip, :null
      field[:allow][prop] = true
    else
      field[:cleaners][prop] = true
    end
  }
end
equal_to(*args) click to toggle source
# File lib/datoki.rb, line 464
def equal_to *args
  field[:cleaners][:equal_to] ||= []
  field[:cleaners][:equal_to].concat args
end
field(*args) { || ... } click to toggle source
# File lib/datoki.rb, line 164
def field *args
  # === Setup a default table if none specified:
  if !@table_name && Datoki.db
    t_name = self.to_s.downcase.to_sym
    table(t_name) if Datoki.db.tables.include?(t_name)
  end

  return fields[@current_field] if args.empty?
  return fields[args.first] unless block_given?

  name = args.first

  fail "#{name.inspect} already defined." if fields[name]
  fields_as_required[:"#{name}!"] = name

  fields[name] = {
    :name         => name,
    :type         => :unknown,
    :english_name => name.to_s.freeze,
    :allow        => {:null => false},
    :disable      => {},
    :cleaners     => {},
    :on           => {}
  }

  @current_field = name

  if field? :chars
    field[:allow][:strip] = true
  end

  if schema[name]
    if schema[name].has_key? :max_length
      fields[name][:max] = schema[name][:max_length]
    end
  end

  yield

  fail("Type not specified for #{name.inspect}") if field[:type] == :unknown

  # === check :allow_null and :min are not both set.
  if field?(:chars) && field[:allow][:null] && field.has_key?(:min) && field[:min] < 1
    fail "#{field[:type].inspect} can't be both: allow :null && :min = #{field[:min]}"
  end

  # === Ensure schema matches with field definition:
  schema_match

  field[:html_escape] = case
                        when field[:html_escape]
                          field[:html_escape]
                        when field?(:numeric)
                          :number
                        when field?(:chars)
                          :string
                        else
                          fail "Unknown html_escape for: #{field[:name].inspect}"
                        end

  @current_field = nil
end
field?(*args) click to toggle source
# File lib/datoki.rb, line 160
def field? *args
  inspect_field?(:type, field[:name], *args)
end
field_on(action, meth_name_sym) click to toggle source
# File lib/datoki.rb, line 305
def field_on action, meth_name_sym
  fail "Invalid action: #{action.inspect}" unless Actions.include? action
  if field
    field[:on][action] ||= {}
    field[:on][action][meth_name_sym] = true
  else
    @ons[action] ||= {}
    @ons[action][meth_name_sym] = true
  end
  self
end
href(*args) click to toggle source
# File lib/datoki.rb, line 347
def href *args
  field[:html_escape] = :href
  case args.map(&:class)
  when []
    varchar 1, 255
  when [NilClass]
    varchar nil, 1, (schema[field[:name]] ? schema[field[:name]][:max_length] : 255)
  else
    varchar *args
  end
end
html_escape() click to toggle source
# File lib/datoki.rb, line 93
def html_escape
  @html_escape ||= begin
                     fields.inject({}) { |memo, (name, meta)|
                       memo[name] = meta[:html_escape]
                       memo
                     }
                   end
end
included_in(arr) click to toggle source
# File lib/datoki.rb, line 469
def included_in arr
  field[:cleaners][:included_in] ||= []
  field[:cleaners][:included_in].concat arr
end
initialize_def_field() click to toggle source
# File lib/datoki.rb, line 53
def initialize_def_field
  @ons                = {}
  @fields             = {} # Ex: {:name=>{}, :age=>{}}
  @fields_as_required = {} # Ex: {:name!=>:name}
  @current_field      = nil
  @schema             = {}
  @schema_match       = false
  @table_name         = nil
end
inspect_field?(target, name, *args) click to toggle source
# File lib/datoki.rb, line 119
def inspect_field? target, name, *args
  case target
  when :type
    meta = fields[name]
    fail "Unknown field: #{name.inspect}" unless meta
    return true if args.include?(meta[:type])
    return true if args.include?(:chars) && Char_Types.include?(meta[:type])
    args.include?(:numeric) && Numeric_Types.include?(meta[:type])
  else
    fail "Unknown arg: #{target.inspect}"
  end
end
matches(v = :blok) click to toggle source
# File lib/datoki.rb, line 487
def matches v = :blok
  field[:cleaners][:match] ||= []
  field[:cleaners][:match] << (v == :blok ? Proc.new : v)
end
primary_key() click to toggle source
# File lib/datoki.rb, line 330
def primary_key
  field[:primary_key] = true
  if field?(:unknown)
    if schema[field[:name]]
      type schema[field[:name]][:type]
    else
      type :integer
    end
  end

  true
end
pseudo() click to toggle source
# File lib/datoki.rb, line 132
def pseudo
  fields[@current_field][:pseudo] = true
end
returning_fields() click to toggle source

This method removes keys that are meant to be secret: e.g. encrypted passwords. This decreases the chance they end up in logs.

# File lib/datoki.rb, line 145
def returning_fields
  return [] unless table_name
  s = Datoki.db.schema(table_name)
  return [] unless s
  s.map { |pair|
    name, meta = pair
    field = fields[name]
    if !field || !field[:secret]
      name
    else
      nil
    end
  }.compact
end
schema(*args) click to toggle source
# File lib/datoki.rb, line 102
def schema *args
  case args.size

  when 0
    @schema 

  when 1
    result = @schema[args.first]
    fail "Unknown field: #{args.first.inspect}" unless result
    result

  else
    fail "Unknown args: #{args.inspect}"

  end
end
schema_match(target = :current) click to toggle source
# File lib/datoki.rb, line 227
def schema_match target = :current
  return true if !@table_name
  return true if schema_match?

  if target == :all # === do a schema match on entire table
    schema.each { |name, db_schema|
      orig_field = @current_field
      @current_field = name
      schema_match
      @current_field = orig_field
    }

    @schema_match = true
    return true
  end # === if target

  name      = @current_field
  db_schema = schema[@current_field]

  return true if db_schema && !field
  return true if field[:schema_has_been_matched]
  return true if field[:pseudo]

  if db_schema[:allow_null] != field[:allow][:null]
    fail Schema_Conflict, "#{name}: :allow_null: #{db_schema[:allow_null].inspect} != #{field[:allow][:null].inspect}"
  end

  if field?(:chars)
    if !field[:min].is_a?(Numeric) || field[:min] < 0
      fail ":min not properly defined for #{name.inspect}: #{field[:min].inspect}"
    end

    if !field[:max].is_a?(Numeric)
      fail ":max not properly defined for #{name.inspect}: #{field[:max].inspect}"
    end
  end

  if db_schema.has_key?(:max_length)
    if field[:max] != db_schema[:max_length]
      fail Schema_Conflict, "#{name}: :max: #{db_schema[:max_length].inspect} != #{field[:max].inspect}"
    end
  end

  if !!db_schema[:primary_key] != !!field[:primary_key]
    fail Schema_Conflict, "#{name}: :primary_key: #{db_schema[:primary_key].inspect} != #{field[:primary_key].inspect}"
  end

  # === match :type
  if field[:type] != :string_ish
    db_type = Datoki.db_type_to_ruby db_schema[:db_type], db_schema[:type]
    type    = field[:type]
    if db_type != type
      fail Schema_Conflict, "#{name}: :type: #{db_type.inspect} != #{type.inspect}"
    end
  end

  # === match :max_length
  db_max = db_schema[:max_length]
  max    = field[:max]
  if !db_max.nil? && db_max != max
    fail Schema_Conflict, "#{name}: :max_length: #{db_max.inspect} != #{max.inspect}"
  end

  # === match :min_length
  db_min = db_schema[:min_length]
  min    = field[:min]
  if !db_min.nil? && db_min != min
    fail Schema_Conflict, "#{name}: :min_length: #{db_min.inspect} != #{min.inspect}"
  end

  # === match :allow_null
  if db_schema[:allow_null] != field[:allow][:null]
    fail Schema_Conflict, "#{name}: :allow_null: #{db_schema[:allow_null].inspect} != #{field[:allow][:null].inspect}"
  end

  field[:schema_has_been_matched] = true
end
schema_match?() click to toggle source
# File lib/datoki.rb, line 63
def schema_match?
  @schema_match
end
secret() click to toggle source
# File lib/datoki.rb, line 326
def secret
  field[:secret] = true
end
set_to(v = :blok) click to toggle source
# File lib/datoki.rb, line 459
def set_to v = :blok
  field[:cleaners][:set_to] ||= []
  field[:cleaners][:set_to] << (v == :blok ? Proc.new : v)
end
table(name) click to toggle source
# File lib/datoki.rb, line 67
def table name
  fail ArgumentError, "Table name must be a Symbol: #{name.inspect}" unless name.is_a?(Symbol)
  if !@schema.empty? || @table_name
    fail "Schema/table already defined: #{@table_name.inspect}"
  end

  db_schema = Datoki.db.schema(name)

  if !db_schema
    fail ArgumentError, "Schema not found for: #{name.inspect}"
  end

  @table_name = name
  self.const_set(:TABLE, DB[@table_name])

  db_schema.each { |pair|
    @schema[pair.first] = pair.last
  }

  if @schema.empty?
    @schema_match = true
  end

  schema
end
text(*args) click to toggle source
# File lib/datoki.rb, line 343
def text *args
  type :text, *args
end
type(name, *args) click to toggle source
# File lib/datoki.rb, line 367
def type name, *args
  field[:type] = name

  if field? :chars

    enable :strip

    if field?(:text)
      field[:max] ||= 4000
    else
      field[:max] ||= 255
    end

    if schema[name] && !schema[name][:allow_null]
      field[:min] = 1
    end

  end # === if field? :chars

  case args.map(&:class)

  when []
    # do nothing

  when [Array]
    field[:options] = args.first
    enable(:null) if field[:options].include? nil
    disable :min, :max

  when [NilClass]
    if field?(:chars)
      fail "A :min and :max is required for String fields."
    end

    enable :null

  when [NilClass, Fixnum, Fixnum]
    field[:allow][:null] = true
    field[:min] = args[-2]
    field[:max] = args.last

  when [Fixnum, Fixnum]
    field[:min], field[:max] = args

  when [Proc], [Regexp]
    matches *args

  when [Fixnum, Fixnum, Proc], [Fixnum, Fixnum, Regexp]
    field[:min] = args.shift
    field[:max] = args.shift
    matches *args

  else
    fail "Unknown args: #{args.inspect}"

  end # === case

end
unique_index(name, msg = nil) click to toggle source
# File lib/datoki.rb, line 317
def unique_index name, msg = nil
  field[:unique_index] = name
  if msg
    field[:error_msgs] ||= {}
    field[:error_msgs][:unique] = msg
  end
  self
end
update(raw) click to toggle source
# File lib/datoki.rb, line 497
def update raw
  raw[:update] = self.to_s
  new raw
end