merb_inspector 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|