mack-data_mapper 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/README +3 -0
  2. data/lib/helpers/orm_helpers.rb +47 -0
  3. data/lib/mack-data_mapper.rb +45 -0
  4. data/lib/mack-data_mapper_tasks.rb +3 -0
  5. data/lib/migration_generator/migration_generator.rb +41 -0
  6. data/lib/migration_generator/templates/db/migrations/%=@migration_name%.rb.template +31 -0
  7. data/lib/model_generator/manifest.yml +11 -0
  8. data/lib/model_generator/model_generator.rb +54 -0
  9. data/lib/model_generator/templates/model.rb.template +11 -0
  10. data/lib/model_generator/templates/test.rb.template +9 -0
  11. data/lib/scaffold_generator/manifest.yml +24 -0
  12. data/lib/scaffold_generator/scaffold_generator.rb +41 -0
  13. data/lib/scaffold_generator/templates/app/controllers/controller.rb.template +50 -0
  14. data/lib/scaffold_generator/templates/app/views/edit.html.erb.template +19 -0
  15. data/lib/scaffold_generator/templates/app/views/index.html.erb.template +41 -0
  16. data/lib/scaffold_generator/templates/app/views/new.html.erb.template +19 -0
  17. data/lib/scaffold_generator/templates/app/views/show.html.erb.template +12 -0
  18. data/lib/scaffold_generator/templates/test.rb.template +9 -0
  19. data/lib/tasks/db_create_drop_tasks.rake +76 -0
  20. data/lib/tasks/db_migration_tasks.rake +83 -0
  21. data/test/database.yml +3 -0
  22. data/test/fixtures/add_users_migration.rb.fixture +9 -0
  23. data/test/fixtures/album.rb.fixture +4 -0
  24. data/test/fixtures/album_unit_test.rb.fixture +9 -0
  25. data/test/fixtures/album_with_cols.rb.fixture +7 -0
  26. data/test/fixtures/create_users_migration.rb.fixture +12 -0
  27. data/test/fixtures/routes.rb.fixture +3 -0
  28. data/test/fixtures/zoo_no_cols/edit.html.erb.fixture +11 -0
  29. data/test/fixtures/zoo_no_cols/index.html.erb.fixture +20 -0
  30. data/test/fixtures/zoo_no_cols/new.html.erb.fixture +11 -0
  31. data/test/fixtures/zoo_no_cols/show.html.erb.fixture +6 -0
  32. data/test/fixtures/zoo_with_cols/edit.html.erb.fixture +19 -0
  33. data/test/fixtures/zoo_with_cols/index.html.erb.fixture +26 -0
  34. data/test/fixtures/zoo_with_cols/new.html.erb.fixture +19 -0
  35. data/test/fixtures/zoo_with_cols/show.html.erb.fixture +22 -0
  36. data/test/fixtures/zoo_with_cols/zoo.rb.fixture +4 -0
  37. data/test/fixtures/zoo_with_cols/zoos_controller.rb.fixture +50 -0
  38. data/test/generators/migration_generator_test.rb +71 -0
  39. data/test/generators/model_generator_test.rb +37 -0
  40. data/test/generators/scaffold_generator_test.rb +61 -0
  41. data/test/lib/user.rb +6 -0
  42. data/test/tasks/db_migration_tasks_test.rb +57 -0
  43. data/test/test_helper.rb +76 -0
  44. metadata +117 -0
