Module: DT

Defined in:
lib/dt.rb,
lib/dt/action_controller_extensions.rb

Overview

Debug toolkit.

Allows to print debug messages from anywhere in your Rails project. Do a:

DT.p "Hello, world!"

, and see the message in log, log/dt.log, console and web.

To set up web output, in your application root do a:

$ rails generate rails_dt     # Rails 3
$ script/generate rails_dt    # Rails 2

Follow the instructions the generator gives you then.

Defined Under Namespace

Modules: ActionControllerExtensions

Constant Summary collapse

MAX_WEB_MESSAGES =

Maximum number of stored messages, if they’re not cleared. If web output is configured, messages are cleared before every request.

100

Class Method Summary collapse

Class Method Details

._hash_kbinding(h) ⇒ Object

Turn hash’s entries into locals and return binding. Useful for simple templating.



212
213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/dt.rb', line 212

def self._hash_kbinding(h)    #:nodoc:
  # NOTE: This IS important, since assignment is eval'd in this context.
  bnd = binding

  _value = nil
  h.each do |k, v|
    ##puts "-- k-#{k.inspect} v-#{_value.inspect}"    #DEBUG
    _value = v      # IMPORTANT: Ruby 1.9 compatibility hack.
    eval("#{k} = _value", bnd)
  end

  bnd
end

._initializeObject

Initializer.



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/dt.rb', line 26

def self._initialize    #:nodoc:
  clear_web_messages

  # NOTES:
  # * Stuffing is inserted in order to work around buggy RDoc parser.
  #   "a""bc" => "abc", just in case.
  # * Don't forget to update generator/initializers/dt.rb with these.
  # * "Canonical" order of imporance: log, console, web.
  @log_prefix = "[DT <""%= file_rel %>:<""%= line %>] "
  @console_prefix = @log_prefix.dup
  @web_prefix = '<a href="txmt://open?url=file://<''%= file %>&line=<''%= line %>"><''%= file_rel %>:<''%= line %></a> '

  # In case of path problems @log will be nil.
  @log = Logger.new(Rails.root + "log/dt.log") rescue nil
end

._otf_initObject

On-the-fly initializer.



43
44
45
46
47
48
49
50
51
# File 'lib/dt.rb', line 43

def self._otf_init    #:nodoc:
  # Consider job done, replace self with a blank.
  class_eval {
    def self._otf_init    #:nodoc:
    end
  }

  _initialize
end

.clear_web_messagesObject

Clear messages.



125
126
127
128
# File 'lib/dt.rb', line 125

def self.clear_web_messages
  _otf_init
  @web_messages = []
end

.console_prefixObject



59
60
61
62
# File 'lib/dt.rb', line 59

def self.console_prefix
  _otf_init
  @console_prefix
end

.console_prefix=(s) ⇒ Object

Set message prefix for console. See log_prefix=.



54
55
56
57
# File 'lib/dt.rb', line 54

def self.console_prefix=(s)
  _otf_init
  @console_prefix = s
end

.logObject



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

def self.log
  _otf_init
  @log
end

.log=(obj) ⇒ Object

Set logger to use. Must be a Logger.

log = Logger.new("log/my.log")


67
68
69
70
71
# File 'lib/dt.rb', line 67

def self.log=(obj)
  _otf_init
  raise "Logger expected, #{obj.class} given" if not obj.is_a? Logger
  @log = obj
end

.log_prefixObject



100
101
102
103
# File 'lib/dt.rb', line 100

def self.log_prefix
  _otf_init
  @log_prefix
end

.log_prefix=(s) ⇒ Object

Set message prefix for log. Syntax is ERB.

log_prefix = "[DT <""%= file_rel %>:<""%= line %>] "

NOTE: In the above example some stuffing was made to satisfy the buggy RDoc parser. Just in case, "a""bc" is "abc" in Ruby.

Template variables:

  • file – full path to file.

  • file_base – file base name.

  • file_rel – file name relative to Rails application root.

  • line – line number.

By setting prefix to nil you disable respective output.

web_prefix = nil      # Disable web output.


95
96
97
98
# File 'lib/dt.rb', line 95

def self.log_prefix=(s)
  _otf_init
  @log_prefix = s
end

.p(*args) ⇒ Object

Print a debug message or dump a value. Somewhat similar to Ruby’s native p.

p "Hello, world!"
p "myvar", myvar


134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/dt.rb', line 134

def self.p(*args)
  _otf_init
  # Fetch caller information.
  # NOTE: May be lacking file information, e.g. when in an irb session.
  file, line = caller.first.split(":")

  # Assign template variables.
  hc = {
    :file => file,
    :line => line,
    :file_base => (begin; File.basename(file); rescue; file; end),
    :file_rel => (begin; Pathname(file).relative_path_from(Rails.root).to_s; rescue; file; end),
  }

  args.each do |r|
    s = r.is_a?(String) ? r : r.inspect

    # To log.
    if @log_prefix
      ##Kernel.p "@log", @log   #DEBUG
      if @log
        pfx = ERB.new(@log_prefix, nil, "-").result(_hash_kbinding(hc))
        msg = [pfx, s].join
        @log.info msg
        Rails.logger.info msg rescue nil    # In case something's wrong with `Rails.logger`.
      end
    end

    # To console.
    if @console_prefix
      pfx = ERB.new(@console_prefix, nil, "-").result(_hash_kbinding(hc))
      puts [pfx, s].join
    end

    # To web.
    if @web_prefix
      pfx = ERB.new(@web_prefix, nil, "-").result(_hash_kbinding(hc))

      pcs = []
      pcs << pfx
      pcs << CGI.escapeHTML(s).gsub("\n", "<br/>\n")
      @web_messages << pcs.join

      # Rotate messages.
      @web_messages.slice!(0..-(MAX_WEB_MESSAGES + 1))
    end
  end

  # Be like `puts`, return nil.
  nil
end

.web_messagesObject

Return messages accumulated since last cleared.



106
107
108
109
# File 'lib/dt.rb', line 106

def self.web_messages
  _otf_init
  @web_messages
end

.web_messages_as_htmlObject

Format accumulated web messages as HTML. Usually called from a view template.

web_messages_as_html    # => Something like "<ul><li>Message 1</li><li>Message 2</li>...</ul>".


189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/dt.rb', line 189

def self.web_messages_as_html
  _otf_init

  pcs = []
  pcs << "<ul>"
  @web_messages.each do |s|
    pcs << ["<li>", s, "</li>"].join
  end
  pcs << "</ul>"

  if (out = pcs.join).respond_to? :html_safe
    out.html_safe
  else
    out
  end
end

.web_prefixObject



117
118
119
120
# File 'lib/dt.rb', line 117

def self.web_prefix
  _otf_init
  @web_prefix
end

.web_prefix=(s) ⇒ Object

Set message prefix for web. See log_prefix=.



112
113
114
115
# File 'lib/dt.rb', line 112

def self.web_prefix=(s)
  _otf_init
  @web_prefix = s
end