class Twimock::Database::Table

Constants

CHILDREN
COLUMN_NAMES
TABLE_NAME

以下は継承先でオーバーライド必須

* TABLE_NAME, COLUMN_NAMES
* initialize()

Public Class Methods

all() click to toggle source
# File lib/twimock/database/table.rb, line 83
def self.all
  records = execute "SELECT * FROM #{table_name};"
  records_to_objects(records)
end
children() click to toggle source
# File lib/twimock/database/table.rb, line 137
def self.children
  self::CHILDREN
end
column_names() click to toggle source
# File lib/twimock/database/table.rb, line 133
def self.column_names
  self::COLUMN_NAMES
end
column_type(column_name) click to toggle source
# File lib/twimock/database/table.rb, line 141
def self.column_type(column_name)
  return nil unless column_names.include?(column_name.to_s.to_sym)
  table_info.send(column_name).type
end
create!(options={}) click to toggle source
# File lib/twimock/database/table.rb, line 77
def self.create!(options={})
  instance = self.new(options)
  instance.save!
  instance
end
first() click to toggle source
# File lib/twimock/database/table.rb, line 88
def self.first
  records = execute "SELECT * FROM #{table_name} LIMIT 1;"
  record_to_object(records.first)
end
last() click to toggle source
# File lib/twimock/database/table.rb, line 93
def self.last
  records = execute "SELECT * FROM #{table_name} ORDER BY ID DESC LIMIT 1 ;"
  record_to_object(records.first)
end
method_missing(name, *args) click to toggle source
Calls superclass method
# File lib/twimock/database/table.rb, line 107
def self.method_missing(name, *args)
  if ((name =~ /^find_by_(.+)/ || name =~ /^find_all_by_(.+)/) && 
    (column_name = $1) && column_names.include?(column_name.to_sym))
    raise ArgumentError, "wrong number of arguments (#{args.size} for 1)" unless args.size == 1
    define_find_method(name, column_name) ? send(name, args.first) : super
  else
    super
  end
end
new(options={}) click to toggle source
# File lib/twimock/database/table.rb, line 15
def initialize(options={})
  opts = Hashie::Mash.new(options)
  self.id = opts.id
  self.text = opts.text
  self.active = opts.active || false
  self.number = opts.number
  self.created_at = opts.created_at
end
table_info() click to toggle source
# File lib/twimock/database/table.rb, line 146
def self.table_info
  sql = "PRAGMA TABLE_INFO(#{table_name});"
  records = execute sql
  info = Hashie::Mash.new
  records.each do |record|
    column_info = Hashie::Mash.new(
      { cid:         record[0],
        name:        record[1].to_sym,
        type:        record[2],
        notnull:    (record[3] == 1),
        dflt_value:  record[4],
        pk:         (record[5] == 1) }
    )
    info.send(record[1] + "=", column_info)
  end
  info
end
table_name() click to toggle source
# File lib/twimock/database/table.rb, line 129
def self.table_name
  self::TABLE_NAME
end
where(column) click to toggle source
# File lib/twimock/database/table.rb, line 98
def self.where(column)
  column_name = column.keys.first
  value = column.values.first
  column_value = (value.kind_of?(String)) ? "'" + value + "'" : value.to_s

  records = execute "SELECT * FROM #{table_name} WHERE #{column_name} = #{column_value};"
  records_to_objects(records)
end

Private Class Methods

column_notnull(column_name) click to toggle source
# File lib/twimock/database/table.rb, line 347
def self.column_notnull(column_name)
  return nil unless column_names.include?(column_name.to_s.to_sym)
  table_info.send(column_name).notnull
end
define_find_all_by_column(column_name) click to toggle source
# File lib/twimock/database/table.rb, line 240
      def self.define_find_all_by_column(column_name)
        self.class_eval <<-EOF
          def self.find_all_by_#{column_name}(value)
            return [] if value.nil?

            column_value = case value
            when String then "'" + value + "'"
            when Time   then "'" + value.to_s + "'"
            else value.to_s
            end

            sql  = "SELECT * FROM #{table_name} WHERE #{column_name} = "
            sql += column_value + ";"
            records = execute sql
            records_to_objects(records)
          end
        EOF
        true
      end
