beds 0.0.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/bin/beds +70 -0
- data/lib/beds.rb +298 -0
- metadata +65 -0
data/bin/beds
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'beds'
|
3
|
+
@options = {
|
4
|
+
:viewdir => "./views",
|
5
|
+
:routefile => "./scaffold.rb",
|
6
|
+
:list => true,
|
7
|
+
:save => true,
|
8
|
+
:template => true,
|
9
|
+
:new => true,
|
10
|
+
:index => true,
|
11
|
+
:exclude => []
|
12
|
+
}
|
13
|
+
optparser = OptionParser.new do |opts|
|
14
|
+
opts.banner = " Usage: #{File.basename($0)} -m <models.rb> [OPTIONS]"
|
15
|
+
opts.on("-m","--models FILE", "Specify file with DataMapper models defined.") do |app|
|
16
|
+
@options[:app] = app
|
17
|
+
end
|
18
|
+
opts.on("-v","--viewdir","Specify which directory to place the views in. Default: ./views/") do |viewdir|
|
19
|
+
@options[:viewdir] = viewdir
|
20
|
+
end
|
21
|
+
opts.on("-r","--routefile", "Sepcify the file to generate the routes in. Default: scaffold.rb") do |routefile|
|
22
|
+
@options[:routefile] = routefile
|
23
|
+
end
|
24
|
+
opts.on("--exclude x,y,z", Array, "Do not generate anything for specified models, or before, index, and/or layout") do |models|
|
25
|
+
@options[:exclude] = models
|
26
|
+
end
|
27
|
+
opts.on("--only x,y,z", Array, "Only process the specified models.") do |models|
|
28
|
+
@options[:only] = models
|
29
|
+
end
|
30
|
+
opts.on("-f","--[no-]force", "Overwtie files") do |force|
|
31
|
+
@options[:force] = force
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
begin
|
36
|
+
optparser.parse! ARGV
|
37
|
+
raise OptionParser::InvalidOption, "[NONE]" if @options[:app].nil?
|
38
|
+
rescue OptionParser::InvalidOption => e
|
39
|
+
puts e
|
40
|
+
puts optparser
|
41
|
+
exit 1
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
|
46
|
+
load "#{@options[:app]}"
|
47
|
+
scaffold = SinScaffold.new(@options)
|
48
|
+
scaffold.generate
|
49
|
+
|
50
|
+
### Write Files
|
51
|
+
|
52
|
+
if File.exist?(@options[:routefile]) and ! @options[:force] then
|
53
|
+
puts "Error: Route file #{@options[:routefile]} already exists. Not writing"
|
54
|
+
else
|
55
|
+
File.open(@options[:routefile],"w") {|file| file.write(scaffold.routes.join("\n"))}
|
56
|
+
end
|
57
|
+
|
58
|
+
Dir.mkdir(@options[:viewdir]) unless Dir.exist?(@options[:viewdir])
|
59
|
+
|
60
|
+
@gen_files = []
|
61
|
+
scaffold.views.each {|file,content|
|
62
|
+
if File.exist?(File.join(@options[:viewdir],file)) and ! @options[:force] then
|
63
|
+
puts "Warning: file #{File.join(@options[:viewdir],file)} exists. Not overwriting"
|
64
|
+
else
|
65
|
+
@gen_files << File.join(@options[:viewdir],file)
|
66
|
+
File.open(File.join(@options[:viewdir],file),"w") {|file| file.write(content) }
|
67
|
+
end
|
68
|
+
}
|
69
|
+
|
70
|
+
puts "Generated files: #{@gen_files.join(", ")}"
|
data/lib/beds.rb
ADDED
@@ -0,0 +1,298 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'erb'
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
class SinScaffold
|
6
|
+
STATIC_ROUTE_TEMPLATES = {
|
7
|
+
:before => %q^
|
8
|
+
before do
|
9
|
+
@active_page = request.path_info.split(/\//)[1]
|
10
|
+
@active_page = "index" if @active_page.nil?
|
11
|
+
end
|
12
|
+
^,
|
13
|
+
:index => %Q^
|
14
|
+
get '/' do
|
15
|
+
erb :index
|
16
|
+
end
|
17
|
+
^ }
|
18
|
+
STATIC_ERB_TEMPLATES = {
|
19
|
+
:layout => %Q^
|
20
|
+
<!DOCTYPE html>
|
21
|
+
<html lang="en">
|
22
|
+
<head>
|
23
|
+
<meta charset="utf-8">
|
24
|
+
<title>Application</title>
|
25
|
+
<meta name="GeneratedBy" content="sdbscaffold"
|
26
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
27
|
+
<meta name="description" content="">
|
28
|
+
<meta name="author" content="">
|
29
|
+
<!-- Le styles -->
|
30
|
+
|
31
|
+
<link href="/assets/css/bootstrap.css" rel="stylesheet">
|
32
|
+
<link href="/style.css" rel="stylesheet">
|
33
|
+
<style>
|
34
|
+
body {
|
35
|
+
padding-top: 60px; /* 60px to make the container go all the way to the bottom of the topbar */
|
36
|
+
}
|
37
|
+
</style>
|
38
|
+
|
39
|
+
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
|
40
|
+
<!--[if lt IE 9]>
|
41
|
+
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
|
42
|
+
<![endif]-->
|
43
|
+
<script src="/assets/js/jquery.js" type="text/javascript"></script>
|
44
|
+
<script>
|
45
|
+
$(document).ready(function() {
|
46
|
+
$("#<%%=@active_page%>").addClass("active");
|
47
|
+
});
|
48
|
+
</script>
|
49
|
+
<!-- Le fav and touch icons -->
|
50
|
+
<link rel="shortcut icon" href="/assets/ico/favicon.ico">
|
51
|
+
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="/assets/ico/apple-touch-icon-144-precomposed.png">
|
52
|
+
<link rel="apple-touch-icon-precomposed" sizes="114x114" href="/assets/ico/apple-touch-icon-114-precomposed.png">
|
53
|
+
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="/assets/ico/apple-touch-icon-72-precomposed.png">
|
54
|
+
<link rel="apple-touch-icon-precomposed" href="/assets/ico/apple-touch-icon-57-precomposed.png">
|
55
|
+
</head>
|
56
|
+
|
57
|
+
<body>
|
58
|
+
|
59
|
+
<div class="navbar navbar-fixed-top">
|
60
|
+
<div class="navbar-inner">
|
61
|
+
<div class="container">
|
62
|
+
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
63
|
+
<span class="icon-bar"></span>
|
64
|
+
<span class="icon-bar"></span>
|
65
|
+
<span class="icon-bar"></span>
|
66
|
+
</a>
|
67
|
+
<a class="brand" href="#">YourApp</a>
|
68
|
+
<div class="nav-collapse">
|
69
|
+
<ul class="nav">
|
70
|
+
<li class="divider-vertical"></li>
|
71
|
+
<li id="index" ><a href="/">Home</a></li>
|
72
|
+
<% @models.each do |model| %>
|
73
|
+
<li id="<%=model.name.downcase%>" ><a href="/<%=model.name.downcase%>/"><%= model.name %></a></li>
|
74
|
+
<% end %>
|
75
|
+
</ul>
|
76
|
+
<ul class="nav pull-right">
|
77
|
+
<li class="divider-vertical"></li>
|
78
|
+
<li><a href="/login">Log<%%= session[:valid] ? "out" : "in"%></a></li>
|
79
|
+
</ul>
|
80
|
+
</div><!--/.nav-collapse -->
|
81
|
+
</div>
|
82
|
+
</div>
|
83
|
+
</div>
|
84
|
+
|
85
|
+
<div class="container">
|
86
|
+
<%% if ! @flash.nil? then %>
|
87
|
+
<span class="span9 offset1">
|
88
|
+
<%% @flash.each do |alert| %>
|
89
|
+
<div class="alert alert-<%%=alert[:level].downcase%>" style="margin:0px; margin-bottom:8px;">
|
90
|
+
<button class="close" data-dismiss="alert">x</button>
|
91
|
+
<strong><%%=alert[:level].capitalize%>!</strong> <%%=alert[:message]%>
|
92
|
+
</div>
|
93
|
+
<%% end %>
|
94
|
+
</span>
|
95
|
+
<%%end %>
|
96
|
+
<%%= yield %>
|
97
|
+
</div> <!-- /container -->
|
98
|
+
|
99
|
+
<!-- Le javascript
|
100
|
+
================================================== -->
|
101
|
+
<!-- Placed at the end of the document so the pages load faster -->
|
102
|
+
<script src="/assets/js/bootstrap.min.js"></script>
|
103
|
+
</body>
|
104
|
+
</html>
|
105
|
+
^,
|
106
|
+
:index => %Q^
|
107
|
+
<div class="well">
|
108
|
+
<div class="hero-unit">
|
109
|
+
<h1>Models</h1>
|
110
|
+
<p class="btn-group">
|
111
|
+
<% @models.each do |model| %>
|
112
|
+
<a class="btn btn-large btn-info" href="/<%=model.name.downcase%>/"><%= model.name %></a>
|
113
|
+
<% end %>
|
114
|
+
</p>
|
115
|
+
</div>
|
116
|
+
</div>
|
117
|
+
^
|
118
|
+
}
|
119
|
+
ROUTE_TEMPLATES = {
|
120
|
+
:list => %Q^
|
121
|
+
get '/<%=@model_name.downcase%>/?' do
|
122
|
+
@offset = params["page"] if params["page"] =~ /[0-9]+/
|
123
|
+
@offset ||= 0
|
124
|
+
@db_objects = <%=@model_name%>.all(:limit => 20,:offset => @offset * 20)
|
125
|
+
erb :list_<%=@model_name.downcase%>
|
126
|
+
end
|
127
|
+
^,
|
128
|
+
:new => %q^
|
129
|
+
get '/<%=@model_name.downcase%>/new/?' do
|
130
|
+
erb :new_<%=@model_name.downcase%>
|
131
|
+
end
|
132
|
+
^,
|
133
|
+
:save => %q^
|
134
|
+
post '/<%=@model_name.downcase%>/save/?' do
|
135
|
+
db_object = <%=@model_name%>.new
|
136
|
+
params.each do |key,value|
|
137
|
+
db_object.send("#{key}=",value) if <%=@model_name%>.properties.collect{|x| x.name}.include? key.to_sym
|
138
|
+
end
|
139
|
+
if db_object.save then
|
140
|
+
redirect "/<%=@model_name.downcase%>/#{db_object.id}"
|
141
|
+
else
|
142
|
+
result = []
|
143
|
+
db_object.errors.each do |e|
|
144
|
+
result << "<li>#{e}</li>"
|
145
|
+
end
|
146
|
+
return "<UL>#{result.join("")}</UL>"
|
147
|
+
end
|
148
|
+
end
|
149
|
+
^,
|
150
|
+
:edit => %q^
|
151
|
+
get '/<%=@model_name.downcase%>/:id/?' do |id|
|
152
|
+
pass if "#{id.to_i}" != "#{id}"
|
153
|
+
@db_object = <%=@model_name%>.first(:id => id)
|
154
|
+
return 404 if @db_object.nil?
|
155
|
+
erb :edit_<%=@model_name.downcase%>
|
156
|
+
end
|
157
|
+
|
158
|
+
post '/<%=@model_name.downcase%>/:id/?' do |id|
|
159
|
+
db_object = <%=@model_name%>.first(:id => id)
|
160
|
+
redirect 404 if ! db_object
|
161
|
+
params.each do |key,value|
|
162
|
+
db_object.send("#{key}=",value) if <%=@model_name%>.properties.collect{|x| x.name}.include? key.to_sym
|
163
|
+
end
|
164
|
+
if db_object.save then
|
165
|
+
redirect "/<%=@model_name.downcase%>/#{db_object.id}"
|
166
|
+
else
|
167
|
+
result = []
|
168
|
+
db_object.errors.each do |e|
|
169
|
+
STDERR.puts e
|
170
|
+
result << "<li>#{e}</li>"
|
171
|
+
end
|
172
|
+
return "<UL>#{result.join("")}</UL>"
|
173
|
+
end
|
174
|
+
end
|
175
|
+
^,
|
176
|
+
:delete => %q^
|
177
|
+
get '/<%=@model_name.downcase%>/delete/:id/?' do |id|
|
178
|
+
db_object = <%=@model_name%>.first(:id => id)
|
179
|
+
if db_object then
|
180
|
+
db_object.destroy
|
181
|
+
redirect '/<%=@model_name.downcase%>/'
|
182
|
+
else
|
183
|
+
redirect 404
|
184
|
+
end
|
185
|
+
end
|
186
|
+
^
|
187
|
+
}
|
188
|
+
ERB_TEMPLATES = {
|
189
|
+
:list => %Q^
|
190
|
+
<a href="/<%=@model_name.downcase%>/new" class="btn btn-info">New</a>
|
191
|
+
<table class="table table-bordered">
|
192
|
+
<thead>
|
193
|
+
<% @properties.each do |header| %>
|
194
|
+
<th><%=header.name%></th>
|
195
|
+
<% end %>
|
196
|
+
<th>Actions</th>
|
197
|
+
</thead>
|
198
|
+
<tbody>
|
199
|
+
<%% @db_objects.each do |object| %>
|
200
|
+
<tr>
|
201
|
+
<% @properties.each do |prop| %>
|
202
|
+
<td><%%=object.<%=prop.name%>%></td>
|
203
|
+
<%end%>
|
204
|
+
<td><a href="/<%=@model_name.downcase%>/<%%=object.id%>" class="btn btn-mini">Edit</a>
|
205
|
+
<a href="/<%=@model_name.downcase%>/delete/<%%=object.id%>" class="btn btn-mini">Delete</a></td>
|
206
|
+
</tr>
|
207
|
+
<%%end%>
|
208
|
+
</tbody>
|
209
|
+
</table>
|
210
|
+
^,
|
211
|
+
:new => %q^
|
212
|
+
<form class="well row" method="post" action="/<%=@model_name.downcase%>/save">
|
213
|
+
<% @properties.each do |prop| %>
|
214
|
+
<% next if prop.name == :id %>
|
215
|
+
<label><%=prop.name.to_s%></label>
|
216
|
+
<%=form_type(prop,:name => prop.name)%>
|
217
|
+
|
218
|
+
<% end %>
|
219
|
+
<button type="submit" class="btn">Submit</button>
|
220
|
+
</form>
|
221
|
+
^,
|
222
|
+
:edit => %q^
|
223
|
+
<form class="well" method="post" action="/<%=@model_name.downcase%>/<%%= @db_object.id%>">
|
224
|
+
<% @properties.each do |prop| %>
|
225
|
+
<% next if prop.name == :id %>
|
226
|
+
<label><%=prop.name.to_s%></label>
|
227
|
+
<%=form_type(prop,:name => prop.name,:value => "<%= @db_object.#{prop.name} %%>")%>
|
228
|
+
|
229
|
+
<% end %>
|
230
|
+
<button type="submit" class="btn">Submit</button>
|
231
|
+
</form>
|
232
|
+
^
|
233
|
+
}
|
234
|
+
|
235
|
+
def initialize(opts)
|
236
|
+
@routes = []
|
237
|
+
@views = {}
|
238
|
+
@models = []
|
239
|
+
@opts = opts
|
240
|
+
DataMapper::Model.descendants.entries.each {|entry|
|
241
|
+
@models << entry
|
242
|
+
#@model_name=entry.inspect
|
243
|
+
#@properties=entry.properties
|
244
|
+
|
245
|
+
#puts ERB.new(ERB_TEMPLATES[:new]).result(binding)
|
246
|
+
}
|
247
|
+
@models.delete_if { |model| @opts[:exclude].include? model.name or @opts[:exclude].include? model.name.downcase }
|
248
|
+
@models.select! { |model| @opts[:only].include? model.name or @opts[:only].include? model.name.downcase } unless @opts[:only].nil?
|
249
|
+
end
|
250
|
+
def generate
|
251
|
+
result = Hash.new
|
252
|
+
routes = Hash.new
|
253
|
+
STATIC_ROUTE_TEMPLATES.each { |key,value| next if @opts[:exclude].include? key.to_s; puts "Processing Route: #{key}"; @routes << ERB.new(value,nil,"<>").result(binding) } if @opts[:only].nil?
|
254
|
+
STATIC_ERB_TEMPLATES.each { |key,value| next if @opts[:exclude].include? key.to_s; puts "Processing Template: #{key}";@views["#{key.to_s}.erb"]=ERB.new(value,nil,"<>").result(binding) } if @opts[:only].nil?
|
255
|
+
@models.each { |entry|
|
256
|
+
@model_name = entry.inspect
|
257
|
+
@properties = entry.properties
|
258
|
+
puts "Processing Model: #{@model_name}"
|
259
|
+
ROUTE_TEMPLATES.each {|key,value|
|
260
|
+
@routes << ERB.new(value,nil,"<>").result(binding)
|
261
|
+
}
|
262
|
+
ERB_TEMPLATES.each { |key,value|
|
263
|
+
@views["#{key.to_s}_#{@model_name.downcase}.erb"] = ERB.new(value,nil,"<>").result(binding)
|
264
|
+
}
|
265
|
+
}
|
266
|
+
return true
|
267
|
+
end
|
268
|
+
def routes
|
269
|
+
@routes
|
270
|
+
end
|
271
|
+
def views
|
272
|
+
@views
|
273
|
+
end
|
274
|
+
private
|
275
|
+
def form_type(object,properties)
|
276
|
+
append = String.new
|
277
|
+
properties.each {|key,value|
|
278
|
+
append << " #{key}='#{value}'"
|
279
|
+
}
|
280
|
+
|
281
|
+
case object
|
282
|
+
when DataMapper::Property::Serial
|
283
|
+
""
|
284
|
+
when DataMapper::Property::String
|
285
|
+
"<input type='text' class='span2' #{append} />"
|
286
|
+
when DataMapper::Property::Boolean
|
287
|
+
"<input type='checkbox' #{append}/>"
|
288
|
+
when DataMapper::Property::Text
|
289
|
+
"<textbox class='span3' #{append - append[:value]}>#{append[:value] unless append[:value].nil?}</textbox>"
|
290
|
+
when DataMapper::Property::Float, DataMapper::Property::Integer, DataMapper::Property::Decimal
|
291
|
+
"<input type='text' class='span1' #{append} />"
|
292
|
+
when DateTime, Date, Time
|
293
|
+
"<input type='text' class='span2' #{append} />"
|
294
|
+
else
|
295
|
+
"<input type='text' class='span1' #{append} />"
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
metadata
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: beds
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.2
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- James Paterni
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2012-06-12 00:00:00 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rspec
|
17
|
+
prerelease: false
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
type: :development
|
25
|
+
version_requirements: *id001
|
26
|
+
description:
|
27
|
+
email: james@ruby-code.com
|
28
|
+
executables:
|
29
|
+
- beds
|
30
|
+
extensions: []
|
31
|
+
|
32
|
+
extra_rdoc_files: []
|
33
|
+
|
34
|
+
files:
|
35
|
+
- lib/beds.rb
|
36
|
+
- bin/beds
|
37
|
+
homepage: https://github.com/jamez01/beds
|
38
|
+
licenses: []
|
39
|
+
|
40
|
+
post_install_message:
|
41
|
+
rdoc_options: []
|
42
|
+
|
43
|
+
require_paths:
|
44
|
+
- lib
|
45
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
46
|
+
none: false
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: "0"
|
51
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: "0"
|
57
|
+
requirements: []
|
58
|
+
|
59
|
+
rubyforge_project: nowarning
|
60
|
+
rubygems_version: 1.8.15
|
61
|
+
signing_key:
|
62
|
+
specification_version: 3
|
63
|
+
summary: The BootStrap ERb DataMapper Sinatra [scaffolder]
|
64
|
+
test_files: []
|
65
|
+
|