Module: Mystic

Defined in:
lib/mystic.rb,
lib/mystic/sql.rb,
lib/mystic/model.rb,
lib/mystic/postgres.rb,
lib/mystic/migration.rb,
lib/mystic/sql/index.rb,
lib/mystic/sql/table.rb,
lib/mystic/sql/column.rb

Defined Under Namespace

Modules: Model, SQL Classes: Migration, Postgres

Constant Summary collapse

MysticError =
Class.new StandardError
RootError =
Class.new StandardError
EnvironmentError =
Class.new StandardError
AdapterError =
Class.new StandardError
ConnectionError =
Class.new StandardError
CLIError =
Class.new StandardError
MIG_REGEX =

example: 1_MigrationClassName.rb

/^(?<num>\d+)_(?<name>[a-zA-Z]+)\.rb$/
JSON_COL =
"mystic_return_json89788"

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.postgresObject (readonly)

Returns the value of attribute postgres.



24
25
26
# File 'lib/mystic.rb', line 24

def postgres
  @postgres
end

Class Method Details

.create_mig_tableObject



90
91
92
# File 'lib/mystic.rb', line 90

def create_mig_table
  execute "CREATE TABLE IF NOT EXISTS mystic_migrations (mig_number integer, filename text)"
end

.create_migration(name = "") ⇒ Object

Creates a blank migration in mystic/migrations

Raises:



133
134
135
136
137
138
139
140
141
142
143
# File 'lib/mystic.rb', line 133

def create_migration name=""
  name.strip!
  raise CLIError, "Migration name must not be empty." if name.empty?
    name.capitalize_first!
  
  migs = root.join "mystic","migrations"

  num = migs.entries.map{ |e| MIG_REGEX.match(e.to_s)[:num].to_i rescue 0 }.max.to_i+1

  File.open(migs.join("#{num}_#{name}.rb").to_s, 'w') { |f| f.write(template name) }
end

.db_ymlObject

Accessors



30
31
32
33
34
35
36
37
# File 'lib/mystic.rb', line 30

def db_yml
  if @db_yml.nil?
    # Heroku uses ERB cuz rails uses it errwhere
    yaml = ERB.new(root.join("config","database.yml").read).result
  @db_yml = YAML.load yaml
  end
  @db_yml
end

.disconnectObject



74
75
76
# File 'lib/mystic.rb', line 74

def disconnect
    postgres.disconnect
end

.envObject



39
40
41
# File 'lib/mystic.rb', line 39

def env
  @env
end

.env=(new_env) ⇒ Object Also known as: connect

Raises:



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/mystic.rb', line 43

def env= new_env
  @postgres.disconnect unless @postgres.nil?
  @postgres = nil
  
  load_env
  
      @env = (new_env || ENV["RACK_ENV"] || ENV["RAILS_ENV"] || "development").to_s
      raise EnvironmentError, "Environment '#{@env}' doesn't exist." unless db_yml.member? @env
  
  conf = db_yml[@env].symbolize
  conf[:dbname] = conf.delete :database
  raise MysticError, "Mystic only supports Postgres." unless /^postg.+$/i =~ conf[:adapter]
  
  @postgres = Postgres.new(conf)
  
  @env
end

.escape(str = "") ⇒ Object Also known as: sanitize



83
84
85
86
# File 'lib/mystic.rb', line 83

def escape str=""
    # raise ConnectionError, "Not connected to Postgres" unless postgres.connected?
      postgres.escape str
end

.execute(sql = "") ⇒ Object



78
79
80
81
# File 'lib/mystic.rb', line 78

def execute sql=""
    #raise ConnectionError, "Not connected to Postgres" unless postgres.connected?
  postgres.execute sql.sql_terminate.densify
end

.migrateObject

Runs every yet-to-be-ran migration



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/mystic.rb', line 99

def migrate
  create_mig_table
  migrated_filenames = execute("SELECT filename FROM mystic_migrations").map{ |r| r["filename"] }
  mp = root.join("mystic","migrations").to_s

  Dir.entries(mp)
    .reject { |e| MIG_REGEX.match(e).nil? }
    .reject { |e| migrated_filenames.include? e }
    .sort { |a,b| MIG_REGEX.match(a)[:num].to_i <=> MIG_REGEX.match(b)[:num].to_i }
    .each { |fname|
      load File.join mp,fname
    
      mig_num,mig_name = MIG_REGEX.match(fname).captures
      Object.const_get(mig_name).new.migrate
      execute "INSERT INTO mystic_migrations (mig_number, filename) VALUES (#{mig_num},'#{fname}')"
    }
end

.rollbackObject

Rolls back a single migration



118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/mystic.rb', line 118

def rollback
  create_mig_table
  fname = execute("SELECT filename FROM mystic_migrations ORDER BY mig_number DESC LIMIT 1")[0]["filename"] rescue nil
  return if fname.nil?

  load root.join("mystic","migrations",fname).to_s

  mig_num,mig_name = MIG_REGEX.match(fname).captures

  Object.const_get(mig_name).new.rollback

  execute "DELETE FROM mystic_migrations WHERE filename='#{fname}' and mig_number=#{mig_num}"
end

.root(path = Pathname.new(Dir.pwd)) ⇒ Object

Raises:



61
62
63
64
65
66
# File 'lib/mystic.rb', line 61

def root path=Pathname.new(Dir.pwd)
  raise RootError, "Failed to find the application's root." if path == path.parent
  mystic_path = path.join "config", "database.yml"
    return root(path.parent) unless mystic_path.file? # exist? is implicit with file?
  path
end