define_find_by_column(column_name) click to toggle source
# File lib/twimock/database/table.rb, line 220
      def self.define_find_by_column(column_name)
        self.class_eval <<-EOF
          def self.find_by_#{column_name}(value)
            return nil if value.nil?

            column_value = case value
            when String then "'" + value + "'"
            when Time   then "'" + value.to_s + "'"
            else value.to_s
            end

            sql  = "SELECT * FROM #{table_name} WHERE #{column_name} = "
            sql += column_value + " LIMIT 1;"
            records = execute sql
            record_to_object(records.first)
          end
        EOF
        true
      end
define_find_method(method_name, column_name) click to toggle source
# File lib/twimock/database/table.rb, line 213
def self.define_find_method(method_name, column_name)
  case method_name
  when /^find_by_(.+)/     then define_find_by_column(column_name)
  when /^find_all_by_(.+)/ then define_find_all_by_column(column_name)
  end
end
execute(sql) click to toggle source
# File lib/twimock/database/table.rb, line 170
      def self.execute(sql)
        database = Twimock::Database.new
        records = database.connection.execute sql
        if records.empty? && sql =~ /^INSERT /
          records = database.connection.execute <<-SQL
            SELECT * FROM #{table_name} WHERE ROWID = last_insert_rowid();
          SQL
        end
        database.disconnect!
        records
      end
record_to_hash(record) click to toggle source

以下の形式のHashが返される

{ id: x, ..., created_at: yyyy-mm-dd :hh:mm +xxxx }
# File lib/twimock/database/table.rb, line 199
def self.record_to_hash(record)
  hash = Hashie::Mash.new
  column_names.each_with_index do |column_name, index|
    value = (record[index] == "") ? nil : record[index]
    parsed_value = case column_type(column_name)
    when "BOOLEAN"  then eval(value)
    when "DATETIME" then Time.parse(value)
    else  value
    end
    hash.send(column_name.to_s + "=", parsed_value)
  end
  hash
end
record_to_object(record) click to toggle source
# File lib/twimock/database/table.rb, line 182
def self.record_to_object(record)
  return nil unless record
  self.new(record_to_hash(record))
end
records_to_objects(records) click to toggle source
# File lib/twimock/database/table.rb, line 187
def self.records_to_objects(records)
  records.inject([]) do |objects, record|
    objects << record_to_object(record)
  end
end

Public Instance Methods

column_names() click to toggle source
# File lib/twimock/database/table.rb, line 121
def column_names
  self.class.column_names
end
destroy() click to toggle source
# File lib/twimock/database/table.rb, line 34
def destroy
  raise unless persisted?
  self.class.children.each do |klass|
    klass_last_name = self.class.name.split("::").last.downcase
    find_method_name = "find_all_by_#{klass_last_name}_id"
    objects = klass.send(find_method_name, self.id)
    objects.each{|object| object.destroy }
  end

  execute "DELETE FROM #{table_name} WHERE ID = #{self.id};"
  self
end
fetch() click to toggle source
# File lib/twimock/database/table.rb, line 47
def fetch
  if persisted?
    sql = "SELECT * FROM #{table_name} WHERE ID = #{self.id} LIMIT 1;"
    records = execute sql
    return nil unless record = records.first
    set_attributes_from_record(record)
    self
  end
end
method_missing(name, *args) click to toggle source
Calls superclass method
# File lib/twimock/database/table.rb, line 57
def method_missing(name, *args)
  method_name = name.to_s.include?("=") ? name.to_s[0...-1].to_sym : name
  case name
  when :identifier  then return send(:id)
  when :identifier= then return send(:id=, *args)
  else
    if column_names.include?(method_name) && args.size <= 1
      if !name.to_s.include?("=") && args.empty?
        define_column_getter(name)
        return send(name)
      else
        define_column_setter(name)
        return send(name, args.first)
      end
    else
      super
    end
  end
end
persisted?() click to toggle source
# File lib/twimock/database/table.rb, line 125
def persisted?
  !!(self.id && !(self.class.find_by_id(self.id).nil?))
