aura 0.0.1.pre10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (249) hide show
  1. data/.gitignore +6 -0
  2. data/.travis.yml +3 -0
  3. data/Gemfile +2 -0
  4. data/HISTORY.md +95 -0
  5. data/README.md +53 -0
  6. data/Rakefile +27 -0
  7. data/Scribefile +8 -0
  8. data/app/css/_utilities.scss +88 -0
  9. data/app/css/admin.scss +21 -0
  10. data/app/css/admin/_settings.scss +136 -0
  11. data/app/css/admin/chrome.scss +208 -0
  12. data/app/css/admin/common.scss +78 -0
  13. data/app/css/admin/forms.scss +342 -0
  14. data/app/css/admin/jquery_wysiwyg.scss +96 -0
  15. data/app/css/admin/loading.scss +18 -0
  16. data/app/css/admin/meta.scss +42 -0
  17. data/app/css/admin/reset.scss +46 -0
  18. data/app/css/admin/sections.scss +79 -0
  19. data/app/css/admin/setup.scss +22 -0
  20. data/app/css/admin/sidebar.scss +136 -0
  21. data/app/css/admin/slug.scss +78 -0
  22. data/app/css/admin/uiscreen.scss +22 -0
  23. data/app/css/admin/wysiwyg_field.scss +11 -0
  24. data/app/css/admin_watermark.scss +23 -0
  25. data/app/css/default_home_page.scss +13 -0
  26. data/app/css/login.scss +47 -0
  27. data/app/helpers/admin_helpers.rb +59 -0
  28. data/app/helpers/flash_helpers.rb +86 -0
  29. data/app/helpers/form_builder_helpers.rb +9 -0
  30. data/app/helpers/html_helpers.rb +27 -0
  31. data/app/helpers/jquery_helpers.rb +26 -0
  32. data/app/helpers/main_helpers.rb +67 -0
  33. data/app/helpers/page_helpers.rb +92 -0
  34. data/app/helpers/template_helpers.rb +94 -0
  35. data/app/helpers/user_helpers.rb +45 -0
  36. data/app/init/admin.rb +34 -0
  37. data/app/init/extensions.rb +18 -0
  38. data/app/init/pistol.rb +11 -0
  39. data/app/init/sequel.rb +11 -0
  40. data/app/main.rb +106 -0
  41. data/app/migrations/page.rb +29 -0
  42. data/app/migrations/settings.rb +11 -0
  43. data/app/migrations/user.rb +13 -0
  44. data/app/models/page.rb +116 -0
  45. data/app/models/page_seed.rb +47 -0
  46. data/app/models/settings.rb +59 -0
  47. data/app/models/user.rb +60 -0
  48. data/app/routes/admin.rb +44 -0
  49. data/app/routes/css_js.rb +53 -0
  50. data/app/routes/design_tests.rb +15 -0
  51. data/app/routes/editor.rb +152 -0
  52. data/app/routes/site.rb +33 -0
  53. data/app/routes/user.rb +48 -0
  54. data/app/views/admin/_back_to_dashboard.haml +3 -0
  55. data/app/views/admin/dashboard.haml +46 -0
  56. data/app/views/admin/layout.haml +73 -0
  57. data/app/views/admin/settings.haml +40 -0
  58. data/app/views/admin/settings/database.haml +42 -0
  59. data/app/views/base/crumbs.haml +50 -0
  60. data/app/views/base/delete.haml +19 -0
  61. data/app/views/base/edit.haml +61 -0
  62. data/app/views/base/errors.haml +10 -0
  63. data/app/views/base/form.haml +11 -0
  64. data/app/views/base/list.haml +14 -0
  65. data/app/views/base/list_actions.haml +4 -0
  66. data/app/views/base/list_item.haml +7 -0
  67. data/app/views/base/nav.haml +36 -0
  68. data/app/views/base/new.haml +36 -0
  69. data/app/views/base/preview.haml +28 -0
  70. data/app/views/base/tabs.haml +12 -0
  71. data/app/views/default_home_page.haml +15 -0
  72. data/app/views/design_tests/admin_styles.haml +58 -0
  73. data/app/views/form_builder/builder.haml +29 -0
  74. data/app/views/page/edit.haml +29 -0
  75. data/app/views/page/form.haml +22 -0
  76. data/app/views/page/meta_form.haml +22 -0
  77. data/app/views/page/new.haml +26 -0
  78. data/app/views/user/edit.haml +52 -0
  79. data/app/views/user/form.haml +43 -0
  80. data/app/views/user/list.haml +11 -0
  81. data/app/views/user/login.haml +33 -0
  82. data/app/views/user/new.haml +25 -0
  83. data/app/views/user/welcome.haml +29 -0
  84. data/app/views/watermark/watermark.haml +16 -0
  85. data/aura.gemspec +36 -0
  86. data/bin/aura +8 -0
  87. data/config/database.rb +12 -0
  88. data/config/extensions.rb +5 -0
  89. data/config/scss.rb +14 -0
  90. data/config/user.rb +10 -0
  91. data/default/.gitignore +6 -0
  92. data/default/Gemfile +11 -0
  93. data/default/README.md +24 -0
  94. data/default/Rakefile +8 -0
  95. data/default/app/README +3 -0
  96. data/default/app/css/.gitignore +0 -0
  97. data/default/app/helpers/helpers.rb.example +9 -0
  98. data/default/app/js/.gitignore +0 -0
  99. data/default/app/migrations/model.rb.example +20 -0
  100. data/default/app/models/model.rb.example +11 -0
  101. data/default/app/models/page-ext.rb.example +17 -0
  102. data/default/app/routes/site.rb.example +5 -0
  103. data/default/app/views/hello.haml.example +1 -0
  104. data/default/config.ru +3 -0
  105. data/default/config/.gitignore +0 -0
  106. data/default/config/database.rb.example +30 -0
  107. data/default/config/extensions.rb +5 -0
  108. data/default/config/user.rb.example +10 -0
  109. data/default/db/.gitignore +0 -0
  110. data/default/init.rb +15 -0
  111. data/default/public/.gitignore +0 -0
  112. data/extensions/contact_form/migrations/contact_form.rb +13 -0
  113. data/extensions/contact_form/models/contact_form.rb +13 -0
  114. data/extensions/contact_form/routes/contact_form.rb +11 -0
  115. data/extensions/contact_form/views/contact_form/edit.haml +8 -0
  116. data/extensions/contact_form/views/contact_form/form.haml +3 -0
  117. data/extensions/contact_form/views/contact_form/nav.haml +42 -0
  118. data/extensions/contact_form/views/contact_form/responses.haml +20 -0
  119. data/extensions/contact_form/views/contact_form/tabs.haml +8 -0
  120. data/extensions/default_theme/css/theme/_settings.scss +3 -0
  121. data/extensions/default_theme/css/theme/chrome.scss +66 -0
  122. data/extensions/default_theme/css/theme/reset.scss +34 -0
  123. data/extensions/default_theme/css/theme/style.scss +3 -0
  124. data/extensions/default_theme/info.yml +2 -0
  125. data/extensions/default_theme/public/browse.png +0 -0
  126. data/extensions/default_theme/views/base/id_portfolio.haml +32 -0
  127. data/extensions/default_theme/views/base/show.haml +31 -0
  128. data/extensions/default_theme/views/errors/error.haml +9 -0
  129. data/extensions/default_theme/views/errors/not_found.haml +11 -0
  130. data/extensions/default_theme/views/layout.haml +33 -0
  131. data/lib/aura.rb +315 -0
  132. data/lib/aura/admin.rb +41 -0
  133. data/lib/aura/app.rb +4 -0
  134. data/lib/aura/cli.rb +19 -0
  135. data/lib/aura/cli/base.rb +89 -0
  136. data/lib/aura/cli/helpers.rb +32 -0
  137. data/lib/aura/editor.rb +30 -0
  138. data/lib/aura/extension.rb +189 -0
  139. data/lib/aura/files.rb +38 -0
  140. data/lib/aura/menu.rb +142 -0
  141. data/lib/aura/models.rb +80 -0
  142. data/lib/aura/public.rb +68 -0
  143. data/lib/aura/rendering.rb +134 -0
  144. data/lib/aura/seeder.rb +38 -0
  145. data/lib/aura/slugs.rb +87 -0
  146. data/lib/aura/subtype.rb +48 -0
  147. data/lib/aura/tasks.rb +24 -0
  148. data/lib/aura/tasks/common.rb +17 -0
  149. data/lib/aura/tasks/db.rake +54 -0
  150. data/lib/aura/utils.rb +81 -0
  151. data/lib/aura/version.rb +25 -0
  152. data/lib/core/hasharray.rb +65 -0
  153. data/lib/core/object_ext.rb +9 -0
  154. data/lib/sequel/plugins/aura_custom.rb +16 -0
  155. data/lib/sequel/plugins/aura_editable.rb +39 -0
  156. data/lib/sequel/plugins/aura_hierarchy.rb +82 -0
  157. data/lib/sequel/plugins/aura_model.rb +271 -0
  158. data/lib/sequel/plugins/aura_renderable.rb +42 -0
  159. data/lib/sequel/plugins/aura_sluggable.rb +103 -0
  160. data/lib/sequel/plugins/aura_subtyped.rb +83 -0
  161. data/lib/terra.rb +185 -0
  162. data/lib/terra/ext.rb +16 -0
  163. data/lib/terra/field.rb +98 -0
  164. data/lib/terra/fields.rb +122 -0
  165. data/lib/terra/fieldset.rb +93 -0
  166. data/lib/terra/form.rb +111 -0
  167. data/manual/configuration.md +42 -0
  168. data/manual/extensions.md +45 -0
  169. data/manual/files.md +70 -0
  170. data/manual/helpers.md +39 -0
  171. data/manual/index.md +65 -0
  172. data/manual/models.md +58 -0
  173. data/manual/recipes.md +38 -0
  174. data/manual/recipes/bundling_sample_data.md +30 -0
  175. data/manual/recipes/creating_themes.md +10 -0
  176. data/manual/recipes/using_markdown_or_textile.md +24 -0
  177. data/manual/routes.md +39 -0
  178. data/manual/theming.md +55 -0
  179. data/manual/views.md +128 -0
  180. data/public/hi.html +0 -0
  181. data/public/images/admin/back.png +0 -0
  182. data/public/images/admin/browse.png +0 -0
  183. data/public/images/admin/mock-bg.png +0 -0
  184. data/public/images/admin/top-loader.gif +0 -0
  185. data/public/images/admin/uiscreen-loader.gif +0 -0
  186. data/public/images/admin_icons/add.png +0 -0
  187. data/public/images/admin_icons/contact.png +0 -0
  188. data/public/images/admin_icons/dashboard.png +0 -0
  189. data/public/images/admin_icons/generic.png +0 -0
  190. data/public/images/admin_icons/home-12.png +0 -0
  191. data/public/images/admin_icons/page.png +0 -0
  192. data/public/images/admin_icons/settings.png +0 -0
  193. data/public/images/jquery.wysiwyg.gif +0 -0
  194. data/public/js/admin.form_builder.js +15 -0
  195. data/public/js/admin.js +62 -0
  196. data/public/js/admin.layout.js +53 -0
  197. data/public/js/admin.nav.js +241 -0
  198. data/public/js/admin.slug.js +46 -0
  199. data/public/js/admin.subpage.js +15 -0
  200. data/public/js/jquery.hashlisten.js +85 -0
  201. data/public/js/jquery.js +166 -0
  202. data/public/js/jquery.livenavigate.js +58 -0
  203. data/public/js/jquery.livequery.js +226 -0
  204. data/public/js/jquery.quickvalidate.js +164 -0
  205. data/public/js/jquery.tmpl.js +486 -0
  206. data/public/js/jquery.uiscreen.js +150 -0
  207. data/public/js/jquery.wysiwyg.js +2339 -0
  208. data/public/js/jqueryui.js +766 -0
  209. data/public/js/lib.dirty.js +11 -0
  210. data/public/js/lib.loading.js +23 -0
  211. data/public/js/lib.wysiwyg.js +155 -0
  212. data/public/js/underscore-1.1.7.js +27 -0
  213. data/test/app/app/css/test_raw.css +1 -0
  214. data/test/app/app/css/test_sass.sass +3 -0
  215. data/test/app/app/damogram.txt +1 -0
  216. data/test/app/app/js/test_coffee.coffee +4 -0
  217. data/test/app/app/js/test_javascript.js +4 -0
  218. data/test/app/init.rb +5 -0
  219. data/test/stories/admin_css_story.rb +18 -0
  220. data/test/stories/css_js_story.rb +29 -0
  221. data/test/stories/first_login_story.rb +29 -0
  222. data/test/stories/visit_story.rb +39 -0
  223. data/test/stories_helper.rb +58 -0
  224. data/test/test_cli_helper.rb +31 -0
  225. data/test/test_helper.rb +111 -0
  226. data/test/test_temp_helper.rb +9 -0
  227. data/test/unit/cli_test.rb +38 -0
  228. data/test/unit/dump_test.rb +14 -0
  229. data/test/unit/extensions_test.rb +18 -0
  230. data/test/unit/files_test.rb +14 -0
  231. data/test/unit/flash_helper_test.rb +36 -0
  232. data/test/unit/html_helper_test.rb +29 -0
  233. data/test/unit/jquery_helper_test.rb +18 -0
  234. data/test/unit/model_test.rb +34 -0
  235. data/test/unit/page_helpers_test.rb +36 -0
  236. data/test/unit/seeder_test.rb +15 -0
  237. data/test/unit/settings_test.rb +29 -0
  238. data/test/unit/slug_test.rb +39 -0
  239. data/test/unit/ss_migration_test.rb +14 -0
  240. data/test/unit/terra_test.rb +125 -0
  241. data/test/unit/utils_test.rb +11 -0
  242. data/vendor/sinatra-sequel/.gitignore +3 -0
  243. data/vendor/sinatra-sequel/COPYING +18 -0
  244. data/vendor/sinatra-sequel/README.md +84 -0
  245. data/vendor/sinatra-sequel/Rakefile +67 -0
  246. data/vendor/sinatra-sequel/lib/sinatra/sequel.rb +73 -0
  247. data/vendor/sinatra-sequel/sinatra-sequel.gemspec +39 -0
  248. data/vendor/sinatra-sequel/spec/spec_sinatra_sequel.rb +70 -0
  249. metadata +536 -0
