Class: Sqrbl::Step

Inherits:
Object show all
Includes:
ExpectsBlockWithNew, HasTodos, MethodMissingDelegation
Defined in:
lib/sqrbl/step.rb

Overview

The Step class is where most of the work of SQrbL takes place. All of the public methods on this class have side effects: they take the parameters given, tweak their format in some way, and use them to append data to the output attribute.

For example, the following code will cause the DELETE statement to appear in output:

action "Drop imported organizational contacts" {
  'DELETE FROM new_widgets WHERE note LIKE "Imported from old_widgets"'
}

action is the primary method you’ll use to do the actual work, but there are a number of other helper methods that let you insert variously-formatted comments, and insert_into helps DRY up some of the verbosity involved in writing INSERT statements.

Constant Summary collapse

GiantWarningText =

:stopdoc:

<<-EOF
##     ##    ###    #######   ##    ##  ######  ##    ##    #####    ##
##     ##   ## ##   ##    ##  ###   ##    ##    ###   ##   ##   ##   ##
##     ##  ##   ##  ##    ##  ####  ##    ##    ####  ##  ##         ##
##  #  ##  #######  #######   ## ## ##    ##    ## ## ##  ##   ####  ##
## ### ##  ##   ##  ##  ##    ##  ####    ##    ##  ####  ##     ##  ##
#### ####  ##   ##  ##   ##   ##   ###    ##    ##   ###   ##   ##
###   ###  ##   ##  ##    ##  ##    ##  ######  ##    ##    #####    ##
EOF
GiantWarningSeparator =
'#' * GiantWarningText.split(/\n/).map(&:length).max
GiantWarningTemplate =
"/*" +
"\n" + GiantWarningSeparator + "\n" +
"\n" + GiantWarningText      +
"\n" + GiantWarningSeparator + "\n[[LineNum]]\n[[Message]]" +
"\n" + GiantWarningSeparator +
"\n" + "*/"

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from HasTodos

#todos

Methods included from MethodMissingDelegation

included

Constructor Details

#initialize(step_pair, options = {}, &block) ⇒ Step

:startdoc:



49
50
51
52
53
54
55
# File 'lib/sqrbl/step.rb', line 49

def initialize(step_pair, options = {}, &block)
  @output    = ''
  @step_pair = step_pair
  @block     = lambda(&block)

  eval_block_on_initialize(options)
end

Instance Attribute Details

#blockObject (readonly)

Returns the value of attribute block.



23
24
25
# File 'lib/sqrbl/step.rb', line 23

def block
  @block
end

#outputObject (readonly)

Returns the value of attribute output.



23
24
25
# File 'lib/sqrbl/step.rb', line 23

def output
  @output
end

#step_pairObject (readonly)

Returns the value of attribute step_pair.



23
24
25
# File 'lib/sqrbl/step.rb', line 23

def step_pair
  @step_pair
end

Instance Method Details

#action(message, &block_returning_string) ⇒ Object

Expects a message and a block whose return value is a string. Outputs a comment containing message, followed by the return value of the block.



128
129
130
131
# File 'lib/sqrbl/step.rb', line 128

def action(message, &block_returning_string)
  comment(message)
  write(unindent(block_returning_string.call))
end

#block_comment(&block_returning_string) ⇒ Object

Outputs a message surrounded by /* SQL block-comment delimiters */.



122
123
124
# File 'lib/sqrbl/step.rb', line 122

def block_comment(&block_returning_string)
  write "/*\n%s\n*/" % indent(4, unindent(yield))
end

#comment(message) ⇒ Object

Outputs a message preceded by the SQL line-comment prefix "-- ".



117
118
119
# File 'lib/sqrbl/step.rb', line 117

def comment(message)
  write '-- ' + message
end

#helpers(&block) ⇒ Object

This method is purely cosmetic. If you want to define a number of helpers and use your editor’s code-folding features to collapse them all together, define them in a helper block.