end
save!(options={}) click to toggle source
# File lib/twimock/database/table.rb, line 24
def save!(options={})
  persisted? ? update!(options) : insert!(options)
end
table_name() click to toggle source
# File lib/twimock/database/table.rb, line 117
def table_name
  self.class.table_name
end
update_attributes!(options) click to toggle source
# File lib/twimock/database/table.rb, line 28
def update_attributes!(options)
  # カラムに含まれるかどうかの確認。なければNoMethodError
  options.each_key {|key| self.send(key) }
  persisted? ? update!(options) : insert!(options)
end

Private Instance Methods

column_is_empty?(column_name) click to toggle source
# File lib/twimock/database/table.rb, line 336
def column_is_empty?(column_name)
  return true if self.send(column_name).nil?

  return case self.class.column_type(column_name)
  when "TEXT", "DATETIME", "BOOLEAN"
    true if self.send(column_name) == ""
  else
    false
  end
end
define_column_getter(name) click to toggle source
# File lib/twimock/database/table.rb, line 260
      def define_column_getter(name)
        self.class.class_eval <<-EOF
          def #{name}
            self.instance_variable_get(:@#{name})
          end
        EOF
      end
define_column_setter(name) click to toggle source
# File lib/twimock/database/table.rb, line 268
      def define_column_setter(name)
        self.class.class_eval <<-EOF
          def #{name}(value)
            instance_variable_set(:@#{name.to_s.gsub("=", "")}, value)
          end
        EOF
      end
execute(sql) click to toggle source
# File lib/twimock/database/table.rb, line 166
def execute(sql)
  self.class.execute(sql)
end
insert!(options={}) click to toggle source

DatabaseへのINSERTが成功してからインスタンスのフィールド値を更新する

# File lib/twimock/database/table.rb, line 277
def insert!(options={})
  opts = Hashie::Mash.new(options)
  instance = self.class.new
  column_names.each do |column_name|
    next if column_name == :created_at
    notnull_check(column_name)
    instance.send(column_name.to_s + "=", self.send(column_name))

    if opts.send(column_name)
      instance.send(column_name.to_s + "=", opts.send(column_name))
    end
  end

  target_column_names = if instance.id
    column_names
  else
    column_names.select{|name| name != :id}
  end
  instance.created_at = Time.now
  target_column_values = target_column_names.inject([]) do |ary, column_name|
    ary << "'#{instance.send(column_name)}'"
  end
  values  = target_column_values.join(", ")
  columns = target_column_names.join(', ')

  sql = "INSERT INTO #{table_name}(#{columns}) VALUES ( #{values} );"
  records = execute sql
  set_attributes_from_record(records.first)
  true
end
notnull_check(column_name) click to toggle source
# File lib/twimock/database/table.rb, line 352
def notnull_check(column_name)
  if self.class.column_notnull(column_name) && column_is_empty?(column_name)
    raise Twimock::Errors::ColumnTypeNotNull, "#{column_name} is null"
  end
end
record_to_hash(record) click to toggle source
# File lib/twimock/database/table.rb, line 193
def record_to_hash(record)
  self.class.record_to_hash(record)
end
set_attributes_from_record(record) click to toggle source
# File lib/twimock/database/table.rb, line 328
def set_attributes_from_record(record)
  hash = record_to_hash(record)
  column_names.each do |column_name|
    method_name = column_name.to_s + "="
    self.send(method_name, hash.send(column_name))
  end
end
update!(options={}) click to toggle source
# File lib/twimock/database/table.rb, line 308
def update!(options={})
  if options.empty?
    column_names.each do |column_name|
      if (value = self.send(column_name)) && column_name != :id
        options[column_name] = value unless options.nil?
      end
    end
  end

  unless options.empty?
    target_key_values = options.inject([]) do |ary, (key, value)|
      ary << (value.kind_of?(Integer) ? "#{key} = #{value}" : "#{key} = '#{value}'")
    end
    sql = "UPDATE #{table_name} SET #{target_key_values.join(', ')} WHERE ID = #{self.id};"
    execute sql
  end
  fetch
  true
end