data/README ADDED
@@ -0,0 +1,3 @@
1
+ README
2
+ ========================================================================
3
+ mack-data_mapper was developed by: markbates
@@ -0,0 +1,47 @@
1
+ module Mack
2
+ module ViewHelpers
3
+ module OrmHelpers
4
+ DEFAULT_PARTIAL = %{
5
+ <div>
6
+ <div class="errorExplanation" id="errorExplanation">
7
+ <h2><%= pluralize_word(errors.size, "error") %> occured.</h2>
8
+ <ul>
9
+ <% for error in errors %>
10
+ <li><%= error %></li>
11
+ <% end %>
12
+ </ul>
13
+ </div>
14
+ </div>
15
+ }
16
+
17
+ def error_messages_for(object_names = [], view_partial = nil)
18
+ object_names = [object_names].flatten
19
+ app_errors = []
20
+ object_names.each do |name|
21
+ object = instance_variable_get("@#{name}")
22
+ if object
23
+ if object.is_a?(DataMapper::Persistence)
24
+ app_errors << object.errors.full_messages
25
+ end
26
+ end
27
+ end
28
+ app_errors.flatten!
29
+ File.join(Mack::Configuration.views_directory, "application", "_error_messages.html.erb")
30
+ unless app_errors.empty?
31
+ if view_partial.nil?
32
+ if File.exist?(File.join(Mack::Configuration.views_directory, "application", "_error_messages.html.erb"))
33
+ render :partial => "application/error_messages", :locals => {:errors => app_errors}
34
+ else
35
+ render :text => DEFAULT_PARTIAL, :locals => {:errors => app_errors}
36
+ end
37
+ else
38
+ render :partial => view_partial, :locals => {:errors => app_errors}
39
+ end
40
+ else
41
+ ""
42
+ end
43
+ end
44
+ # self.include_safely_into(Mack::ViewBinder)
45
+ end # OrmHelpers
46
+ end # ViewHelpers
47
+ end # Mack
@@ -0,0 +1,45 @@
1
+ require 'rubygems'
2
+ require 'genosaurus'
3
+ require 'erubis'
4
+ begin
5
+ require 'mack-orm_common'
6
+ rescue Exception => e
7
+ end
8
+
9
+ gem("datamapper", "0.3.2")
10
+ require 'data_mapper'
11
+
12
+ module Mack
13
+ module Configuration
14
+
15
+ def self.load_database_configurations(env = Mack::Configuration.env)
16
+ dbs = Mack::Configuration.database_configurations
17
+ unless dbs.nil?
18
+ settings = dbs[env]
19
+ settings.symbolize_keys!
20
+ if settings[:default]
21
+ settings.each do |k,v|
22
+ DataMapper::Database.setup(k, v.symbolize_keys)
23
+ end
24
+ else
25
+ DataMapper::Database.setup(settings)
26
+ end
27
+ end
28
+ end # load_database_configurations
29
+
30
+ end # Configuration
31
+ end # Mack
32
+
33
+
34
+ Mack::Configuration.load_database_configurations
35
+
36
+ class SchemaInfo # :nodoc:
37
+ include DataMapper::Persistence
38
+
39
+ property :version, :integer, :default => 0
40
+ end
41
+
42
+ [:helpers, :migration_generator, :model_generator, :scaffold_generator].each do |folder|
43
+ Dir.glob(File.join(File.dirname(__FILE__), folder.to_s, "**/*.rb")).each {|f| require f}
44
+ end
45
+ # Dir.glob(File.join(File.dirname(__FILE__), "tasks", "**/*.rake")).each {|f| load f}
@@ -0,0 +1,3 @@
1
+ Dir.glob(File.join(File.dirname(__FILE__), "tasks", "*.rake")).each do |f|
2
+ load(f)
3
+ end
@@ -0,0 +1,41 @@
1
+ # This will generate a migration for your application.
2
+ #
3
+ # Example without columns:
4
+ # rake generate:migration name=create_users
5
+ #
6
+ # db/migrations/<number>_create_users.rb:
7
+ # class CreateUsers < DataMapper::Migration
8
+ # self.up
9
+ # end
10
+ #
11
+ # self.down
12
+ # end
13
+ # end
14
+ #
15
+ # Example with columns:
16
+ # rake generate:migration name=create_users cols=username:string,email_address:string,created_at:datetime,updated_at:datetime
17
+ #
18
+ # db/migrations/<number>_create_users.rb:
19
+ # class CreateUsers < DataMapper::Migration
20
+ # self.up
21
+ # create_table :users do |t|
22
+ # t.column :username, :string
23
+ # t.column :email_address, :string
24
+ # t.column :created_at, :datetime
25
+ # t.column :updated_at, :datetime
26
+ # end
27
+ #
28
+ # self.down
29
+ # drop_table :users
30
+ # end
31
+ # end
32
+ class MigrationGenerator < Genosaurus
33
+
34
+ require_param :name
35
+
36
+ def setup
37
+ @table_name = param(:name).underscore.plural.gsub("create_", "")
38
+ @migration_name = "#{next_migration_number}_#{param(:name).underscore}"
39
+ end
40
+
41
+ end
@@ -0,0 +1,31 @@
1
+ class <%= param(:name).camelcase %> < DataMapper::Migration
2
+
3
+ def self.up
4
+ <%
5
+ unless columns.empty?
6
+ -%>
7
+ create_table :<%= @table_name %> do |t|
8
+ <%
9
+ for column in columns
10
+ -%>
11
+ t.column :<%= column.column_name %>, :<%= column.column_type %>
12
+ <%
13
+ end
14
+ -%>
15
+ end
16
+ <%
17
+ end
18
+ -%>
19
+ end
20
+
21
+ def self.down
22
+ <%
23
+ unless columns.empty?
24
+ -%>
25
+ drop_table :<%= @table_name %>
26
+ <%
27
+ end
28
+ -%>
29
+ end
30
+
31
+ end
@@ -0,0 +1,11 @@
1
+ models_directory:
2
+ type: directory
3
+ output_path: <%= File.join("app", "models") %>
4
+ model_template:
5
+ type: file
6
+ template_path: <%= File.join(templates_directory_path, "model.rb.template") %>
7
+ output_path: <%= File.join("app", "models", "#{param(:name).singular.underscore}.rb") %>
8
+ test_template:
9
+ type: file
10
+ template_path: <%= File.join(templates_directory_path, "test.rb.template") %>
11
+ output_path: <%= File.join("test", "unit", "#{param(:name).singular.underscore}_test.rb") %>
@@ -0,0 +1,54 @@
1
+ # This will generate an ORM 'model' for your application based on the specified ORM you're using.
2
+ #
3
+ # Example without columns:
4
+ # rake generate:model name=user
5
+ #
6
+ # app/models/user.rb:
7
+ # class User
8
+ # include DataMapper::Persistence
9
+ #
10
+ # end
11
+ # db/migrations/<number>_create_users.rb:
12
+ # class CreateUsers < DataMapper::Migration
13
+ # self.up
14
+ # end
15
+ #
16
+ # self.down
17
+ # end
18
+ # end
19
+ #
20
+ # Example with columns:
21
+ # rake generate:model name=user cols=username:string,email_address:string,created_at:datetime,updated_at:datetime
22
+ #
23
+ # app/models/user.rb:
24
+ # class User
25
+ # include DataMapper::Persistence
26
+ #
27
+ # property :username, :string
28
+ # property :email_address, :string
29
+ # property :created_at, :datetime
30
+ # property :updated_at, :datetime
31
+ # end
32
+ # db/migrations/<number>_create_users.rb:
33
+ # class CreateUsers < DataMapper::Migration
34
+ # self.up
35
+ # create_table :users do |t|
36
+ # t.column :username, :string
37
+ # t.column :email_address, :string
38
+ # t.column :created_at, :datetime
39
+ # t.column :updated_at, :datetime
40
+ # end
41
+ #
42
+ # self.down
43
+ # drop_table :users
44
+ # end
45
+ # end
46
+ class ModelGenerator < Genosaurus
47
+
48
+ require_param :name
49
+
50
+ def after_generate
51
+ MigrationGenerator.run(@options.merge({"name" => "create_#{param(:name).plural}"}))
52
+ end
53
+
54
+ end
@@ -0,0 +1,11 @@
1
+ class <%= param(:name).singular.camelcase %>
2
+ include DataMapper::Persistence
3
+
4
+ <%
5
+ for column in columns
6
+ -%>
7
+ property :<%= column.column_name %>, :<%= column.column_type %>
8
+ <%
9
+ end
10
+ -%>
11
+ end
@@ -0,0 +1,9 @@
1
+ require File.dirname(__FILE__) + '/../test_helper.rb'
2
+
3
+ class <%= param(:name).singular.camelcase %>Test < Test::Unit::TestCase
4
+
5
+ def test_truth
6
+ assert true
7
+ end
8
+
9
+ end
@@ -0,0 +1,24 @@
1
+ controller_template:
2
+ type: file
3
+ template_path: <%= File.join(templates_directory_path, "app", "controllers", "controller.rb.template") %>
4
+ output_path: <%= File.join("app", "controllers", "#{@name_plural}_controller.rb") %>
5
+ edit_template:
6
+ type: file
7
+ template_path: <%= File.join(templates_directory_path, "app", "views", "edit.html.erb.template") %>
8
+ output_path: <%= File.join("app", "views", @name_plural, "edit.html.erb") %>
9
+ index_template:
10
+ type: file
11
+ template_path: <%= File.join(templates_directory_path, "app", "views", "index.html.erb.template") %>
12
+ output_path: <%= File.join("app", "views", @name_plural, "index.html.erb") %>
13
+ new_template:
14
+ type: file
15
+ template_path: <%= File.join(templates_directory_path, "app", "views", "new.html.erb.template") %>
16
+ output_path: <%= File.join("app", "views", @name_plural, "new.html.erb") %>
17
+ show_template:
18
+ type: file
19
+ template_path: <%= File.join(templates_directory_path, "app", "views", "show.html.erb.template") %>
20
+ output_path: <%= File.join("app", "views", @name_plural, "show.html.erb") %>
21
+ functional_teat_template:
22
+ type: file
23
+ template_path: <%= File.join(templates_directory_path, "test.rb.template") %>
24
+ output_path: <%= File.join("test", "functional", "#{@name_plural}_controller_test.rb") %>
@@ -0,0 +1,41 @@
1
+ # Generates scaffold for Mack applications.
2
+ #
3
+ # Example:
4
+ # rake generate:scaffold name=post
5
+ class ScaffoldGenerator < Genosaurus
6
+
7
+ require_param :name
8
+
9
+ def setup
10
+ @name_singular = param(:name).singular.underscore
11
+ @name_plural = param(:name).plural.underscore
12
+ @name_singular_camel = @name_singular.camelcase
13
+ @name_plural_camel = @name_plural.camelcase
14
+ end
15
+
16
+ def after_generate
17
+ ModelGenerator.run(@options)
18
+ update_routes_file
19
+ end
20
+
21
+ def update_routes_file
22
+ # update routes.rb
23
+ routes = File.join(Mack::Configuration.config_directory, "routes.rb")
24
+ rf = File.open(routes).read
25
+ unless rf.match(".resource :#{@name_plural}")
26
+ puts "Updating routes.rb"
27
+ nrf = ""
28
+ rf.each do |line|
29
+ if line.match("Mack::Routes.build")
30
+ x = line.match(/\|(.+)\|/).captures
31
+ line << "\n #{x}.resource :#{@name_plural} # Added by rake generate:scaffold name=#{param(:name)}\n"
32
+ end
33
+ nrf << line
34
+ end
35
+ File.open(routes, "w") do |f|
36
+ f.puts nrf
37
+ end
38
+ end
39
+ end
40
+
41
+ end
@@ -0,0 +1,50 @@
1
+ class <%= @name_plural_camel %>Controller < Mack::Controller::Base
2
+
3
+ # GET /<%= @name_plural %>
4
+ def index
5
+ @<%= @name_plural %> = <%= @name_singular_camel %>.find(:all)
6
+ end
7
+
8
+ # GET /<%= @name_plural %>/1
9
+ def show
10
+ @<%= @name_singular %> = <%= @name_singular_camel %>.find(params(:id))
11
+ end
12
+
13
+ # GET /<%= @name_plural %>/new
14
+ def new
15
+ @<%= @name_singular %> = <%= @name_singular_camel %>.new
16
+ end
17
+
18
+ # GET /<%= @name_plural %>/1/edit
19
+ def edit
20
+ @<%= @name_singular %> = <%= @name_singular_camel %>.find(params(:id))
21
+ end
22
+
23
+ # POST /<%= @name_plural %>
24
+ def create
25
+ @<%= @name_singular %> = <%= @name_singular_camel %>.new(params(:<%= @name_singular %>))
26
+ if @<%= @name_singular %>.save
27
+ redirect_to(<%= @name_plural %>_show_url(:id => @<%= @name_singular %>.id))
28
+ else
29
+ render(:action => "new")
30
+ end
31
+ end
32
+
33
+ # PUT /<%= @name_plural %>/1
34
+ def update
35
+ @<%= @name_singular %> = <%= @name_singular_camel %>.find(params(:id))
36
+ if @<%= @name_singular %>.update_attributes(params(:<%= @name_singular %>))
37
+ redirect_to(<%= @name_plural %>_show_url(:id => @<%= @name_singular %>.id))
38
+ else
39
+ render(:action => "edit")
40
+ end
41
+ end
42
+
43
+ # DELETE /<%= @name_plural %>/1
44
+ def delete
45
+ @<%= @name_singular %> = <%= @name_singular_camel %>.find(params(:id))
46
+ @<%= @name_singular %>.destroy!
47
+ redirect_to(<%= @name_plural %>_index_url)
48
+ end
49
+
50
+ end
@@ -0,0 +1,19 @@
1
+ <h1>Edit <%= @name_singular_camel %></h1>
2
+
3
+ <%%= error_messages_for :<%= @name_singular %> %>
4
+
5
+ <%% form(<%= @name_singular %>s_update_url(:id => @<%= @name_singular %>.id), :class => "edit_<%= @name_singular %>", :id => "edit_<%= @name_singular %>", :method => :put) do %>
6
+ <% for column in columns -%>
7
+ <% unless column.column_name == "created_at" || column.column_name == "updated_at" -%>
8
+ <p>
9
+ <b><%= column.column_name.singular.camelcase %></b><br />
10
+ <%= column.form_field %>
11
+ </p>
12
+ <% end -%>
13
+ <% end -%>
14
+ <p>
15
+ <input id="<%= @name_singular %>_submit" name="commit" type="submit" value="Update" />
16
+ </p>
17
+ <%% end %>
18
+
19
+ <%%= link_to("Back", <%= @name_singular %>s_index_url) %>
@@ -0,0 +1,41 @@
1
+ <h1>Listing <%= @name_plural_camel %></h1>
2
+
3
+ <table>
4
+ <tr>
5
+ <%
6
+ unless columns.empty?
7
+ columns.each do |col|
8
+ -%>
9
+ <th><%= col.column_name.camelcase %></th>
10
+ <%
11
+ end
12
+ else
13
+ -%>
14
+ <th>&nbsp;</th>
15
+ <%
16
+ end
17
+ -%>
18
+ </tr>
19
+
20
+ <%% for <%= @name_singular %> in @<%= @name_plural %> %>
21
+ <tr>
22
+ <%
23
+ unless columns.empty?
24
+ columns.each do |col| -%>
25
+ <td><%%= <%= @name_singular %>.<%= col.column_name %> %></td>
26
+ <%
27
+ end
28
+ else
29
+ -%>
30
+ <td>&nbsp;</td>
31
+ <% end -%>
32
+ <td><%%= link_to("Show", <%= @name_plural %>_show_url(:id => <%= @name_singular %>.id)) %></td>
33
+ <td><%%= link_to("Edit", <%= @name_plural %>_edit_url(:id => <%= @name_singular %>.id)) %></td>
34
+ <td><%%= link_to("Delete", <%= @name_plural %>_delete_url(:id => <%= @name_singular %>.id), :method => :delete, :confirm => "Are you sure?") %></td>
35
+ </tr>
36
+ <%% end %>
37
+ </table>
38
+
39
+ <br />
40
+
41
+ <%%= link_to("New <%= @name_singular_camel %>", <%= @name_plural %>_new_url) %>
@@ -0,0 +1,19 @@
1
+ <h1>New <%= @name_singular_camel %></h1>
2
+
3
+ <%%= error_messages_for :<%= @name_singular %> %>
4
+
5
+ <%% form(<%= @name_singular %>s_create_url, :class => "new_<%= @name_singular %>", :id => "new_<%= @name_singular %>") do %>
6
+ <% for column in columns -%>
7
+ <% unless column.column_name == "created_at" || column.column_name == "updated_at" -%>
8
+ <p>
9
+ <b><%= column.column_name.singular.camelcase %></b><br />
10
+ <%= column.form_field %>
11
+ </p>
12
+ <% end -%>
13
+ <% end -%>
14
+ <p>
15
+ <input id="<%= @name_singular %>_submit" name="commit" type="submit" value="Create" />
16
+ </p>
17
+ <%% end %>
18
+
19
+ <%%= link_to("Back", <%= @name_singular %>s_index_url) %>
@@ -0,0 +1,12 @@
1
+ <p>
2
+ <h1><%= @name_singular_camel %></h1>
3
+ </p>
4
+ <% for column in columns -%>
5
+ <p>
6
+ <b><%= column.column_name.singular.camelcase %></b><br />
7
+ <%%= @<%= @name_singular %>.<%= column.column_name %> %>
8
+ </p>
9
+ <% end -%>
10
+
11
+ <%%= link_to("Edit", <%= @name_plural %>_edit_url(:id => @<%= @name_singular %>.id)) %> |
12
+ <%%= link_to("Back", <%= @name_plural %>_index_url) %>
@@ -0,0 +1,9 @@
1
+ require File.dirname(__FILE__) + '/../test_helper.rb'
2
+
3
+ class <%= @name_plural_camel %>ControllerTest < Test::Unit::TestCase
4
+
5
+ def test_truth
6
+ assert true
7
+ end
8
+
9
+ end
@@ -0,0 +1,76 @@
1
+ require 'rake'
2
+ namespace :db do
3
+
4
+ desc "Create the database for your environment."
5
+ task :create => :environment do
6
+ Mack::Configuration.load_database_configurations(Mack::Configuration.env)
7
+ database(:default) do
8
+ drop_create_database
9
+ end
10
+ end
11
+
12
+ namespace :create do
13
+
14
+ desc "Creates your Full environment. Does NOT create your production database!"
15
+ task :all => :environment do
16
+ Mack::Configuration.load_database_configurations("test")
17
+ database(:default) do
18
+ drop_create_database
19
+ end
20
+ Mack::Configuration.load_database_configurations("development")
21
+ database(:default) do
22
+ drop_create_database
23
+ end
24
+ Rake::Task["db:migrate"].invoke
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+
31
+ private
32
+ def drop_create_database
33
+ configuration = database.adapter.instance_variable_get('@configuration')
34
+ case database.adapter.class.name
35
+ when "DataMapper::Adapters::MysqlAdapter"
36
+ DataMapper::Database.setup(:tmp, {
37
+ :adapter => "mysql",
38
+ :host => "localhost",
39
+ :database => "mysql",
40
+ :username => ENV["DB_USERNAME"] || "root",
41
+ :password => ENV["DB_PASSWORD"] || ""
42
+ })
43
+ database(:tmp) do
44
+ puts "Dropping (MySQL): #{configuration.database}"
45
+ database.execute "DROP DATABASE IF EXISTS `#{configuration.database}`"
46
+ puts "Creating (MySQL): #{configuration.database}"
47
+ database.execute "CREATE DATABASE `#{configuration.database}` DEFAULT CHARACTER SET `utf8`"
48
+ begin
49
+ database.adapter.flush_connections!
50
+ rescue Exception => e
51
+ end
52
+ end
53
+ when "DataMapper::Adapters::PostgresqlAdapter"
54
+ ENV['PGHOST'] = configuration.host if configuration.host
55
+ ENV['PGPORT'] = configuration.port.to_s if configuration.port
56
+ ENV['PGPASSWORD'] = configuration.password.to_s if configuration.password
57
+
58
+ database.adapter.flush_connections!
59
+ begin
60
+ puts "Dropping (PostgreSQL): #{configuration.database}"
61
+ `dropdb -U "#{configuration.username}" #{configuration.database}`
62
+ rescue Exception => e
63
+ end
64
+
65
+ begin
66
+ puts "Creating (PostgreSQL): #{configuration.database}"
67
+ `createdb -U "#{configuration.username}" #{configuration.database}`
68
+ rescue Exception => e
69
+ end
70
+ when 'DataMapper::Adapters::Sqlite3Adapter'
71
+ puts "Dropping (SQLite3): #{configuration.database}"
72
+ FileUtils.rm_rf(configuration.database)
73
+ else
74
+ raise "Task not supported for '#{database.adapter}'"
75
+ end
76
+ end
@@ -0,0 +1,83 @@
1
+ require 'rake'
2
+ namespace :db do
3
+
4
+ desc "Migrate the database through scripts in db/migrations"
5
+ task :migrate => "db:schema:create" do
6
+ migration_files.each do |migration|
7
+ require migration
8
+ migration = File.basename(migration, ".rb")
9
+ m_number = migration_number(migration)
10
+ if m_number > @schema_info.version
11
+ migration_name(migration).camelcase.constantize.up
12
+ @schema_info.version += 1
13
+ @schema_info.save
14
+ end
15
+ end # each
16
+ end # migrate
17
+
18
+ desc "Rolls the schema back to the previous version. Specify the number of steps with STEP=n"
19
+ task :rollback => ["db:schema:create", "db:abort_if_pending_migrations"] do
20
+ migrations = migration_files.reverse
21
+ (ENV["STEP"] || 1).to_i.times do |step|
22
+ migration = migrations[step]
23
+ require migration
24
+ migration = File.basename(migration, ".rb")
25
+ m_number = migration_number(migration)
26
+ if m_number == @schema_info.version
27
+ migration_name(migration).camelcase.constantize.down
28
+ @schema_info.version -= 1
29
+ @schema_info.save
30
+ end
31
+ end
32
+
33
+ end # rollback
34
+
35
+ desc "Raises an error if there are pending migrations"
36
+ task :abort_if_pending_migrations do
37
+ migrations = migration_files.reverse
38
+ return if migrations.empty?
39
+ migration = migrations.first
40
+ migration = File.basename(migration, ".rb")
41
+ m_number = migration_number(migration)
42
+ if m_number > @schema_info.version
43
+ raise Mack::Errors::UnrunMigrations.new(m_number - @schema_info.version)
44
+ end
45
+ end
46
+
47
+ desc "Displays the current schema version of your database"
48
+ task :version => "db:schema:create" do
49
+ puts "\nYour database is currently at version: #{@schema_info.version}\n"
50
+ end
51
+
52
+ private
53
+ namespace :schema do
54
+
55
+ task :create => "mack:environment" do
56
+ require 'data_mapper/migration'
57
+ unless SchemaInfo.table.exists?
58
+ class SchemaInfo
59
+ include DataMapper::Persistence
60
+ property :version, :integer
61
+ end
62
+ SchemaInfo.auto_migrate!
63
+ SchemaInfo.create(:version => 0, :id => 1)
64
+ end
65
+ @schema_info = SchemaInfo.first
66
+ end # create
67
+
68
+ end # schema
69
+
70
+
71
+ def migration_files
72
+ Dir.glob(File.join(Mack::Configuration.root, "db", "migrations", "*.rb"))
73
+ end
74
+
75
+ def migration_number(migration)
76
+ migration.match(/(^\d+)/).captures.last.to_i
77
+ end
78
+
79
+ def migration_name(migration)
80
+ migration.match(/^\d+_(.+)/).captures.last
81
+ end
82
+
83
+ end # db
data/test/database.yml ADDED
@@ -0,0 +1,3 @@
1
+ test:
2
+ adapter: sqlite3
3
+ database: <%= File.join(Mack::Configuration.root, "mack-data_mapper_test.db") %>
@@ -0,0 +1,9 @@
1
+ class AddUsers < DataMapper::Migration
2
+ def self.up
3
+ User.create(:username => "markbates", :email => "mark@mackframework.com")
4
+ end
5
+
6
+ def self.down
7
+ User.delete_all
8
+ end
9
+ end
@@ -0,0 +1,4 @@
1
+ class Album
2
+ include DataMapper::Persistence
3
+
4
+ end