@@ -0,0 +1,14 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ class SsMigrationTest < Test::Unit::TestCase
4
+ setup do
5
+ end
6
+
7
+ test "migrations" do
8
+ p db.tables
9
+
10
+ Aura.run_migrations!
11
+
12
+ assert db.tables.include?(:pages)
13
+ end
14
+ end
@@ -0,0 +1,125 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+ require 'terra'
3
+
4
+ class TerraTest < Test::Unit::TestCase
5
+ setup do
6
+ @form = Terra::Form.new
7
+ @form.root_name 'editor'
8
+ end
9
+
10
+ test "default fieldsets" do
11
+ @form.configure {
12
+ text :hi, "Hi"
13
+ }
14
+
15
+ assert @form.fieldset(:default).name == "Default"
16
+ assert @form.fieldsets == [@form.fieldset(:default)]
17
+ end
18
+
19
+ test "fieldset default name" do
20
+ @form.configure {
21
+ fieldset :meta do
22
+ text :hi, "Hi"
23
+ end
24
+ }
25
+
26
+ assert @form.fieldset(:meta).name == "Meta"
27
+ end
28
+
29
+ test "fieldset name" do
30
+ @form.configure {
31
+ fieldset :meta, "Metadata" do
32
+ text :hi, "Hi"
33
+ end
34
+ }
35
+
36
+ assert @form.fieldset(:meta).name == "Metadata"
37
+ end
38
+
39
+ test "field lookup" do
40
+ @form.configure {
41
+ text :hi
42
+ }
43
+
44
+ assert @form.field(:hi) == @form.fieldset(:default).field(:hi)
45
+ end
46
+
47
+ test "field deep lookup" do
48
+ @form.configure {
49
+ fieldset :one do
50
+ text :name
51
+ end
52
+ fieldset :two do
53
+ text :email
54
+ end
55
+ }
56
+
57
+ assert @form.field(:name) == @form.fieldset(:one).field(:name)
58
+ assert @form.field(:email) == @form.fieldset(:two).field(:email)
59
+ end
60
+
61
+ test "many ways to define select options" do
62
+ forms = [
63
+ Terra::Form.new.configure {
64
+ root_name 'editor'
65
+ options :category, "Categories", :options =>
66
+ [ { :a => "Apple" },
67
+ { :b => "Banana" }
68
+ ].to_hash_array
69
+ },
70
+
71
+ Terra::Form.new.configure {
72
+ root_name 'editor'
73
+ options :category, "Categories", :options =>
74
+ { :a => "Apple", :b => "Banana" }
75
+ },
76
+
77
+ Terra::Form.new.configure {
78
+ root_name 'editor'
79
+ options :category, "Categories", :options =>
80
+ lambda { |x|
81
+ [ { :a => "Apple" },
82
+ { :b => "Banana" }
83
+ ].to_hash_array
84
+ }
85
+ }
86
+ ]
87
+
88
+ forms.each do |form|
89
+ output = form.field(:category).to_html('a')
90
+ assert output.include?("<select id='field_category' name='editor[category]'>\n<option value='a' selected='selected'>a</option>\n<option value='b'>b</option>\n</select>")
91
+
92
+ assert form.fieldset(:default).field(:category)
93
+ end
94
+ end
95
+
96
+ test "traversion" do
97
+ @form.configure {
98
+ text :name
99
+ }
100
+
101
+ assert @form.field(:name).form === @form
102
+ assert @form.field(:name).fieldset === @form.fieldset(:default)
103
+ assert @form.fieldset(:default).form === @form
104
+ end
105
+
106
+ test "root name" do
107
+ @form.root_name 'editor'
108
+ assert @form.name_for('email') == "editor[email]"
109
+ end
110
+
111
+ test "root name 2" do
112
+ @form.root_name ['editor']
113
+ assert @form.name_for('email') == "editor[email]"
114
+ end
115
+
116
+ test "root name 3" do
117
+ @form.root_name ['editor', 'user']
118
+ assert @form.name_for('email') == "editor[user][email]"
119
+ end
120
+
121
+ test "root name 3" do
122
+ @form.root_name []
123
+ assert @form.name_for('email') == "email"
124
+ end
125
+ end
@@ -0,0 +1,11 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ class UtilsTest < Test::Unit::TestCase
4
+ include Aura::Utils
5
+
6
+ test "indir" do
7
+ assert in_dir?(Aura.gem_root('test/unit/utils_test.rb'), Aura.gem_root('test'))
8
+ assert ! in_dir?(Aura.gem_root('app/main.rb'), Aura.gem_root('test'))
9
+ assert ! in_dir?(Aura.gem_root('app/non/existent.rb'), Aura.gem_root('test'))
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ test.db
2
+ /pkg
3
+ *.swp
@@ -0,0 +1,18 @@
1
+ Copyright (c) 2009 Ryan Tomayko <tomayko.com/about>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to
5
+ deal in the Software without restriction, including without limitation the
6
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7
+ sell copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
16
+ THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,84 @@
1
+ Sinatra Sequel Extension
2
+ ========================
3
+
4
+ Extends [Sinatra](http://www.sinatrarb.com/) with a variety of extension methods
5
+ for dealing with a SQL database using the [Sequel ORM](http://sequel.rubyforge.org/).
6
+
7
+ Install the `sinatra-sequel` gem along with one of the database adapters:
8
+
9
+ sudo gem install sequel sinatra-sequel
10
+ sudo gem install sqlite3
11
+ sudo gem install mysql
12
+ sudo gem install postgres
13
+
14
+ I like to split database configuration and migrations out into a separate
15
+ `database.rb` file and then require it from the main app file, but you can plop
16
+ the following code in about anywhere and it'll work just fine:
17
+
18
+ require 'sinatra'
19
+ require 'sinatra/sequel'
20
+
21
+ # Establish the database connection; or, omit this and use the DATABASE_URL
22
+ # environment variable as the connection string:
23
+ set :database, 'sqlite://foo.db'
24
+
25
+ # At this point, you can access the Sequel Database object using the
26
+ # "database" object:
27
+ puts "the foos table doesn't exist" if !database.table_exists?('foos')
28
+
29
+ # define database migrations. pending migrations are run at startup and
30
+ # are guaranteed to run exactly once per database.
31
+ migration "create teh foos table" do
32
+ database.create_table :foos do
33
+ primary_key :id
34
+ text :bar
35
+ integer :baz, :default => 42
36
+ timestamp :bizzle, :null => false
37
+
38
+ index :baz, :unique => true
39
+ end
40
+ end
41
+
42
+ # you can also alter tables
43
+ migration "everything's better with bling" do
44
+ database.alter_table :foos do
45
+ drop_column :baz
46
+ add_column :bling, :float
47
+ end
48
+ end
49
+
50
+ # models just work ...
51
+ class Foo < Sequel::Model
52
+ many_to_one :bar
53
+ end
54
+
55
+ # see:
56
+ Foo.filter(:baz => 42).each { |foo| puts(foo.bar.name) }
57
+
58
+ # access the database within the context of an HTTP request
59
+ get '/foos/:id' do
60
+ @foo = database[:foos].filter(:id => params[:id]).first
61
+ erb :foos
62
+ end
63
+
64
+ # or, using the model
65
+ delete '/foos/:id' do
66
+ @foo = Foo[params[:id]]
67
+ @foo.delete
68
+ end
69
+
70
+ ### Sequel Reference Material
71
+
72
+ * The [Sequel README](http://sequel.rubyforge.org/rdoc/files/README_rdoc.html)
73
+ and [CHEATSHEET](http://sequel.rubyforge.org/rdoc/files/doc/cheat_sheet_rdoc.html)
74
+ are quite useful.
75
+
76
+ * Migrations are a light facade over Sequel's
77
+ [Schema module](http://sequel.rubyforge.org/rdoc/files/doc/schema_rdoc.html).
78
+ Like, [create_table](http://sequel.rubyforge.org/rdoc/classes/Sequel/Schema/Generator.html)
79
+ and [alter_table](http://sequel.rubyforge.org/rdoc/classes/Sequel/Schema/AlterTableGenerator.html).
80
+
81
+ * The best reference on Sequel Models is [the README](http://sequel.rubyforge.org/rdoc/files/README_rdoc.html)
82
+ and the [Associations](http://sequel.rubyforge.org/rdoc/files/doc/advanced_associations_rdoc.html) doc.
83
+ You might find this post on [many_to_many / one_to_one](http://steamcode.blogspot.com/2009/03/sequel-models-manytoone-onetomany.html)
84
+ useful.
@@ -0,0 +1,67 @@
1
+ require 'rake/clean'
2
+
3
+ task :default => :spec
4
+
5
+ desc 'Run specs'
6
+ task :spec do
7
+ sh 'bacon -a'
8
+ end
9
+
10
+ # PACKAGING ============================================================
11
+
12
+ if defined?(Gem)
13
+ # Load the gemspec using the same limitations as github
14
+ $spec = eval(File.read('sinatra-sequel.gemspec'))
15
+
16
+ def package(ext='')
17
+ "pkg/#{$spec.name}-#{$spec.version}" + ext
18
+ end
19
+
20
+ desc 'Build packages'
21
+ task :package => %w[.gem .tar.gz].map { |ext| package(ext) }
22
+
23
+ desc 'Build and install as local gem'
24
+ task :install => package('.gem') do
25
+ sh "gem install #{package('.gem')}"
26
+ end
27
+
28
+ directory 'pkg/'
29
+ CLOBBER.include('pkg')
30
+
31
+ file package('.gem') => %W[pkg/ #{$spec.name}.gemspec] + $spec.files do |f|
32
+ sh "gem build #{$spec.name}.gemspec"
33
+ mv File.basename(f.name), f.name
34
+ end
35
+
36
+ file package('.tar.gz') => %w[pkg/] + $spec.files do |f|
37
+ sh <<-SH
38
+ git archive \
39
+ --prefix=#{$spec.name}-#{$spec.version}/ \
40
+ --format=tar \
41
+ HEAD | gzip > #{f.name}
42
+ SH
43
+ end
44
+ end
45
+
46
+
47
+ # rebuild the gemspec manifest and update timestamps.
48
+ task "sinatra-sequel.gemspec" => FileList['{lib,spec}/**','Rakefile','COPYING','README.md'] do |f|
49
+ # read spec file and split out manifest section
50
+ spec = File.read(f.name)
51
+ head, manifest, tail = spec.split(" # = MANIFEST =\n")
52
+ # replace version and date
53
+ head.sub!(/\.date = '.*'/, ".date = '#{Date.today.to_s}'")
54
+ # determine file list from git ls-files
55
+ files = `git ls-files`.
56
+ split("\n").
57
+ sort.
58
+ reject{ |file| file =~ /^\./ }.
59
+ reject { |file| file =~ /^doc/ }.
60
+ map{ |file| " #{file}" }.
61
+ join("\n")
62
+ # piece file back together and write...
63
+ manifest = " s.files = %w[\n#{files}\n ]\n"
64
+ spec = [head,manifest,tail].join(" # = MANIFEST =\n")
65
+ File.open(f.name, 'w') { |io| io.write(spec) }
66
+ puts "updated #{f.name}"
67
+ end
@@ -0,0 +1,73 @@
1
+ require 'time'
2
+ require 'sinatra/base'
3
+ require 'sequel'
4
+
5
+ module Sinatra
6
+ module SequelHelper
7
+ def database
8
+ options.database
9
+ end
10
+ end
11
+
12
+ module SequelExtension
13
+ def database=(url)
14
+ @database = nil
15
+ set :database_url, url
16
+ database
17
+ end
18
+
19
+ def database
20
+ # MySQL's UTF-8 encoding is "utf8" without the hyphen.
21
+ is_mysql = database_url =~ /^mysql/
22
+ encoding = is_mysql ? "utf8" : "utf-8"
23
+
24
+ @database ||=
25
+ Sequel.connect(database_url, :encoding => encoding)
26
+ end
27
+
28
+ def migration(name, &block)
29
+ create_migrations_table
30
+ return if database[migrations_table_name].filter(:name => name).count > 0
31
+ migrations_log.puts "Running migration: #{name}"
32
+ database.transaction do
33
+ yield database
34
+ database[migrations_table_name] << { :name => name, :ran_at => Time.now }
35
+ end
36
+ end
37
+
38
+ Sequel::Database::ADAPTERS.each do |adapter|
39
+ define_method("#{adapter}?") { @database.database_type == adapter }
40
+ end
41
+
42
+ protected
43
+
44
+ def mysql?
45
+ defined?(Sequel::MySQL::Database) && database.kind_of?(Sequel::MySQL::Database)
46
+ end
47
+
48
+ def create_migrations_table
49
+ is_mysql = mysql?
50
+
51
+ database.create_table? :migrations do
52
+ primary_key :id
53
+
54
+ if is_mysql
55
+ # MySQL indices need a size, which Sequel doesn't seem to support.
56
+ String :name, :null => false
57
+ else
58
+ String :name, :null => false, :index => true
59
+ end
60
+ timestamp :ran_at
61
+ end
62
+ end
63
+
64
+ def self.registered(app)
65
+ app.set :database_url, lambda { ENV['DATABASE_URL'] || "sqlite://#{environment}.db" }
66
+ app.set :migrations_table_name, :migrations
67
+ app.set :migrations_log, lambda { STDOUT }
68
+ app.helpers SequelHelper
69
+ end
70
+ end
71
+
72
+ register SequelExtension
73
+ end
@@ -0,0 +1,39 @@
1
+ Gem::Specification.new do |s|
2
+ s.specification_version = 2 if s.respond_to? :specification_version=
3
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
4
+
5
+ s.name = 'sinatra-sequel'
6
+ s.version = '0.9.0'
7
+ s.date = '2009-08-08'
8
+
9
+ s.description = "Extends Sinatra with Sequel ORM config, migrations, and helpers"
10
+ s.summary = s.description
11
+
12
+ s.authors = ["Ryan Tomayko"]
13
+ s.email = "rtomayko@gmail.com"
14
+
15
+ # = MANIFEST =
16
+ s.files = %w[
17
+ COPYING
18
+ README.md
19
+ Rakefile
20
+ lib/sinatra/sequel.rb
21
+ sinatra-sequel.gemspec
22
+ spec/spec_sinatra_sequel.rb
23
+ ]
24
+ # = MANIFEST =
25
+
26
+ s.test_files = s.files.select {|path| path =~ /^spec\/.*.rb/ }
27
+
28
+ s.extra_rdoc_files = %w[README.md COPYING]
29
+ s.add_dependency 'sinatra', '>= 0.9.4'
30
+ s.add_dependency 'sequel', '>= 3.2.0'
31
+ s.add_development_dependency 'bacon'
32
+
33
+ s.has_rdoc = true
34
+ s.homepage = "http://github.com/rtomayko/sinatra-sequel"
35
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Sinatra::Sequel"]
36
+ s.require_paths = %w[lib]
37
+ s.rubyforge_project = 'wink'
38
+ s.rubygems_version = '1.1.1'
39
+ end
@@ -0,0 +1,70 @@
1
+ root = File.expand_path(File.dirname(__FILE__) + '/..')
2
+ $: << "#{root}/lib"
3
+
4
+ require 'sinatra/base'
5
+ require 'sinatra/sequel'
6
+
7
+ class MockSinatraApp < Sinatra::Base
8
+ register Sinatra::SequelExtension
9
+ end
10
+
11
+ describe 'A Sinatra app with Sequel extensions' do
12
+ before {
13
+ File.unlink 'test.db' rescue nil
14
+ ENV.delete('DATABASE_URL')
15
+ @app = Class.new(MockSinatraApp)
16
+ @app.set :migrations_log, File.open('/dev/null', 'wb')
17
+ }
18
+
19
+ it 'exposes the Sequel database object' do
20
+ @app.should.respond_to :database
21
+ end
22
+
23
+ it 'uses the DATABASE_URL environment variable if set' do
24
+ ENV['DATABASE_URL'] = 'sqlite://test-database-url.db'
25
+ @app.database_url.should.equal 'sqlite://test-database-url.db'
26
+ end
27
+
28
+ it 'uses sqlite://<environment>.db when no DATABASE_URL is defined' do
29
+ @app.environment = :foo
30
+ @app.database_url.should.equal "sqlite://foo.db"
31
+ end
32
+
33
+ it 'establishes a database connection when set' do
34
+ @app.database = 'sqlite://test.db'
35
+ @app.database.should.respond_to :table_exists?
36
+ end
37
+
38
+ it 'runs database migrations' do
39
+ @app.database = 'sqlite://test.db'
40
+ @app.migration 'create the foos table' do |db|
41
+ db.create_table :foos do
42
+ primary_key :id
43
+ text :foo
44
+ integer :bar
45
+ end
46
+ end
47
+
48
+ @app.database[:migrations].count.should.equal 1
49
+ @app.database.should.table_exists :foos
50
+ end
51
+
52
+ it 'does not run database migrations more than once' do
53
+ @app.database = 'sqlite://test.db'
54
+ @app.migration('this should run once') { }
55
+ @app.migration('this should run once') { fail }
56
+ @app.database[:migrations].count.should.equal 1
57
+ end
58
+
59
+ it 'allows you to query what adapter is being used' do
60
+ @app.database = 'sqlite://test.db'
61
+ @app.sqlite?.should.equal true
62
+ end
63
+
64
+
65
+ it 'exposes a query for all available sequel adapters' do
66
+ Sequel::Database::ADAPTERS.each do |adapter|
67
+ @app.should.respond_to "#{adapter}?"
68
+ end
69
+ end
70
+ end