rails_dt 0.1.4 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/.yardopts +2 -0
- data/Gemfile +14 -0
- data/MIT-LICENSE +1 -1
- data/README.md +43 -135
- data/lib/dt.rb +31 -215
- data/lib/dt/config.rb +74 -0
- data/lib/dt/instance.rb +117 -0
- data/lib/rails_dt.rb +3 -2
- data/lib/rails_dt/version.rb +4 -0
- data/rails_dt.gemspec +12 -50
- data/spec/lib/dt/config_spec.rb +76 -0
- data/spec/lib/dt/instance_spec.rb +173 -0
- data/spec/lib/dt_spec.rb +14 -0
- data/spec/lib/rails_dt_spec.rb +6 -0
- data/spec/lib/spec/alias_method_matcher_spec.rb +16 -0
- data/spec/lib/spec/context_when_spec.rb +32 -0
- data/spec/lib/spec/let_m_spec.rb +104 -0
- data/spec/lib/spec/use_custom_let_spec.rb +46 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/support/00extend_x.rb +23 -0
- data/spec/support/alias_method_matcher.rb +20 -0
- data/spec/support/context_when.rb +39 -0
- data/spec/support/let_m.rb +27 -0
- data/spec/support/use_custom_let.rb +80 -0
- metadata +43 -52
- data/README.html +0 -171
- data/Rakefile +0 -68
- data/VERSION.yml +0 -4
- data/generators/rails_dt/USAGE +0 -11
- data/generators/rails_dt/WARNING +0 -2
- data/generators/rails_dt/rails_dt_generator.rb +0 -9
- data/generators/rails_dt/templates/INSTALL +0 -20
- data/generators/rails_dt/templates/dt.css +0 -27
- data/generators/rails_dt/templates/dt.rb +0 -4
- data/init.rb +0 -2
- data/lib/dt/action_controller_extensions.rb +0 -29
- data/lib/generators/rails_dt/USAGE +0 -11
- data/lib/generators/rails_dt/rails_dt_generator.rb +0 -9
- data/lib/generators/rails_dt/templates/INSTALL +0 -20
- data/lib/generators/rails_dt/templates/dt.css +0 -27
- data/lib/generators/rails_dt/templates/dt.rb +0 -4
data/lib/dt/config.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
|
2
|
+
require "pathname"
|
3
|
+
|
4
|
+
require_relative "../dt"
|
5
|
+
|
6
|
+
module DT
|
7
|
+
class Config
|
8
|
+
attr_writer :env, :rails
|
9
|
+
|
10
|
+
def initialize(attrs = {})
|
11
|
+
attrs.each { |k, v| public_send("#{k}=", v) }
|
12
|
+
end
|
13
|
+
|
14
|
+
# A copy of <tt>ENV</tt> for value-reading purposes.
|
15
|
+
# @return [Hash] Default is <tt>ENV.to_h</tt>.
|
16
|
+
def env
|
17
|
+
@env ||= ENV.to_h
|
18
|
+
end
|
19
|
+
|
20
|
+
# Top-level Rails module or substitute value.
|
21
|
+
# @return [Module] <tt>Rails</tt>.
|
22
|
+
# @return [nil]
|
23
|
+
def rails
|
24
|
+
if instance_variable_defined?(k = :@rails)
|
25
|
+
instance_variable_get(k)
|
26
|
+
else
|
27
|
+
instance_variable_set(k, (Rails if defined? Rails))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# @!attribute root_path
|
32
|
+
# @return [Pathname]
|
33
|
+
def root_path
|
34
|
+
@root_path ||= begin
|
35
|
+
# 1. Fetch "raw" value, suitable as `Pathname` argument.
|
36
|
+
s = if rails
|
37
|
+
# Rails project.
|
38
|
+
rails.root
|
39
|
+
else
|
40
|
+
# Non-Rails project, attempt to guess.
|
41
|
+
if (fn = env["BUNDLE_GEMFILE"])
|
42
|
+
# The project has a Gemfile, hook it up.
|
43
|
+
File.expand_path("..", fn)
|
44
|
+
else
|
45
|
+
# Default to pwd otherwise.
|
46
|
+
Dir.pwd
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# 2. Attempt to absolutize raw path, but in a non-fatal way.
|
51
|
+
begin
|
52
|
+
# See "Implementation notes".
|
53
|
+
Pathname(s).realpath
|
54
|
+
rescue Errno::ENOENT
|
55
|
+
Pathname(s)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def root_path=(s)
|
61
|
+
@root_path = if s.is_a? Pathname
|
62
|
+
s
|
63
|
+
else
|
64
|
+
Pathname(s)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
#
|
71
|
+
# Implementation notes:
|
72
|
+
#
|
73
|
+
# * We call `Pathname` as `Pathname` to be able to stub them as own methods during testing. Other
|
74
|
+
# than that we should be using `Kernel.Pathname` which is also usable, but is more ugly.
|
data/lib/dt/instance.rb
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
|
2
|
+
require_relative "../dt"
|
3
|
+
|
4
|
+
module DT
|
5
|
+
class Instance
|
6
|
+
attr_writer \
|
7
|
+
:conf,
|
8
|
+
:dt_logger,
|
9
|
+
:is_rails_console,
|
10
|
+
:rails_logger,
|
11
|
+
:stderr
|
12
|
+
|
13
|
+
def initialize(attrs = {})
|
14
|
+
attrs.each { |k, v| public_send("#{k}=", v) }
|
15
|
+
end
|
16
|
+
|
17
|
+
# The configuration object.
|
18
|
+
# @return [Config] <tt>DT.conf</tt>.
|
19
|
+
def conf
|
20
|
+
# NOTE: See "Implementation notes".
|
21
|
+
@conf ||= DT.conf
|
22
|
+
end
|
23
|
+
|
24
|
+
# File logger, an instance of Ruby's <tt>Logger</tt>.
|
25
|
+
# @return [Logger] Default is a <tt>Logger</tt> writing to <tt>log/dt.log</tt>.
|
26
|
+
def dt_logger
|
27
|
+
if instance_variable_defined?(k = :@dt_logger)
|
28
|
+
instance_variable_get(k)
|
29
|
+
else
|
30
|
+
instance_variable_set(k, begin
|
31
|
+
Logger.new(conf.root_path + "log/dt.log")
|
32
|
+
rescue Errno::ENOENT
|
33
|
+
nil
|
34
|
+
end)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# <tt>true</tt> if running in Rails console.
|
39
|
+
# @return [Boolean]
|
40
|
+
def is_rails_console
|
41
|
+
if instance_variable_defined?(k = :@is_rails_console)
|
42
|
+
instance_variable_get(k)
|
43
|
+
else
|
44
|
+
instance_variable_set(k, conf.rails && conf.rails.const_defined?(:Console))
|
45
|
+
end
|
46
|
+
end
|
47
|
+
alias_method :rails_console?, :is_rails_console
|
48
|
+
|
49
|
+
# An object to use as log in Rails mode.
|
50
|
+
# @return [ActiveSupport::Logger] Default is <tt>conf.rails.logger</tt>.
|
51
|
+
def rails_logger
|
52
|
+
if instance_variable_defined?(k = :@rails_logger)
|
53
|
+
instance_variable_get(k)
|
54
|
+
else
|
55
|
+
instance_variable_set(k, conf.rails && conf.rails.logger)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# A writable IO stream to print to. Default is <tt>STDERR</tt>.
|
60
|
+
# @return [IO]
|
61
|
+
def stderr
|
62
|
+
@stderr ||= STDERR
|
63
|
+
end
|
64
|
+
|
65
|
+
#--------------------------------------- Actions
|
66
|
+
|
67
|
+
# Lower level implementation of <tt>p</tt>.
|
68
|
+
#
|
69
|
+
# * Print to {#dt_logger} if one is available.
|
70
|
+
# * Print to {#rails_logger} if one is available.
|
71
|
+
# * Print to {#stderr} if not running in {#rails_console?}.
|
72
|
+
#
|
73
|
+
# @param caller [Array<Array<file, line>>]
|
74
|
+
# @return nil
|
75
|
+
# @see DT.p
|
76
|
+
def _p(caller, *args)
|
77
|
+
file, line = caller[0].split(":")
|
78
|
+
file_rel = begin
|
79
|
+
Pathname(file).relative_path_from(conf.root_path)
|
80
|
+
rescue ArgumentError
|
81
|
+
# If `file` is "" or other non-path, `relative_path_from` will raise an error.
|
82
|
+
# Fall back to original value then.
|
83
|
+
file
|
84
|
+
end
|
85
|
+
|
86
|
+
args.each do |arg|
|
87
|
+
value = case arg
|
88
|
+
when String
|
89
|
+
arg
|
90
|
+
else
|
91
|
+
arg.inspect
|
92
|
+
end
|
93
|
+
|
94
|
+
msg = "[DT #{file_rel}:#{line}] #{value}"
|
95
|
+
|
96
|
+
# Fire!
|
97
|
+
dt_logger.debug(msg) if dt_logger
|
98
|
+
if rails_logger
|
99
|
+
rails_logger.debug(msg)
|
100
|
+
stderr.puts(msg) if stderr && !rails_console?
|
101
|
+
else
|
102
|
+
stderr.puts(msg) if stderr
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Be like `puts`.
|
107
|
+
nil
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
#
|
113
|
+
# Implementation notes:
|
114
|
+
#
|
115
|
+
# * `DT.conf` acts as a subsystem-wide global, all instance copies point to the same object. The
|
116
|
+
# reason for that is that it's possible that certain configuration options will be added in the
|
117
|
+
# future.
|
data/lib/rails_dt.rb
CHANGED
@@ -1,2 +1,3 @@
|
|
1
|
-
|
2
|
-
require
|
1
|
+
|
2
|
+
# Main gem require. Load all libraries.
|
3
|
+
Dir[File.expand_path("../**/*.rb", __FILE__)].each { |fn| require fn }
|
data/rails_dt.gemspec
CHANGED
@@ -1,56 +1,18 @@
|
|
1
|
-
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
-
# -*- encoding: utf-8 -*-
|
5
1
|
|
6
|
-
|
7
|
-
|
8
|
-
|
2
|
+
# TODO: Finalize.
|
3
|
+
#require_relative ""
|
4
|
+
require File.expand_path("../lib/rails_dt/version", __FILE__)
|
9
5
|
|
10
|
-
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "rails_dt"
|
8
|
+
s.version = RailsDt::VERSION
|
11
9
|
s.authors = ["Alex Fortuna"]
|
12
|
-
s.
|
13
|
-
s.
|
14
|
-
s.email = %q{alex.r@askit.org}
|
15
|
-
s.extra_rdoc_files = [
|
16
|
-
"README.html",
|
17
|
-
"README.md"
|
18
|
-
]
|
19
|
-
s.files = [
|
20
|
-
"MIT-LICENSE",
|
21
|
-
"README.html",
|
22
|
-
"README.md",
|
23
|
-
"Rakefile",
|
24
|
-
"VERSION.yml",
|
25
|
-
"generators/rails_dt/USAGE",
|
26
|
-
"generators/rails_dt/WARNING",
|
27
|
-
"generators/rails_dt/rails_dt_generator.rb",
|
28
|
-
"generators/rails_dt/templates/INSTALL",
|
29
|
-
"generators/rails_dt/templates/dt.css",
|
30
|
-
"generators/rails_dt/templates/dt.rb",
|
31
|
-
"init.rb",
|
32
|
-
"lib/dt.rb",
|
33
|
-
"lib/dt/action_controller_extensions.rb",
|
34
|
-
"lib/generators/rails_dt/USAGE",
|
35
|
-
"lib/generators/rails_dt/rails_dt_generator.rb",
|
36
|
-
"lib/generators/rails_dt/templates/INSTALL",
|
37
|
-
"lib/generators/rails_dt/templates/dt.css",
|
38
|
-
"lib/generators/rails_dt/templates/dt.rb",
|
39
|
-
"lib/rails_dt.rb",
|
40
|
-
"rails_dt.gemspec"
|
41
|
-
]
|
42
|
-
s.homepage = %q{http://github.com/dadooda/rails_dt}
|
43
|
-
s.require_paths = ["lib"]
|
44
|
-
s.rubygems_version = %q{1.6.2}
|
45
|
-
s.summary = %q{Rails Debug Toolkit}
|
10
|
+
s.email = ["fortunadze@gmail.com"]
|
11
|
+
s.homepage = "http://github.com/dadooda/rails_dt"
|
46
12
|
|
47
|
-
|
48
|
-
s.specification_version = 3
|
13
|
+
s.summary = "Ruby/Rails debug toolkit"
|
49
14
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
else
|
54
|
-
end
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.require_paths = ["lib"]
|
55
18
|
end
|
56
|
-
|
@@ -0,0 +1,76 @@
|
|
1
|
+
|
2
|
+
module DT
|
3
|
+
RSpec.describe Config do
|
4
|
+
use_custom_let(:let_a, :attrs)
|
5
|
+
|
6
|
+
let(:instance) { described_class.new(attrs) }
|
7
|
+
|
8
|
+
subject { instance.send(m) }
|
9
|
+
|
10
|
+
describe "#env" do
|
11
|
+
let_m
|
12
|
+
it { is_expected.to eq ENV.to_h }
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#rails" do
|
16
|
+
let_m
|
17
|
+
let_a(:rails)
|
18
|
+
# NOTE: We can't reliably test for constant probing since `defined?` is a language keyword.
|
19
|
+
context_when rails: :signature do
|
20
|
+
it { is_expected.to eq :signature }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#root_path" do
|
25
|
+
let_m
|
26
|
+
let(:pathname_double) { double "Pathname(raw_path)" }
|
27
|
+
let_a(:env)
|
28
|
+
let_a(:rails)
|
29
|
+
|
30
|
+
before :each do
|
31
|
+
expect(instance).to receive(:Pathname).with(raw_path).once.and_return(pathname_double)
|
32
|
+
expect(pathname_double).to receive(:realpath).once.and_return(:signature)
|
33
|
+
end
|
34
|
+
|
35
|
+
context "when Rails" do
|
36
|
+
let(:raw_path) { Pathname("/path/to/project") }
|
37
|
+
let_a(:rails) { double "rails" }
|
38
|
+
it do
|
39
|
+
expect(rails).to receive(:root).once.and_return(raw_path)
|
40
|
+
is_expected.to eq :signature
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context_when rails: nil do
|
45
|
+
context do
|
46
|
+
let(:bundle_gemfile) { self.class.bundle_gemfile }
|
47
|
+
let(:raw_path) { self.class.raw_path }
|
48
|
+
|
49
|
+
define_singleton_method(:raw_path) { "/path/to/project" }
|
50
|
+
define_singleton_method(:bundle_gemfile) { "#{raw_path}/Gemfile"}
|
51
|
+
|
52
|
+
context_when env: {"BUNDLE_GEMFILE" => bundle_gemfile } do
|
53
|
+
it { is_expected.to eq :signature }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context_when env: {} do
|
58
|
+
let(:raw_path) { Dir.pwd }
|
59
|
+
it do
|
60
|
+
subject
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end # describe "#root_path"
|
65
|
+
|
66
|
+
describe "#root_path=" do
|
67
|
+
let_a(:root_path)
|
68
|
+
|
69
|
+
subject { instance.root_path }
|
70
|
+
|
71
|
+
context_when root_path: "/some/path" do
|
72
|
+
it { is_expected.to eq Pathname("/some/path") }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,173 @@
|
|
1
|
+
|
2
|
+
module DT
|
3
|
+
RSpec.describe Instance do
|
4
|
+
use_custom_let(:let_a, :attrs)
|
5
|
+
|
6
|
+
let(:instance) { described_class.new(attrs) }
|
7
|
+
|
8
|
+
subject { instance.send(m) }
|
9
|
+
|
10
|
+
describe "attributes" do
|
11
|
+
describe "#conf" do
|
12
|
+
let_m
|
13
|
+
it do
|
14
|
+
expect(DT).to receive(:conf).once.and_return(:signature)
|
15
|
+
is_expected.to eq :signature
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#dt_logger" do
|
20
|
+
let_m
|
21
|
+
it do
|
22
|
+
expect(Logger).to receive(:new).and_return(:signature)
|
23
|
+
expect(subject).to eq :signature
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#is_rails_console" do
|
28
|
+
let_m
|
29
|
+
let_a(:conf) { double "conf" }
|
30
|
+
let(:rails_double) { double "rails" }
|
31
|
+
|
32
|
+
before :each do
|
33
|
+
expect(conf).to receive(:rails).at_least(:once).and_return(rails_double)
|
34
|
+
expect(rails_double).to receive(:const_defined?).with(:Console).and_return(is_const_defined)
|
35
|
+
end
|
36
|
+
|
37
|
+
context_when is_const_defined: true do
|
38
|
+
it { is_expected.to be true }
|
39
|
+
end
|
40
|
+
|
41
|
+
context_when is_const_defined: false do
|
42
|
+
it { is_expected.to be false }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#rails_logger" do
|
47
|
+
let_m
|
48
|
+
let_a(:conf) { double "conf" }
|
49
|
+
|
50
|
+
context "when Rails mode" do
|
51
|
+
let(:rails_double) { double "rails" }
|
52
|
+
|
53
|
+
it do
|
54
|
+
expect(conf).to receive(:rails).at_least(:once).and_return(rails_double)
|
55
|
+
expect(rails_double).to receive(:logger).and_return(:signature)
|
56
|
+
expect(subject).to eq :signature
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context "when non-Rails mode" do
|
61
|
+
it do
|
62
|
+
expect(conf).to receive(:rails).at_least(:once).and_return(nil)
|
63
|
+
expect(subject).to be nil
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "#stderr" do
|
69
|
+
let_m
|
70
|
+
it { is_expected.to eq STDERR }
|
71
|
+
end
|
72
|
+
|
73
|
+
it { expect(instance).to alias_method(:rails_console?, :is_rails_console) }
|
74
|
+
end # describe "attributes"
|
75
|
+
|
76
|
+
describe "actions" do
|
77
|
+
describe "#_p" do
|
78
|
+
let_m
|
79
|
+
|
80
|
+
let_a(:conf) { Config.new(root_path: "/some/path") }
|
81
|
+
let_a(:is_rails_console)
|
82
|
+
|
83
|
+
# Output channels.
|
84
|
+
let_a(:dt_logger) { double "dt_logger" } # "1".
|
85
|
+
let_a(:rails_logger) { double "rails_logger" } # "2".
|
86
|
+
let_a(:stderr) { double "stderr" } # This one is a "backup" output channel which pairs with `rails_logger`.
|
87
|
+
|
88
|
+
let(:args) { ["Message", {kk: 12}] }
|
89
|
+
let(:caller) do
|
90
|
+
[
|
91
|
+
"/some/path/lib/file2:20 in `method2'",
|
92
|
+
"/some/path/lib/file1:10 in `method1'",
|
93
|
+
]
|
94
|
+
end
|
95
|
+
let(:msg1) { "#{pfx} Message" }
|
96
|
+
let(:msg2) { "#{pfx} {:kk=>12}"}
|
97
|
+
let(:pfx) { "[DT lib/file2:20 in `method2']" }
|
98
|
+
|
99
|
+
subject { instance.send(m, caller, *args) }
|
100
|
+
|
101
|
+
# Disable output channels in combos to leave out just one.
|
102
|
+
# Order: dt_logger, rails_logger, stdout (via `is_rails_console`).
|
103
|
+
|
104
|
+
def expect_to_dt
|
105
|
+
expect(dt_logger).to receive(:debug).once.with(msg1)
|
106
|
+
expect(dt_logger).to receive(:debug).once.with(msg2)
|
107
|
+
end
|
108
|
+
|
109
|
+
def expect_to_rails
|
110
|
+
expect(rails_logger).to receive(:debug).once.with(msg1)
|
111
|
+
expect(rails_logger).to receive(:debug).once.with(msg2)
|
112
|
+
end
|
113
|
+
|
114
|
+
def expect_to_stderr
|
115
|
+
expect(stderr).to receive(:puts).once.with(msg1)
|
116
|
+
expect(stderr).to receive(:puts).once.with(msg2)
|
117
|
+
end
|
118
|
+
|
119
|
+
# Disable 1.
|
120
|
+
context_when dt_logger: nil do
|
121
|
+
context_when is_rails_console: true do
|
122
|
+
it do
|
123
|
+
expect_to_rails
|
124
|
+
subject
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
it do
|
129
|
+
expect_to_rails
|
130
|
+
expect_to_stderr
|
131
|
+
subject
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
# Disable 2.
|
136
|
+
context_when rails_logger: nil do
|
137
|
+
it do
|
138
|
+
expect_to_dt
|
139
|
+
expect_to_stderr
|
140
|
+
subject
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# Disable 1 and 2.
|
145
|
+
context_when dt_logger: nil, rails_logger: nil do
|
146
|
+
it do
|
147
|
+
expect_to_stderr
|
148
|
+
subject
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
# Disable all.
|
153
|
+
context_when dt_logger: nil, rails_logger: nil, stderr: nil do
|
154
|
+
it "generally works" do
|
155
|
+
# Just expect nothing to crash by using `nil`.
|
156
|
+
# RSpec negative expectations are warned against (which I think is right).
|
157
|
+
subject
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
# Generic case, all channels enabled.
|
162
|
+
context_when is_rails_console: false do
|
163
|
+
it do
|
164
|
+
expect_to_dt
|
165
|
+
expect_to_rails
|
166
|
+
expect_to_stderr
|
167
|
+
subject
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|