merb_inspector 0.3.2
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.
- data/LICENSE +20 -0
- data/README +39 -0
- data/Rakefile +51 -0
- data/TODO +5 -0
- data/inspectors/array.rb +5 -0
- data/inspectors/basic.rb +4 -0
- data/inspectors/data_mapper.rb +172 -0
- data/inspectors/hash.rb +5 -0
- data/inspectors/mongo_mapper.rb +153 -0
- data/inspectors/object.rb +11 -0
- data/lib/merb_inspector.rb +30 -0
- data/lib/merb_inspector/builtin.rb +14 -0
- data/lib/merb_inspector/data.rb +129 -0
- data/lib/merb_inspector/helper.rb +42 -0
- data/lib/merb_inspector/inspector.rb +148 -0
- data/lib/merb_inspector/manager.rb +99 -0
- data/lib/merb_inspector/merbtasks.rb +6 -0
- data/mirror/public/stylesheets/merb_inspector.css +91 -0
- data/spec/merb_inspector_spec.rb +7 -0
- data/spec/spec_helper.rb +1 -0
- data/templates/_default.html.erb +1 -0
- data/templates/array/_default.html.erb +18 -0
- data/templates/basic/_default.html.erb +1 -0
- data/templates/data_mapper/collection/_records.html.erb +29 -0
- data/templates/data_mapper/resource/_record.html.erb +41 -0
- data/templates/hash/_default.html.erb +19 -0
- data/templates/mongo_mapper/document/_record.html.erb +41 -0
- data/templates/object/_default.html.erb +19 -0
- data/templates/object/_plain.html.erb +1 -0
- metadata +94 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008 Maiha <maiha@wota.jp>
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
merb_inspector
|
2
|
+
==============
|
3
|
+
|
4
|
+
A plugin for the Merb framework that provides "inspect" helper.
|
5
|
+
Just inspect your objects! No longer need to prepare views, scaffold and pagination.
|
6
|
+
|
7
|
+
|
8
|
+
Setup
|
9
|
+
=====
|
10
|
+
|
11
|
+
1. load gem at the bottom of config/dependencies.rb
|
12
|
+
|
13
|
+
require "merb_inspector"
|
14
|
+
|
15
|
+
2. include css and js in your view or layout files
|
16
|
+
|
17
|
+
<%= css_include_tag "merb_inspector.css" -%>
|
18
|
+
<%= js_include_tag "jquery.js" -%>
|
19
|
+
|
20
|
+
|
21
|
+
Example
|
22
|
+
=======
|
23
|
+
|
24
|
+
just *inspect* the object you want to know!
|
25
|
+
|
26
|
+
<%= inspect [1, :hello] %>
|
27
|
+
<%= inspect ENV.to_hash %>
|
28
|
+
<%= inspect User.all(:limit=>10) %>
|
29
|
+
<%= inspect @item %>
|
30
|
+
...
|
31
|
+
|
32
|
+
of course you can see available inspectors as following
|
33
|
+
|
34
|
+
<%= inspect Merb::Inspector::Manager.stores %>
|
35
|
+
|
36
|
+
|
37
|
+
Copyright (c) 2008 maiha@wota.jp, released under the MIT license
|
38
|
+
|
39
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake/gempackagetask'
|
3
|
+
|
4
|
+
require 'merb-core'
|
5
|
+
require 'merb-core/tasks/merb'
|
6
|
+
|
7
|
+
GEM_NAME = "merb_inspector"
|
8
|
+
GEM_VERSION = "0.3.2"
|
9
|
+
AUTHOR = "Maiha"
|
10
|
+
EMAIL = "maiha@wota.jp"
|
11
|
+
HOMEPAGE = "http://github.com/maiha/merb_inspector"
|
12
|
+
SUMMARY = "Merb plugin that provides powerful 'inspect' helper method"
|
13
|
+
|
14
|
+
spec = Gem::Specification.new do |s|
|
15
|
+
s.rubyforge_project = 'merb'
|
16
|
+
s.name = GEM_NAME
|
17
|
+
s.version = GEM_VERSION
|
18
|
+
s.platform = Gem::Platform::RUBY
|
19
|
+
s.has_rdoc = true
|
20
|
+
s.extra_rdoc_files = ["README", "LICENSE", 'TODO']
|
21
|
+
s.summary = SUMMARY
|
22
|
+
s.description = s.summary
|
23
|
+
s.author = AUTHOR
|
24
|
+
s.email = EMAIL
|
25
|
+
s.homepage = HOMEPAGE
|
26
|
+
s.add_dependency('merb', '>= 1.0.8')
|
27
|
+
s.require_path = 'lib'
|
28
|
+
s.files = %w(LICENSE README Rakefile TODO) + Dir.glob("{lib,spec,inspectors,templates,mirror}/**/*")
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
33
|
+
pkg.gem_spec = spec
|
34
|
+
end
|
35
|
+
|
36
|
+
desc "install the plugin as a gem"
|
37
|
+
task :install do
|
38
|
+
Merb::RakeHelper.install(GEM_NAME, :version => GEM_VERSION)
|
39
|
+
end
|
40
|
+
|
41
|
+
desc "Uninstall the gem"
|
42
|
+
task :uninstall do
|
43
|
+
Merb::RakeHelper.uninstall(GEM_NAME, :version => GEM_VERSION)
|
44
|
+
end
|
45
|
+
|
46
|
+
desc "Create a gemspec file"
|
47
|
+
task :gemspec do
|
48
|
+
File.open("#{GEM_NAME}.gemspec", "w") do |file|
|
49
|
+
file.puts spec.to_ruby
|
50
|
+
end
|
51
|
+
end
|
data/TODO
ADDED
data/inspectors/array.rb
ADDED
data/inspectors/basic.rb
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
class DataMapper::ResourceInspector < Merb::Inspector
|
2
|
+
builtin
|
3
|
+
model ::DataMapper::Resource
|
4
|
+
|
5
|
+
def edit(object, options = {})
|
6
|
+
@object = object
|
7
|
+
@options = options
|
8
|
+
@mode = :edit
|
9
|
+
|
10
|
+
execute
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
def model
|
15
|
+
@object.class
|
16
|
+
end
|
17
|
+
|
18
|
+
def klass
|
19
|
+
@object.class
|
20
|
+
end
|
21
|
+
|
22
|
+
def columns
|
23
|
+
@columns ||= build_columns
|
24
|
+
end
|
25
|
+
|
26
|
+
def dom_id
|
27
|
+
oid = @object.new_record? ? "new" : @object.id
|
28
|
+
"#{resource_name}-#{oid}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def template
|
32
|
+
if @options[:action].to_s == 'new'
|
33
|
+
"new"
|
34
|
+
else
|
35
|
+
"record"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def save_action
|
40
|
+
if @object.new_record?
|
41
|
+
"/" + resource_name
|
42
|
+
else
|
43
|
+
resource(@object)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def options
|
48
|
+
{:model=>model, :record=>@object, :save_action=>save_action, :toggle=>toggle}
|
49
|
+
end
|
50
|
+
|
51
|
+
######################################################################
|
52
|
+
### Resourceful
|
53
|
+
|
54
|
+
def resource_name
|
55
|
+
Extlib::Inflection.demodulize(model.name).plural.snake_case
|
56
|
+
end
|
57
|
+
|
58
|
+
def link_to_new(label = 'New', opts = {})
|
59
|
+
link_to label, resource(resource_name, :new), opts
|
60
|
+
rescue Merb::Router::GenerationError
|
61
|
+
end
|
62
|
+
|
63
|
+
def show_link_value(record, p, opts = {})
|
64
|
+
opts[:label] ||= "Show"
|
65
|
+
link_to opts[:label], resource(record), opts
|
66
|
+
rescue Merb::Router::GenerationError
|
67
|
+
end
|
68
|
+
|
69
|
+
def edit_link_value(record, p, opts = {})
|
70
|
+
opts[:label] ||= "Edit"
|
71
|
+
link_to opts[:label], resource(record, :edit), opts
|
72
|
+
rescue Merb::Router::GenerationError
|
73
|
+
end
|
74
|
+
|
75
|
+
def delete_link_value(record, p, opts = {})
|
76
|
+
opts[:label] ||= "Delete"
|
77
|
+
link_to opts[:label], resource(record, :delete), opts
|
78
|
+
rescue Merb::Router::GenerationError
|
79
|
+
end
|
80
|
+
|
81
|
+
######################################################################
|
82
|
+
### form builder for DataMapper
|
83
|
+
|
84
|
+
def default_columns
|
85
|
+
[LinkColumn.new(self, :show), LinkColumn.new(self, :edit)]
|
86
|
+
end
|
87
|
+
|
88
|
+
def find_column_by_name(name)
|
89
|
+
name = name.to_s.intern
|
90
|
+
(klass.properties.to_a + default_columns).each do |col|
|
91
|
+
return col if col.name == name
|
92
|
+
end
|
93
|
+
return nil
|
94
|
+
end
|
95
|
+
|
96
|
+
def build_columns
|
97
|
+
if @options[:only]
|
98
|
+
valids = Array(@options[:only]).flatten.compact.map(&:to_sym)
|
99
|
+
cols = valids.map{|name| find_column_by_name(name) || name}
|
100
|
+
else
|
101
|
+
cols = klass.properties.to_a + default_columns
|
102
|
+
if @options[:except]
|
103
|
+
invalids = Array(@options[:except]).flatten.compact.map(&:to_sym)
|
104
|
+
cols = cols.reject{|col| invalids.include?(col.name)}
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
cols.map do |col|
|
109
|
+
case col
|
110
|
+
when ::DataMapper::Property
|
111
|
+
DMColumn.new(self, col)
|
112
|
+
when Column
|
113
|
+
col
|
114
|
+
else
|
115
|
+
VirtualColumn.new(self, col)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def column_label(column)
|
121
|
+
column.label
|
122
|
+
end
|
123
|
+
|
124
|
+
def column_value(record, column)
|
125
|
+
column.value(record)
|
126
|
+
rescue Column::MethodFound => e
|
127
|
+
__send__ *e.args
|
128
|
+
rescue Column::NotDefined => e
|
129
|
+
call_user_method(e.message, record, column)
|
130
|
+
end
|
131
|
+
|
132
|
+
def column_form(record, column)
|
133
|
+
column.form(record)
|
134
|
+
rescue Column::MethodFound => e
|
135
|
+
__send__ *e.args
|
136
|
+
rescue Column::NotDefined => e
|
137
|
+
call_user_method(e.message, record, column)
|
138
|
+
end
|
139
|
+
|
140
|
+
def call_user_method(method, record, column)
|
141
|
+
method = method.to_sym
|
142
|
+
block = @options[:columns][method] rescue nil
|
143
|
+
if block
|
144
|
+
block.call(record, column)
|
145
|
+
else
|
146
|
+
"[VirtualColumn] '#{method}' is not defined yet"
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
|
152
|
+
class DataMapper::CollectionInspector < DataMapper::ResourceInspector
|
153
|
+
builtin
|
154
|
+
model ::DataMapper::Collection, ::DataMapper::Associations::OneToMany::Proxy
|
155
|
+
|
156
|
+
private
|
157
|
+
def model
|
158
|
+
@object.query.model
|
159
|
+
end
|
160
|
+
|
161
|
+
def klass
|
162
|
+
@object
|
163
|
+
end
|
164
|
+
|
165
|
+
def options
|
166
|
+
{:model=>model, :records=>@object}
|
167
|
+
end
|
168
|
+
|
169
|
+
def template
|
170
|
+
"records"
|
171
|
+
end
|
172
|
+
end
|
data/inspectors/hash.rb
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
class MongoMapper::DocumentInspector < Merb::Inspector
|
2
|
+
builtin
|
3
|
+
model ::MongoMapper::Document
|
4
|
+
|
5
|
+
def edit(object, options = {})
|
6
|
+
@object = object
|
7
|
+
@options = options
|
8
|
+
@mode = :edit
|
9
|
+
|
10
|
+
execute
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
def model
|
15
|
+
@object.class
|
16
|
+
end
|
17
|
+
|
18
|
+
def klass
|
19
|
+
@object.class
|
20
|
+
end
|
21
|
+
|
22
|
+
def columns
|
23
|
+
@columns ||= build_columns
|
24
|
+
end
|
25
|
+
|
26
|
+
def dom_id
|
27
|
+
oid = @object.new_record? ? "new" : @object.id
|
28
|
+
"#{resource_name}-#{oid}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def template
|
32
|
+
if @options[:action].to_s == 'new'
|
33
|
+
"new"
|
34
|
+
else
|
35
|
+
"record"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def save_action
|
40
|
+
if @object.new_record?
|
41
|
+
"/" + resource_name
|
42
|
+
else
|
43
|
+
resource(@object)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def options
|
48
|
+
{:model=>model, :record=>@object, :save_action=>save_action, :toggle=>toggle}
|
49
|
+
end
|
50
|
+
|
51
|
+
######################################################################
|
52
|
+
### Resourceful
|
53
|
+
|
54
|
+
def resource_name
|
55
|
+
Extlib::Inflection.demodulize(model.name).plural.snake_case
|
56
|
+
end
|
57
|
+
|
58
|
+
def link_to_new(label = 'New', opts = {})
|
59
|
+
link_to label, resource(resource_name, :new), opts
|
60
|
+
rescue Merb::Router::GenerationError
|
61
|
+
end
|
62
|
+
|
63
|
+
def show_link_value(record, p, opts = {})
|
64
|
+
opts[:label] ||= "Show"
|
65
|
+
link_to opts[:label], resource(record), opts
|
66
|
+
rescue Merb::Router::GenerationError
|
67
|
+
end
|
68
|
+
|
69
|
+
def edit_link_value(record, p, opts = {})
|
70
|
+
opts[:label] ||= "Edit"
|
71
|
+
link_to opts[:label], resource(record, :edit), opts
|
72
|
+
rescue Merb::Router::GenerationError
|
73
|
+
end
|
74
|
+
|
75
|
+
def delete_link_value(record, p, opts = {})
|
76
|
+
opts[:label] ||= "Delete"
|
77
|
+
link_to opts[:label], resource(record, :delete), opts
|
78
|
+
rescue Merb::Router::GenerationError
|
79
|
+
end
|
80
|
+
|
81
|
+
######################################################################
|
82
|
+
### form builder for DataMapper
|
83
|
+
|
84
|
+
def default_columns
|
85
|
+
[LinkColumn.new(self, :show), LinkColumn.new(self, :edit)]
|
86
|
+
end
|
87
|
+
|
88
|
+
def all_columns
|
89
|
+
default_columns
|
90
|
+
end
|
91
|
+
|
92
|
+
def find_column_by_name(name)
|
93
|
+
name = name.to_s.intern
|
94
|
+
all_columns.each do |col|
|
95
|
+
return col if col.name == name
|
96
|
+
end
|
97
|
+
return nil
|
98
|
+
end
|
99
|
+
|
100
|
+
def build_columns
|
101
|
+
if @options[:only]
|
102
|
+
valids = Array(@options[:only]).flatten.compact.map(&:to_sym)
|
103
|
+
cols = valids.map{|name| find_column_by_name(name) || name}
|
104
|
+
else
|
105
|
+
cols = all_columns
|
106
|
+
if @options[:except]
|
107
|
+
invalids = Array(@options[:except]).flatten.compact.map(&:to_sym)
|
108
|
+
cols = cols.reject{|col| invalids.include?(col.name)}
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
cols.map do |col|
|
113
|
+
case col
|
114
|
+
when ::DataMapper::Property
|
115
|
+
DMColumn.new(self, col)
|
116
|
+
when Column
|
117
|
+
col
|
118
|
+
else
|
119
|
+
VirtualColumn.new(self, col)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def column_label(column)
|
125
|
+
column.label
|
126
|
+
end
|
127
|
+
|
128
|
+
def column_value(record, column)
|
129
|
+
column.value(record)
|
130
|
+
rescue Column::MethodFound => e
|
131
|
+
__send__ *e.args
|
132
|
+
rescue Column::NotDefined => e
|
133
|
+
call_user_method(e.message, record, column)
|
134
|
+
end
|
135
|
+
|
136
|
+
def column_form(record, column)
|
137
|
+
column.form(record)
|
138
|
+
rescue Column::MethodFound => e
|
139
|
+
__send__ *e.args
|
140
|
+
rescue Column::NotDefined => e
|
141
|
+
call_user_method(e.message, record, column)
|
142
|
+
end
|
143
|
+
|
144
|
+
def call_user_method(method, record, column)
|
145
|
+
method = method.to_sym
|
146
|
+
block = @options[:columns][method] rescue nil
|
147
|
+
if block
|
148
|
+
block.call(record, column)
|
149
|
+
else
|
150
|
+
"[VirtualColumn] '#{method}' is not defined yet"
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# make sure we're running inside Merb
|
2
|
+
if defined?(Merb::Plugins)
|
3
|
+
|
4
|
+
$: << File.dirname(__FILE__) unless $:.include?(File.dirname(__FILE__))
|
5
|
+
|
6
|
+
# Merb gives you a Merb::Plugins.config hash...feel free to put your stuff in your piece of it
|
7
|
+
Merb::Plugins.config[:merb_inspector] = {
|
8
|
+
:chickens => false
|
9
|
+
}
|
10
|
+
|
11
|
+
Merb::BootLoader.before_app_loads do
|
12
|
+
require "merb_inspector" / "inspector"
|
13
|
+
require "merb_inspector" / "data"
|
14
|
+
require "merb_inspector" / "builtin"
|
15
|
+
require "merb_inspector" / "manager"
|
16
|
+
require "merb_inspector" / "helper"
|
17
|
+
|
18
|
+
Merb::Inspector::Manager.reset
|
19
|
+
Merb::Inspector::Manager.install
|
20
|
+
end
|
21
|
+
|
22
|
+
Merb::BootLoader.after_app_loads do
|
23
|
+
|
24
|
+
# class ::Application
|
25
|
+
# include Merb::Inspector::Helper
|
26
|
+
# end
|
27
|
+
end
|
28
|
+
|
29
|
+
Merb::Plugins.add_rakefiles "merb_inspector/merbtasks"
|
30
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
module Merb
|
2
|
+
class Inspector
|
3
|
+
class Column # Abstract
|
4
|
+
class Delegate < StandardError; end
|
5
|
+
class NotDefined < Delegate; end
|
6
|
+
class MethodFound < Delegate
|
7
|
+
attr_reader :args
|
8
|
+
def initialize(*args)
|
9
|
+
@args = args
|
10
|
+
super("method delegation")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_accessor :context, :name
|
15
|
+
|
16
|
+
def initialize(context, name)
|
17
|
+
@context = context
|
18
|
+
@name = name.to_s.intern
|
19
|
+
end
|
20
|
+
|
21
|
+
def label(*)
|
22
|
+
name
|
23
|
+
end
|
24
|
+
|
25
|
+
def value(record)
|
26
|
+
# first, search class prefixed method that user override
|
27
|
+
evaluate(record, "#{Extlib::Inflection.demodulize(record.class.name)}_#{name}_value")
|
28
|
+
|
29
|
+
# second, search method that user override
|
30
|
+
evaluate(record, "#{name}_value")
|
31
|
+
|
32
|
+
# finally, guess form from property type
|
33
|
+
default_value(record)
|
34
|
+
end
|
35
|
+
|
36
|
+
def form(record)
|
37
|
+
# first, search class prefixed method that user override
|
38
|
+
evaluate(record, "#{Extlib::Inflection.demodulize(record.class.name)}_#{name}_form")
|
39
|
+
|
40
|
+
# second, search method that user override
|
41
|
+
evaluate(record, "#{name}_form")
|
42
|
+
|
43
|
+
# finally, guess form from property type
|
44
|
+
default_form(record)
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
def h(str)
|
49
|
+
context.h(str)
|
50
|
+
end
|
51
|
+
|
52
|
+
def evaluate(record, method)
|
53
|
+
raise MethodFound.new(method, record, self) if context.respond_to?(method, true)
|
54
|
+
end
|
55
|
+
|
56
|
+
def default_value(record)
|
57
|
+
raise NotImplementedError
|
58
|
+
end
|
59
|
+
|
60
|
+
def default_form(record)
|
61
|
+
raise NotImplementedError
|
62
|
+
end
|
63
|
+
|
64
|
+
def not_defined(method)
|
65
|
+
raise NotDefined, method
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
class DMColumn < Column
|
70
|
+
def initialize(context, property)
|
71
|
+
@context = context
|
72
|
+
@property = property
|
73
|
+
end
|
74
|
+
|
75
|
+
def name
|
76
|
+
@property.name.to_s
|
77
|
+
end
|
78
|
+
|
79
|
+
def type
|
80
|
+
@property.type
|
81
|
+
end
|
82
|
+
|
83
|
+
def default_value(record)
|
84
|
+
value = record.send(name)
|
85
|
+
if type == ::DataMapper::Types::Text
|
86
|
+
value.to_s.split(/\r?\n/).map{|i| h(i.to_s)}.join("<BR>")
|
87
|
+
else
|
88
|
+
h(value.to_s)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def default_form(record)
|
93
|
+
if type == ::DataMapper::Types::Serial
|
94
|
+
record.send name
|
95
|
+
elsif type == ::DataMapper::Types::Text
|
96
|
+
raise MethodFound.new(:text_area, name.to_sym)
|
97
|
+
else
|
98
|
+
raise MethodFound.new(:text_field, name.to_sym)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
class VirtualColumn < Column
|
104
|
+
def default_value(record)
|
105
|
+
not_defined("#{name}_value")
|
106
|
+
end
|
107
|
+
|
108
|
+
def default_form(record)
|
109
|
+
not_defined("#{name}_form")
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
class LinkColumn < Column
|
114
|
+
def default_value(record)
|
115
|
+
evaluate(record, "#{name}_link_value")
|
116
|
+
not_defined("#{name}_link_value")
|
117
|
+
end
|
118
|
+
|
119
|
+
def default_form(record)
|
120
|
+
evaluate(record, "#{name}_link_form")
|
121
|
+
not_defined("#{name}_link_form")
|
122
|
+
end
|
123
|
+
|
124
|
+
def label
|
125
|
+
nil
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Merb
|
2
|
+
class Inspector
|
3
|
+
module Helper
|
4
|
+
def inspect(*args)
|
5
|
+
return h(super()) if args.blank?
|
6
|
+
object = args.shift
|
7
|
+
options = args.shift || {}
|
8
|
+
|
9
|
+
unless options.is_a?(Hash)
|
10
|
+
action = options.to_s
|
11
|
+
options = args.shift || {}
|
12
|
+
options[:action] = action
|
13
|
+
end
|
14
|
+
options[:action] ||= :show
|
15
|
+
options[:level] ||= 1
|
16
|
+
options[:max_level] ||= 3
|
17
|
+
|
18
|
+
# validate keys
|
19
|
+
valid_keys = [:action, :level, :max_level, :only, :except, :columns, :lead]
|
20
|
+
unknown_keys = options.keys - valid_keys
|
21
|
+
if !unknown_keys.blank?
|
22
|
+
return h("[INSPECTOR ERROR] Unknown key(s): %s" % unknown_keys.inspect)
|
23
|
+
end
|
24
|
+
|
25
|
+
inspector_class = BasicInspector if options[:level] >= options[:max_level]
|
26
|
+
inspector_class ||= Manager.lookup(object) || Merb::Inspector.default
|
27
|
+
|
28
|
+
inspector = inspector_class.new(Merb::Request.new({}))
|
29
|
+
if inspector.respond_to?(options[:action])
|
30
|
+
inspector.send options[:action], object, options
|
31
|
+
else
|
32
|
+
message = "%s doesn't recognize '%s' action" % [inspector.class, options[:action]]
|
33
|
+
raise Merb::Inspector::ActionNotFound, message
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class Merb::Controller
|
41
|
+
include Merb::Inspector::Helper
|
42
|
+
end
|
@@ -0,0 +1,148 @@
|
|
1
|
+
module Merb
|
2
|
+
class Inspector < Merb::Controller
|
3
|
+
######################################################################
|
4
|
+
### for exceptins
|
5
|
+
|
6
|
+
class Merb::Inspector::ActionNotFound < Merb::ControllerExceptions::ActionNotFound; end
|
7
|
+
|
8
|
+
######################################################################
|
9
|
+
### for module
|
10
|
+
|
11
|
+
def self.root
|
12
|
+
@root ||= Pathname(File.expand_path(File.dirname(__FILE__) + "/../../"))
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.default
|
16
|
+
ObjectInspector
|
17
|
+
end
|
18
|
+
|
19
|
+
######################################################################
|
20
|
+
### for class
|
21
|
+
|
22
|
+
def self.model(*models)
|
23
|
+
models.each do |model|
|
24
|
+
Merb::Inspector::Manager.register(model, self)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.builtin
|
29
|
+
include Merb::Inspector::Builtin
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.lead(options = {})
|
33
|
+
@lead_options = options
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.lead_options
|
37
|
+
@lead_options
|
38
|
+
end
|
39
|
+
|
40
|
+
def show(object, options = {})
|
41
|
+
@object = object
|
42
|
+
@options = options
|
43
|
+
|
44
|
+
execute
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
def name
|
49
|
+
self.class.name.sub(/^Merb::/,'').sub(/Inspector$/,'').snake_case.gsub(/::/, '/')
|
50
|
+
end
|
51
|
+
|
52
|
+
def dom_id
|
53
|
+
@object.class.name.plural.snake_case.gsub(/::/,'-') + '-' + @object.object_id.to_s
|
54
|
+
end
|
55
|
+
|
56
|
+
def toggle
|
57
|
+
"$('##{dom_id} > .reversible').toggle();return false;"
|
58
|
+
end
|
59
|
+
|
60
|
+
def template_for(name)
|
61
|
+
name.to_s
|
62
|
+
end
|
63
|
+
|
64
|
+
def main
|
65
|
+
partial template_for(template), current_options
|
66
|
+
end
|
67
|
+
|
68
|
+
def execute
|
69
|
+
if lead?
|
70
|
+
wrapped_main
|
71
|
+
else
|
72
|
+
main
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def close_lead_label
|
77
|
+
"[x]"
|
78
|
+
end
|
79
|
+
|
80
|
+
def lead_size
|
81
|
+
sizes = Array((self.class.lead_options || {})[:size]).compact
|
82
|
+
sizes[level-1] || sizes[-1] || 15
|
83
|
+
end
|
84
|
+
|
85
|
+
def lead?
|
86
|
+
case @options[:lead]
|
87
|
+
when NilClass
|
88
|
+
self.class.lead_options
|
89
|
+
else
|
90
|
+
!! @options[:lead]
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def lead
|
95
|
+
"<span class=nowrap>%s</span>" % h(@object.inspect.truncate(lead_size))
|
96
|
+
end
|
97
|
+
|
98
|
+
def link_to_lead
|
99
|
+
link_to close_lead_label, "#", :onclick=>toggle
|
100
|
+
end
|
101
|
+
|
102
|
+
def link_to_main
|
103
|
+
link_to lead, "#", :onclick=>toggle
|
104
|
+
end
|
105
|
+
|
106
|
+
def template
|
107
|
+
:default
|
108
|
+
end
|
109
|
+
|
110
|
+
def current_options
|
111
|
+
basic_options.merge(options)
|
112
|
+
end
|
113
|
+
|
114
|
+
def options
|
115
|
+
{}
|
116
|
+
end
|
117
|
+
|
118
|
+
def level
|
119
|
+
@options[:level]
|
120
|
+
end
|
121
|
+
|
122
|
+
def basic_options
|
123
|
+
{:options=>@options, :level=>level}
|
124
|
+
end
|
125
|
+
|
126
|
+
def child_options
|
127
|
+
{:level=>@options[:level]+1, :max_level=>@options[:max_level]}
|
128
|
+
end
|
129
|
+
|
130
|
+
def wrapped_main
|
131
|
+
<<-HTML
|
132
|
+
<div id="#{dom_id}">
|
133
|
+
<div id="#{dom_id}_lead" class="reversible" style="display:block;">
|
134
|
+
#{link_to_main}
|
135
|
+
</div>
|
136
|
+
<div id="#{dom_id}_main" class="reversible" style="display:none;">
|
137
|
+
<div style="float:right;">#{link_to_lead}</div>
|
138
|
+
#{main}
|
139
|
+
</div>
|
140
|
+
</div>
|
141
|
+
HTML
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def self.inspector
|
146
|
+
Merb::Inspector
|
147
|
+
end
|
148
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module Merb
|
2
|
+
class Inspector
|
3
|
+
module Manager
|
4
|
+
######################################################################
|
5
|
+
### for module
|
6
|
+
|
7
|
+
class << self
|
8
|
+
attr_accessor :stores
|
9
|
+
attr_accessor :caches
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.reset
|
13
|
+
self.stores = Hash.new
|
14
|
+
self.caches = Hash.new
|
15
|
+
|
16
|
+
log = Merb.root / "log" / "inspector.log"
|
17
|
+
File.unlink log if File.exist?(log)
|
18
|
+
load_builtin_inspectors
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.load_builtin_inspectors
|
22
|
+
inspector_dir = File.dirname(__FILE__) / "../../inspectors"
|
23
|
+
Dir["#{inspector_dir}/*.rb"].sort.each do |file|
|
24
|
+
begin
|
25
|
+
require file
|
26
|
+
rescue Exception => error
|
27
|
+
message = "[MerbInspector] load error: #{error} (#{error.class})\n#{error.backtraces.first rescue nil}"
|
28
|
+
Merb.logger.error message
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.log(message)
|
34
|
+
path = Merb.root / "log" / "inspector.log"
|
35
|
+
message = "[Inspector] %s" % message.to_s.strip
|
36
|
+
File.open(path, "a+") {|f| f.puts message}
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.register(klass, inspector)
|
40
|
+
action = stores.has_key?(klass) ? "overridden" : "registered"
|
41
|
+
stores[klass] = inspector
|
42
|
+
log "%s %s -> %s" % [action, klass, inspector]
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.lookup(object)
|
46
|
+
# first, search object itself for mainly class stuff
|
47
|
+
if stores.has_key?(object)
|
48
|
+
log "lookup: %s => %s" % [object, stores[object]]
|
49
|
+
return stores[object]
|
50
|
+
end
|
51
|
+
|
52
|
+
# second, search its class
|
53
|
+
if caches.has_key?(object.class)
|
54
|
+
log "lookup: %s => %s (cached)" % [object.class, caches[object.class] || 'nil']
|
55
|
+
return caches[object.class]
|
56
|
+
end
|
57
|
+
|
58
|
+
# finally, search ancestors of the class
|
59
|
+
klass = object.class.ancestors.find{|klass|
|
60
|
+
log "lookup: %s = %s ... %s" % [object.class, klass, stores[klass]]
|
61
|
+
stores.has_key?(klass)
|
62
|
+
}
|
63
|
+
caches[object.class] = stores[klass]
|
64
|
+
if klass
|
65
|
+
log "lookup: %s => %s (registered)" % [object.class, caches[object.class]]
|
66
|
+
else
|
67
|
+
log "lookup: %s => nil (registered as negative cache)" % [object.class]
|
68
|
+
end
|
69
|
+
return stores[klass]
|
70
|
+
end
|
71
|
+
|
72
|
+
######################################################################
|
73
|
+
### Install
|
74
|
+
|
75
|
+
def self.install
|
76
|
+
mirror("public/stylesheets")
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.mirror(dir)
|
80
|
+
source_dir = File.join(File.dirname(__FILE__), '..', '..', 'mirror', dir)
|
81
|
+
target_dir = File.join(Merb.root, dir)
|
82
|
+
FileUtils.mkdir_p(target_dir) unless File.exist?(target_dir)
|
83
|
+
|
84
|
+
Dir[source_dir + "/*"].each do |src|
|
85
|
+
time = File.mtime(src)
|
86
|
+
file = File.basename(src)
|
87
|
+
dst = File.join(target_dir, file)
|
88
|
+
|
89
|
+
next if File.directory?(src)
|
90
|
+
next if File.exist?(dst) and File.mtime(dst) >= time
|
91
|
+
FileUtils.copy(src, dst)
|
92
|
+
File.utime(time, time, dst)
|
93
|
+
command = File.exist?(dst) ? "update" : "install"
|
94
|
+
log "#{command}: #{dir}/#{file}"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
span.nowrap {
|
2
|
+
white-space: nowrap;
|
3
|
+
}
|
4
|
+
|
5
|
+
table.inspector {
|
6
|
+
border-collapse:collapse;
|
7
|
+
}
|
8
|
+
|
9
|
+
|
10
|
+
table.inspector th {
|
11
|
+
background-color: #555;
|
12
|
+
text-align: left;
|
13
|
+
}
|
14
|
+
|
15
|
+
table.inspector th a,
|
16
|
+
table.inspector th p {
|
17
|
+
font: bold 11px arial, sans-serif;
|
18
|
+
display: block;
|
19
|
+
background-color: #555;
|
20
|
+
}
|
21
|
+
|
22
|
+
table.inspector th a {
|
23
|
+
color: #fff;
|
24
|
+
padding: 2px 15px 2px 5px;
|
25
|
+
}
|
26
|
+
|
27
|
+
table.inspector th p {
|
28
|
+
color: #eee;
|
29
|
+
padding: 2px 5px;
|
30
|
+
}
|
31
|
+
|
32
|
+
table.inspector th a:hover {
|
33
|
+
background-color: #000;
|
34
|
+
color: #ff8;
|
35
|
+
}
|
36
|
+
|
37
|
+
table.inspector > tbody > tr.record td {
|
38
|
+
background-color: #E6F2FF;
|
39
|
+
}
|
40
|
+
|
41
|
+
table.inspector > tbody > tr.record > td {
|
42
|
+
padding: 5px 4px;
|
43
|
+
color: #333;
|
44
|
+
font-family: Verdana, sans-serif;
|
45
|
+
font-size: 11px;
|
46
|
+
border-bottom: solid 1px #C5DBF7;
|
47
|
+
border-left: solid 1px #C5DBF7;
|
48
|
+
}
|
49
|
+
|
50
|
+
table.inspector > tbody > tr.even-record td {
|
51
|
+
background-color: #fff;
|
52
|
+
}
|
53
|
+
|
54
|
+
table.inspector > tbody > tr.even-record > td {
|
55
|
+
border-left: solid 1px #ddd;
|
56
|
+
}
|
57
|
+
|
58
|
+
table.inspector > tbody > tr.record > td.sorted {
|
59
|
+
background-color: #B9DCFF;
|
60
|
+
border-bottom: solid 1px #AFD0F5;
|
61
|
+
}
|
62
|
+
|
63
|
+
table.inspector > tbody > tr.even-record > td.sorted {
|
64
|
+
background-color: #E6F2FF;
|
65
|
+
border-bottom: solid 1px #AFD0F5;
|
66
|
+
}
|
67
|
+
|
68
|
+
|
69
|
+
|
70
|
+
.record table
|
71
|
+
{
|
72
|
+
background-color: #fff;
|
73
|
+
border-collapse: collapse;
|
74
|
+
border-spacing: 0px;
|
75
|
+
}
|
76
|
+
.record table th
|
77
|
+
{
|
78
|
+
background-color: #dee7ec;
|
79
|
+
border: 1px solid #8cacbb;
|
80
|
+
padding: 3px;
|
81
|
+
}
|
82
|
+
.record table td
|
83
|
+
{
|
84
|
+
border: 1px solid #8cacbb;
|
85
|
+
padding: 3px;
|
86
|
+
}
|
87
|
+
|
88
|
+
table.logical th,
|
89
|
+
table.logical td {
|
90
|
+
border: 0px;
|
91
|
+
}
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
$:.push File.join(File.dirname(__FILE__), '..', 'lib')
|
@@ -0,0 +1 @@
|
|
1
|
+
<%=h @object.inspect %>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<table class="inspector">
|
2
|
+
<tr>
|
3
|
+
<th><p>index</p></th>
|
4
|
+
<th><p>value</p></th>
|
5
|
+
<th><p>type</p></th>
|
6
|
+
</tr>
|
7
|
+
<%- @object.each_with_index do |obj, i| -%>
|
8
|
+
<%-
|
9
|
+
tr_class = (i % 2 == 0) ? "even-record" : ""
|
10
|
+
tr_class += " #{list_row_class(obj)}" if respond_to? :list_row_class
|
11
|
+
-%>
|
12
|
+
<tr class="record <%=tr_class%>">
|
13
|
+
<td align=center><%=i+1%></td>
|
14
|
+
<td><%= inspect obj, child_options %></td>
|
15
|
+
<td><%=h obj.class.name %></td>
|
16
|
+
</tr>
|
17
|
+
<%- end -%>
|
18
|
+
</table>
|
@@ -0,0 +1 @@
|
|
1
|
+
<span class=nowrap><%=h @object.inspect.truncate(80) %></span>
|
@@ -0,0 +1,29 @@
|
|
1
|
+
<div>
|
2
|
+
<table class="inspector data-mapper-collection">
|
3
|
+
<thead>
|
4
|
+
<tr>
|
5
|
+
<%- columns.each do |p| -%>
|
6
|
+
<th><p><%= column_label(p) %></p></th>
|
7
|
+
<%- end -%>
|
8
|
+
<th></th>
|
9
|
+
</tr>
|
10
|
+
</thead>
|
11
|
+
<tbody class="records">
|
12
|
+
<%- records.each_with_index do |record, i| -%>
|
13
|
+
<%-
|
14
|
+
tr_class = (i % 2 == 0) ? "even-record" : ""
|
15
|
+
tr_class += " #{list_row_class(record)}" if respond_to? :list_row_class
|
16
|
+
-%>
|
17
|
+
<tr class="record <%=tr_class%>">
|
18
|
+
<%- columns.each do |p| -%>
|
19
|
+
<td><%= column_value(record, p) %></td>
|
20
|
+
<%- end -%>
|
21
|
+
</tr>
|
22
|
+
<%- end -%>
|
23
|
+
</tbody>
|
24
|
+
</table>
|
25
|
+
|
26
|
+
<%= link_to_new 'New' %>
|
27
|
+
|
28
|
+
</div>
|
29
|
+
|
@@ -0,0 +1,41 @@
|
|
1
|
+
<div id="<%=dom_id%>">
|
2
|
+
<div id="<%=dom_id%>_show" class="reversible record show" style="display:<%= (@mode == :edit) ? 'none' : 'display' %>">
|
3
|
+
<table>
|
4
|
+
<tbody>
|
5
|
+
<%- columns.each do |p| -%>
|
6
|
+
<tr>
|
7
|
+
<th><%= column_label(p) %></th>
|
8
|
+
<td><%= column_value(record, p) %></td>
|
9
|
+
</tr>
|
10
|
+
<%- end -%>
|
11
|
+
<tr>
|
12
|
+
<td colspan=2 align=center>
|
13
|
+
<%= link_to "edit", "#", :onclick=>toggle %>
|
14
|
+
</td>
|
15
|
+
</tr>
|
16
|
+
</tbody>
|
17
|
+
</table>
|
18
|
+
</div>
|
19
|
+
|
20
|
+
<div id="<%=dom_id%>_edit" class="reversible record edit" style="display:<%= (@mode == :edit) ? 'display' : 'none' %>">
|
21
|
+
<%= form_for record, :action=>save_action do %>
|
22
|
+
<table>
|
23
|
+
<tbody>
|
24
|
+
<%- columns.each do |p| -%>
|
25
|
+
<tr>
|
26
|
+
<th><%= column_label(p) %></th>
|
27
|
+
<td><%= column_form(record, p) %></td>
|
28
|
+
</tr>
|
29
|
+
<%- end -%>
|
30
|
+
<tr>
|
31
|
+
<td colspan=2 align=center>
|
32
|
+
<%= submit (record.new_record? ? "create" : "update").t %>
|
33
|
+
<%= link_to "cancel", "#", :onclick=>toggle unless record.new_record? %>
|
34
|
+
</td>
|
35
|
+
</tr>
|
36
|
+
</tbody>
|
37
|
+
</table>
|
38
|
+
<% end =%>
|
39
|
+
</div>
|
40
|
+
</div>
|
41
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<table class="inspector">
|
2
|
+
<tr>
|
3
|
+
<th><p>key</p></th>
|
4
|
+
<th><p>value</p></th>
|
5
|
+
<th><p>type</p></th>
|
6
|
+
</tr>
|
7
|
+
<%- @object.keys.each_with_index do |key, i| -%>
|
8
|
+
<%- obj = @object[key] -%>
|
9
|
+
<%-
|
10
|
+
tr_class = (i % 2 == 0) ? "even-record" : ""
|
11
|
+
tr_class += " #{list_row_class(obj)}" if respond_to? :list_row_class
|
12
|
+
-%>
|
13
|
+
<tr class="record <%=tr_class%>">
|
14
|
+
<td><%= inspect key, child_options %></td>
|
15
|
+
<td><%= inspect obj, child_options %></td>
|
16
|
+
<td><%=h obj.class.name %></td>
|
17
|
+
</tr>
|
18
|
+
<%- end -%>
|
19
|
+
</table>
|
@@ -0,0 +1,41 @@
|
|
1
|
+
<div id="<%=dom_id%>">
|
2
|
+
<div id="<%=dom_id%>_show" class="reversible record show" style="display:<%= (@mode == :edit) ? 'none' : 'display' %>">
|
3
|
+
<table>
|
4
|
+
<tbody>
|
5
|
+
<%- columns.each do |p| -%>
|
6
|
+
<tr>
|
7
|
+
<th><%= column_label(p) %></th>
|
8
|
+
<td><%= column_value(record, p) %></td>
|
9
|
+
</tr>
|
10
|
+
<%- end -%>
|
11
|
+
<tr>
|
12
|
+
<td colspan=2 align=center>
|
13
|
+
<%= link_to "edit", "#", :onclick=>toggle %>
|
14
|
+
</td>
|
15
|
+
</tr>
|
16
|
+
</tbody>
|
17
|
+
</table>
|
18
|
+
</div>
|
19
|
+
|
20
|
+
<div id="<%=dom_id%>_edit" class="reversible record edit" style="display:<%= (@mode == :edit) ? 'display' : 'none' %>">
|
21
|
+
<%= form_for record, :action=>save_action do %>
|
22
|
+
<table>
|
23
|
+
<tbody>
|
24
|
+
<%- columns.each do |p| -%>
|
25
|
+
<tr>
|
26
|
+
<th><%= column_label(p) %></th>
|
27
|
+
<td><%= column_form(record, p) %></td>
|
28
|
+
</tr>
|
29
|
+
<%- end -%>
|
30
|
+
<tr>
|
31
|
+
<td colspan=2 align=center>
|
32
|
+
<%= submit (record.new_record? ? "create" : "update").t %>
|
33
|
+
<%= link_to "cancel", "#", :onclick=>toggle unless record.new_record? %>
|
34
|
+
</td>
|
35
|
+
</tr>
|
36
|
+
</tbody>
|
37
|
+
</table>
|
38
|
+
<% end =%>
|
39
|
+
</div>
|
40
|
+
</div>
|
41
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<table class="inspector">
|
2
|
+
<tr>
|
3
|
+
<th><p>key</p></th>
|
4
|
+
<th><p>value</p></th>
|
5
|
+
<th><p>type</p></th>
|
6
|
+
</tr>
|
7
|
+
<%- @object.instance_variables.sort.each_with_index do |key, i| -%>
|
8
|
+
<%- obj = @object.instance_variable_get(key) -%>
|
9
|
+
<%-
|
10
|
+
tr_class = (i % 2 == 0) ? "even-record" : ""
|
11
|
+
tr_class += " #{list_row_class(obj)}" if respond_to? :list_row_class
|
12
|
+
-%>
|
13
|
+
<tr class="record <%=tr_class%>">
|
14
|
+
<td><%=h key %></td>
|
15
|
+
<td><%#h obj.inspect %><%= inspect obj, child_options rescue "error" %></td>
|
16
|
+
<td><%=h obj.class.name %></td>
|
17
|
+
</tr>
|
18
|
+
<%- end -%>
|
19
|
+
</table>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%=h @object.inspect %>
|
metadata
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: merb_inspector
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Maiha
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-12-28 00:00:00 +09:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: merb
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.0.8
|
24
|
+
version:
|
25
|
+
description: Merb plugin that provides powerful 'inspect' helper method
|
26
|
+
email: maiha@wota.jp
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- README
|
33
|
+
- LICENSE
|
34
|
+
- TODO
|
35
|
+
files:
|
36
|
+
- LICENSE
|
37
|
+
- README
|
38
|
+
- Rakefile
|
39
|
+
- TODO
|
40
|
+
- lib/merb_inspector/helper.rb
|
41
|
+
- lib/merb_inspector/builtin.rb
|
42
|
+
- lib/merb_inspector/data.rb
|
43
|
+
- lib/merb_inspector/merbtasks.rb
|
44
|
+
- lib/merb_inspector/manager.rb
|
45
|
+
- lib/merb_inspector/inspector.rb
|
46
|
+
- lib/merb_inspector.rb
|
47
|
+
- spec/spec_helper.rb
|
48
|
+
- spec/merb_inspector_spec.rb
|
49
|
+
- inspectors/object.rb
|
50
|
+
- inspectors/hash.rb
|
51
|
+
- inspectors/basic.rb
|
52
|
+
- inspectors/mongo_mapper.rb
|
53
|
+
- inspectors/data_mapper.rb
|
54
|
+
- inspectors/array.rb
|
55
|
+
- templates/hash/_default.html.erb
|
56
|
+
- templates/_default.html.erb
|
57
|
+
- templates/basic/_default.html.erb
|
58
|
+
- templates/array/_default.html.erb
|
59
|
+
- templates/object/_plain.html.erb
|
60
|
+
- templates/object/_default.html.erb
|
61
|
+
- templates/data_mapper/resource/_record.html.erb
|
62
|
+
- templates/data_mapper/collection/_records.html.erb
|
63
|
+
- templates/mongo_mapper/document/_record.html.erb
|
64
|
+
- mirror/public/stylesheets/merb_inspector.css
|
65
|
+
has_rdoc: true
|
66
|
+
homepage: http://github.com/maiha/merb_inspector
|
67
|
+
licenses: []
|
68
|
+
|
69
|
+
post_install_message:
|
70
|
+
rdoc_options: []
|
71
|
+
|
72
|
+
require_paths:
|
73
|
+
- lib
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: "0"
|
79
|
+
version:
|
80
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: "0"
|
85
|
+
version:
|
86
|
+
requirements: []
|
87
|
+
|
88
|
+
rubyforge_project: merb
|
89
|
+
rubygems_version: 1.3.5
|
90
|
+
signing_key:
|
91
|
+
specification_version: 3
|
92
|
+
summary: Merb plugin that provides powerful 'inspect' helper method
|
93
|
+
test_files: []
|
94
|
+
|