60
61
62
# File 'lib/sqrbl/step.rb', line 60

def helpers(&block)
  yield
end

#insert_into(table_name, map_from_fieldname_to_expr = {}) ⇒ Object

Helper method for DRYing up INSERT statements. Takes a table name and a hash that maps field names to SQL expressions, and builds an INSERT statement that populates those fields. For example:

insert_into 'new_widgets', {
  :name     => 'widget_name',
  :part_num => 'CONCAT("X_", part_number)',
  :note     => '"Imported from old_widgets"',
}

will produce:

INSERT INTO new_widgets (
    part_num,
    note,
    name
)
SELECT
    CONCAT("X_", part_number) AS part_num,
    "Imported from old_widgets" AS note,
    widget_name AS name

(Note that this only creates the INSERT INTO and SELECT clauses of a SQL statement.)



157
158
159
160
161
162
163
164
165
166
167
# File 'lib/sqrbl/step.rb', line 157

def insert_into(table_name, map_from_fieldname_to_expr = {})
  # Build the "INSERT INTO (foo, bar, baz)" clause
  insert_fields = map_from_fieldname_to_expr.keys.join(",\n")
  insert_clause = "INSERT INTO %s (\n%s\n)\n" % [table_name, indent(4, insert_fields)]

  # Build the "SELECT FROM" clause
  select_fields = map_from_fieldname_to_expr.map { |field_name, expr| "#{expr} AS #{field_name}" }.join(",\n")
  select_clause = "SELECT\n" + indent(4, select_fields)

  insert_clause + select_clause
end

#todo(message) ⇒ Object

Writes a commented-out Todo item to output.

Also, creates a Todo object that may be used to create console output when building the *.sql output files (see HasTodos for more information).



69
70
71
72
73
74
# File 'lib/sqrbl/step.rb', line 69

def todo(message)
  returning(super) do |todo|
    todo_msg = "--> %s %s:\t%s" % ['todo'.upcase, caller_info(todo), todo.message]
    write todo_msg
  end
end

#warning(message) ⇒ Object Also known as: danger_will_robinson!

Takes message and writes it to output surrounded by a large block-commented ASCII-art message that reads “WARNING!”. The intent here is to create a large message that stands out when scrolling through the output or copy/pasting it into your SQL client. This message will also contain information pointing you to the place where warning was called.

For example, calling warning "Danger, Will Robinson!" from foo.rb on line 42 will append something like the following to output:

/*
#######################################################################

##     ##    ###    #######   ##    ##  ######  ##    ##    #####    ##
##     ##   ## ##   ##    ##  ###   ##    ##    ###   ##   ##   ##   ##
##     ##  ##   ##  ##    ##  ####  ##    ##    ####  ##  ##         ##
##  #  ##  #######  #######   ## ## ##    ##    ## ## ##  ##   ####  ##
## ### ##  ##   ##  ##  ##    ##  ####    ##    ##  ####  ##     ##  ##
#### ####  ##   ##  ##   ##   ##   ###    ##    ##   ###   ##   ##
###   ###  ##   ##  ##    ##  ##    ##  ######  ##    ##    #####    ##

#######################################################################
(foo.rb, line 42)
Danger, Will Robinson!
#######################################################################
*/

Also, creates a Todo object of subtype :warning that may be used to create console output when building the *.sql output files (see HasTodos for more information).



107
108
109
110
111
112
113
# File 'lib/sqrbl/step.rb', line 107

def warning(message)
  returning(super) do |warn|
    giant_warning = GiantWarningTemplate.gsub('[[LineNum]]', caller_info(warn)) \
                                        .gsub('[[Message]]', warn.message)
    write giant_warning
  end
end

#write(text) ⇒ Object

Write text to output, followed by newlines. (This is used by most other methods on Step; it’s made public in case you want to use it in a way I didn’t anticipate.)



172
173
174
# File 'lib/sqrbl/step.rb', line 172

def write(text)
  output << text + "\n\n"
end