saucy 0.1.1
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/Gemfile +8 -0
- data/Gemfile.lock +106 -0
- data/README +9 -0
- data/app/controllers/accounts_controller.rb +57 -0
- data/app/controllers/invitations_controller.rb +36 -0
- data/app/controllers/memberships_controller.rb +9 -0
- data/app/controllers/permissions_controller.rb +17 -0
- data/app/controllers/plans_controller.rb +7 -0
- data/app/controllers/profiles_controller.rb +17 -0
- data/app/controllers/projects_controller.rb +56 -0
- data/app/models/account_membership.rb +8 -0
- data/app/models/invitation.rb +86 -0
- data/app/models/project_membership.rb +16 -0
- data/app/models/signup.rb +134 -0
- data/app/views/accounts/_account.html.erb +12 -0
- data/app/views/accounts/_blank_slate.html.erb +6 -0
- data/app/views/accounts/_projects.html.erb +12 -0
- data/app/views/accounts/_tab_bar.html.erb +8 -0
- data/app/views/accounts/edit.html.erb +17 -0
- data/app/views/accounts/index.html.erb +3 -0
- data/app/views/accounts/new.html.erb +26 -0
- data/app/views/invitation_mailer/invitation.text.erb +6 -0
- data/app/views/invitations/new.html.erb +11 -0
- data/app/views/invitations/show.html.erb +20 -0
- data/app/views/memberships/index.html.erb +16 -0
- data/app/views/permissions/edit.html.erb +15 -0
- data/app/views/plans/index.html.erb +3 -0
- data/app/views/profiles/_inputs.html.erb +6 -0
- data/app/views/profiles/edit.html.erb +35 -0
- data/app/views/projects/_form.html.erb +4 -0
- data/app/views/projects/edit.html.erb +18 -0
- data/app/views/projects/index.html.erb +13 -0
- data/app/views/projects/new.html.erb +11 -0
- data/config/routes.rb +18 -0
- data/features/run_features.feature +73 -0
- data/features/step_definitions/clearance_steps.rb +45 -0
- data/features/step_definitions/rails_steps.rb +70 -0
- data/features/support/env.rb +4 -0
- data/features/support/file.rb +11 -0
- data/lib/generators/saucy/base.rb +18 -0
- data/lib/generators/saucy/features/features_generator.rb +68 -0
- data/lib/generators/saucy/features/templates/factories.rb +55 -0
- data/lib/generators/saucy/features/templates/step_definitions/email_steps.rb +13 -0
- data/lib/generators/saucy/features/templates/step_definitions/factory_girl_steps.rb +1 -0
- data/lib/generators/saucy/features/templates/step_definitions/html_steps.rb +3 -0
- data/lib/generators/saucy/features/templates/step_definitions/project_steps.rb +4 -0
- data/lib/generators/saucy/features/templates/step_definitions/session_steps.rb +27 -0
- data/lib/generators/saucy/features/templates/step_definitions/user_steps.rb +54 -0
- data/lib/generators/saucy/install/install_generator.rb +36 -0
- data/lib/generators/saucy/install/templates/create_saucy_tables.rb +72 -0
- data/lib/generators/saucy/install/templates/models/account.rb +3 -0
- data/lib/generators/saucy/install/templates/models/invitation_mailer.rb +9 -0
- data/lib/generators/saucy/install/templates/models/plan.rb +3 -0
- data/lib/generators/saucy/install/templates/models/project.rb +3 -0
- data/lib/generators/saucy/views/views_generator.rb +23 -0
- data/lib/saucy.rb +7 -0
- data/lib/saucy/account.rb +50 -0
- data/lib/saucy/account_authorization.rb +34 -0
- data/lib/saucy/configuration.rb +12 -0
- data/lib/saucy/engine.rb +9 -0
- data/lib/saucy/layouts.rb +36 -0
- data/lib/saucy/plan.rb +11 -0
- data/lib/saucy/project.rb +39 -0
- data/lib/saucy/user.rb +37 -0
- data/spec/controllers/accounts_controller_spec.rb +204 -0
- data/spec/controllers/application_controller_spec.rb +27 -0
- data/spec/controllers/invitations_controller_spec.rb +155 -0
- data/spec/controllers/memberships_controller_spec.rb +33 -0
- data/spec/controllers/permissions_controller_spec.rb +69 -0
- data/spec/controllers/profiles_controller_spec.rb +43 -0
- data/spec/controllers/projects_controller_spec.rb +123 -0
- data/spec/layouts_spec.rb +21 -0
- data/spec/models/account_membership_spec.rb +13 -0
- data/spec/models/account_spec.rb +61 -0
- data/spec/models/invitation_spec.rb +160 -0
- data/spec/models/project_membership_spec.rb +26 -0
- data/spec/models/project_spec.rb +80 -0
- data/spec/models/signup_spec.rb +175 -0
- data/spec/models/user_spec.rb +96 -0
- data/spec/saucy_spec.rb +7 -0
- data/spec/spec_helper.rb +31 -0
- data/spec/support/authentication_helpers.rb +71 -0
- data/spec/support/authorization_helpers.rb +56 -0
- data/spec/support/clearance_matchers.rb +55 -0
- data/spec/views/accounts/_account.html.erb_spec.rb +66 -0
- metadata +203 -0
@@ -0,0 +1,45 @@
|
|
1
|
+
When /^I bootstrap the application for clearance$/ do
|
2
|
+
steps %{
|
3
|
+
When I remove the file "public/index.html"
|
4
|
+
And I successfully run "rails generate cucumber:install"
|
5
|
+
And I successfully run "rails generate clearance"
|
6
|
+
And I successfully run "rails generate clearance_features"
|
7
|
+
And I configure ActionMailer to use "localhost" as a host
|
8
|
+
And I add flash messages to the layout
|
9
|
+
And I add session links to the layout
|
10
|
+
And I configure "clearance/sessions#new" as the root route
|
11
|
+
And I disable Capybara Javascript emulation
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
When /^I add flash messages to the layout$/ do
|
16
|
+
flashes = %{
|
17
|
+
<% flash.each do |key, value| -%>
|
18
|
+
<%= value %>
|
19
|
+
<% end -%>
|
20
|
+
}
|
21
|
+
|
22
|
+
replace_in_file "app/views/layouts/application.html.erb",
|
23
|
+
/(<body>)/,
|
24
|
+
"\\1\n#{flashes}"
|
25
|
+
end
|
26
|
+
|
27
|
+
When /^I add session links to the layout$/ do
|
28
|
+
links = %{
|
29
|
+
<% if signed_in? -%>
|
30
|
+
<%= link_to 'Sign out', sign_out_path, :method => :delete %>
|
31
|
+
<% else -%>
|
32
|
+
<%= link_to 'Sign in', sign_in_path %>
|
33
|
+
<% end -%>
|
34
|
+
}
|
35
|
+
|
36
|
+
replace_in_file "app/views/layouts/application.html.erb",
|
37
|
+
/(<body>)/,
|
38
|
+
"\\1\n#{links}"
|
39
|
+
end
|
40
|
+
|
41
|
+
When /^I configure "([^"]*)" as the root route$/ do |action|
|
42
|
+
replace_in_file "config/routes.rb",
|
43
|
+
/(routes\.draw do)/,
|
44
|
+
"\\1\nroot :to => '#{action}'"
|
45
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
When /^I configure ActionMailer to use "([^"]+)" as a host$/ do |host|
|
2
|
+
mailer_config = "config.action_mailer.default_url_options = { :host => '#{host}' }"
|
3
|
+
replace_in_file "config/application.rb",
|
4
|
+
/(class .* < Rails::Application)/,
|
5
|
+
"\\1\n#{mailer_config}"
|
6
|
+
end
|
7
|
+
|
8
|
+
When /^I add the "([^"]*)" gem from this project as a dependency$/ do |gem_name|
|
9
|
+
append_to_file('Gemfile', %{\ngem "#{gem_name}", :path => "#{PROJECT_ROOT}"})
|
10
|
+
end
|
11
|
+
|
12
|
+
When /^I disable Capybara Javascript emulation$/ do
|
13
|
+
replace_in_file "features/support/env.rb",
|
14
|
+
%{require 'cucumber/rails/capybara_javascript_emulation'},
|
15
|
+
"# Disabled"
|
16
|
+
end
|
17
|
+
|
18
|
+
When /^I give a more detailed new account message$/ do
|
19
|
+
account_message = "Please sign up now."
|
20
|
+
replace_in_file 'app/views/accounts/new.html.erb',
|
21
|
+
%r{(</h2>)},
|
22
|
+
"\\1\n#{account_message}"
|
23
|
+
|
24
|
+
scenario = <<-HERE
|
25
|
+
Feature: The new account page should have a desperate message
|
26
|
+
Scenario: New account message
|
27
|
+
Given a plan exists with a name of "Free"
|
28
|
+
When I go to the sign up page for the "Free" plan
|
29
|
+
Then I should see "Please sign up now"
|
30
|
+
HERE
|
31
|
+
create_file('features/new_account_message.feature', scenario)
|
32
|
+
end
|
33
|
+
|
34
|
+
When /^I add a custom layout to the accounts index$/ do
|
35
|
+
in_current_dir do
|
36
|
+
FileUtils.cp("app/views/layouts/application.html.erb",
|
37
|
+
"app/views/layouts/custom.html.erb")
|
38
|
+
end
|
39
|
+
replace_in_file 'app/views/layouts/custom.html.erb',
|
40
|
+
%r{(<body>)},
|
41
|
+
"\\1\nCustom Layout Content"
|
42
|
+
layout_config = "config.saucy.layouts.accounts.index = 'custom'"
|
43
|
+
replace_in_file "config/application.rb",
|
44
|
+
/(class .* < Rails::Application)/,
|
45
|
+
"\\1\n#{layout_config}"
|
46
|
+
|
47
|
+
create_file('features/custom_accounts_index_layout.feature', <<-SCENARIO)
|
48
|
+
Feature: The accounts index should have a custom layout
|
49
|
+
Scenario: Custom layout
|
50
|
+
Given I am signed up and confirmed as "email@person.com/password"
|
51
|
+
And the following projects exist:
|
52
|
+
| name | account |
|
53
|
+
| ClothesPin | name: One |
|
54
|
+
| Talkr | name: Two |
|
55
|
+
| Fabio | name: One |
|
56
|
+
And "email@person.com" is a member of the "ClothesPin" project
|
57
|
+
And "email@person.com" is a member of the "Talkr" project
|
58
|
+
When I go to the sign in page
|
59
|
+
And I sign in as "email@person.com/password"
|
60
|
+
And I go to the dashboard page
|
61
|
+
Then I should see "Custom Layout Content"
|
62
|
+
SCENARIO
|
63
|
+
end
|
64
|
+
|
65
|
+
When /^I copy the specs for this project$/ do
|
66
|
+
in_current_dir do
|
67
|
+
FileUtils.cp_r(File.join(PROJECT_ROOT, 'spec'), '.')
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
require 'rails/generators/base'
|
3
|
+
|
4
|
+
module Saucy
|
5
|
+
module Generators
|
6
|
+
# Base generator for Saucy generators. Setups up the source root.
|
7
|
+
class Base < ::Rails::Generators::Base
|
8
|
+
# @return [String] source root for tempates within a saucy generator
|
9
|
+
def self.source_root
|
10
|
+
@_saucy_source_root ||=
|
11
|
+
File.expand_path(File.join(File.dirname(__FILE__),
|
12
|
+
generator_name,
|
13
|
+
'templates'))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'generators/saucy/base'
|
2
|
+
|
3
|
+
module Saucy
|
4
|
+
module Generators
|
5
|
+
class FeaturesGenerator < Base
|
6
|
+
|
7
|
+
desc <<DESC
|
8
|
+
Description:
|
9
|
+
Copy saucy cucumber features files to your application.
|
10
|
+
DESC
|
11
|
+
|
12
|
+
def copy_feature_files
|
13
|
+
directory "features", "features/saucy"
|
14
|
+
directory "step_definitions", "features/step_definitions/saucy"
|
15
|
+
template "README", "features/saucy/README"
|
16
|
+
template "README", "features/step_definitions/saucy/README"
|
17
|
+
empty_directory "spec"
|
18
|
+
empty_directory "spec/factories"
|
19
|
+
template "factories.rb", "spec/factories/saucy_factories.rb"
|
20
|
+
end
|
21
|
+
|
22
|
+
def remove_conflicting_files
|
23
|
+
remove_file "features/sign_up.feature"
|
24
|
+
remove_file "spec/factories/clearance.rb"
|
25
|
+
remove_file "test/factories/clearance.rb"
|
26
|
+
end
|
27
|
+
|
28
|
+
def create_paths
|
29
|
+
paths = <<-PATHS
|
30
|
+
when /^the memberships page for the "([^"]+)" account$/
|
31
|
+
account = Account.find_by_name!($1)
|
32
|
+
account_memberships_path(account)
|
33
|
+
when /^the projects page for the "([^"]+)" account$/
|
34
|
+
account = Account.find_by_name!($1)
|
35
|
+
account_projects_path(account)
|
36
|
+
when /settings page for the "([^"]+)" account$/i
|
37
|
+
account = Account.find_by_name!($1)
|
38
|
+
edit_account_path(account)
|
39
|
+
when /settings page$/
|
40
|
+
edit_profile_path
|
41
|
+
when /dashboard page$/
|
42
|
+
accounts_path
|
43
|
+
when /sign up page for the "([^"]+)" plan$/i
|
44
|
+
plan = Plan.find_by_name!($1)
|
45
|
+
new_plan_account_path(plan)
|
46
|
+
PATHS
|
47
|
+
|
48
|
+
replace_in_file "features/support/paths.rb",
|
49
|
+
"case page_name",
|
50
|
+
"case page_name\n#{paths}"
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def replace_in_file(relative_path, find, replace)
|
56
|
+
path = File.join(destination_root, relative_path)
|
57
|
+
contents = IO.read(path)
|
58
|
+
unless contents.gsub!(find, replace)
|
59
|
+
raise "#{find.inspect} not found in #{relative_path}"
|
60
|
+
end
|
61
|
+
File.open(path, "w") { |file| file.write(contents) }
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
|
@@ -0,0 +1,55 @@
|
|
1
|
+
Factory.sequence :email do |n|
|
2
|
+
"user#{n}@example.com"
|
3
|
+
end
|
4
|
+
|
5
|
+
Factory.sequence :name do |n|
|
6
|
+
"name#{n}"
|
7
|
+
end
|
8
|
+
|
9
|
+
Factory.define :user do |user|
|
10
|
+
user.name { "test user" }
|
11
|
+
user.email { Factory.next :email }
|
12
|
+
user.password { "password" }
|
13
|
+
user.password_confirmation { "password" }
|
14
|
+
end
|
15
|
+
|
16
|
+
Factory.define :email_confirmed_user, :parent => :user do |user|
|
17
|
+
user.email_confirmed { true }
|
18
|
+
end
|
19
|
+
|
20
|
+
Factory.define :account do |f|
|
21
|
+
f.name { Factory.next(:name) }
|
22
|
+
f.url { Factory.next(:name) }
|
23
|
+
end
|
24
|
+
|
25
|
+
Factory.define :account_membership do |f|
|
26
|
+
f.association :user
|
27
|
+
f.association :account
|
28
|
+
end
|
29
|
+
|
30
|
+
Factory.define :signup do |f|
|
31
|
+
f.account_name { Factory.next(:name) }
|
32
|
+
f.url { Factory.next(:name) }
|
33
|
+
f.user_name { "test user" }
|
34
|
+
f.email { Factory.next :email }
|
35
|
+
f.password { "password" }
|
36
|
+
f.password_confirmation { "password" }
|
37
|
+
end
|
38
|
+
|
39
|
+
Factory.define :project do |f|
|
40
|
+
f.association :account
|
41
|
+
end
|
42
|
+
|
43
|
+
Factory.define :project_membership do |f|
|
44
|
+
f.association :user
|
45
|
+
f.project {|a| a.association(:project, :account => a.user.account)}
|
46
|
+
end
|
47
|
+
|
48
|
+
Factory.define :invitation do |f|
|
49
|
+
f.email { Factory.next(:email) }
|
50
|
+
f.association :account
|
51
|
+
end
|
52
|
+
|
53
|
+
Factory.define :plan do |f|
|
54
|
+
f.name 'Free'
|
55
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
When /^I follow the link sent to "([^"]+)"$/ do |email_address|
|
2
|
+
email = ActionMailer::Base.deliveries.detect do |tmail|
|
3
|
+
tmail.to.include?(email_address)
|
4
|
+
end or raise "No email sent to #{email_address}"
|
5
|
+
|
6
|
+
unless match = email.body.match(%r{http://\S+})
|
7
|
+
raise "No link included in the email:\n#{email.body}"
|
8
|
+
end
|
9
|
+
url = match[0]
|
10
|
+
|
11
|
+
visit url
|
12
|
+
end
|
13
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'factory_girl/step_definitions'
|
@@ -0,0 +1,27 @@
|
|
1
|
+
Given /^I (?:am signed in|sign in) as an admin of the "([^"]+)" project$/ do |project_name|
|
2
|
+
project = Project.find_by_name!(project_name)
|
3
|
+
user = Factory(:email_confirmed_user)
|
4
|
+
Factory(:account_membership, :user => user, :account => project.account, :admin => true)
|
5
|
+
Factory(:project_membership, :user => user, :project => project)
|
6
|
+
When %{I sign in as "#{user.email}"}
|
7
|
+
end
|
8
|
+
|
9
|
+
Given /^I am signed in as an admin of the "([^"]*)" account$/ do |account_name|
|
10
|
+
account = Account.find_by_name!(account_name)
|
11
|
+
user = Factory(:email_confirmed_user)
|
12
|
+
Factory(:account_membership, :user => user,
|
13
|
+
:account => account,
|
14
|
+
:admin => true)
|
15
|
+
When %{I sign in as "#{user.email}"}
|
16
|
+
end
|
17
|
+
|
18
|
+
When /^I sign in as "([^"\/]*)"$/ do |email|
|
19
|
+
user = User.find_by_email!(email)
|
20
|
+
user.update_attributes!(:password => 'test', :password_confirmation => 'test')
|
21
|
+
When %{I sign in as "#{email}/test"}
|
22
|
+
end
|
23
|
+
|
24
|
+
Given /^I am signed in$/ do
|
25
|
+
user = Factory(:email_confirmed_user)
|
26
|
+
When %{I sign in as "#{user.email}"}
|
27
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
Given /^"([^"]*)" is a member of the "([^"]*)" project$/ do |email, project_name|
|
2
|
+
user = User.find_by_email!(email)
|
3
|
+
project = Project.find_by_name!(project_name)
|
4
|
+
Factory(:account_membership, :user => user, :account => project.account)
|
5
|
+
Factory(:project_membership, :user => user, :project => project)
|
6
|
+
end
|
7
|
+
|
8
|
+
Given /^"([^"]*)" is a member of the "([^"]*)" account/ do |email, account_name|
|
9
|
+
user = User.find_by_email!(email)
|
10
|
+
account = Account.find_by_name!(account_name)
|
11
|
+
Factory(:account_membership, :user => user, :account => account)
|
12
|
+
end
|
13
|
+
|
14
|
+
Given /^"([^"]*)" is an admin of the "([^"]*)" account/ do |email, account_name|
|
15
|
+
user = User.find_by_email!(email)
|
16
|
+
account = Account.find_by_name!(account_name)
|
17
|
+
Factory(:account_membership, :user => user, :account => account, :admin => true)
|
18
|
+
end
|
19
|
+
|
20
|
+
Then /^the user "([^"]*)" should be an admin of "([^"]*)"$/ do |email, account_name|
|
21
|
+
user = User.find_by_email!(email)
|
22
|
+
account = Account.find_by_name!(account_name)
|
23
|
+
user.should be_admin_of(account)
|
24
|
+
end
|
25
|
+
|
26
|
+
Given /^the user "([^"]*)" exists under the "([^"]*)" account$/ do |email, account_name|
|
27
|
+
Given %{a user exists with an email of "#{email}"}
|
28
|
+
Given %{"#{email}" is a member of the "#{account_name}" account}
|
29
|
+
end
|
30
|
+
|
31
|
+
When /^I fill in the following new user:$/ do |table|
|
32
|
+
within "fieldset.new_user" do
|
33
|
+
table.transpose.hashes.first.each do |field, value|
|
34
|
+
fill_in field, :with => value
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
When /^I fill in the following existing user:$/ do |table|
|
40
|
+
within "fieldset.existing_user" do
|
41
|
+
table.transpose.hashes.first.each do |field, value|
|
42
|
+
fill_in field, :with => value
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
Then /^"([^"]*)" should be a member of the "([^"]*)" account$/ do |email, account_name|
|
48
|
+
User.find_by_email!(email).should be_member_of(Account.find_by_name!(account_name))
|
49
|
+
end
|
50
|
+
|
51
|
+
Then /^"([^"]*)" should be an admin member of the "([^"]*)" account$/ do |email, account_name|
|
52
|
+
User.find_by_email!(email).should be_admin_of(Account.find_by_name!(account_name))
|
53
|
+
end
|
54
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'generators/saucy/base'
|
2
|
+
require 'rails/generators/active_record/migration'
|
3
|
+
|
4
|
+
module Saucy
|
5
|
+
module Generators
|
6
|
+
class InstallGenerator < Base
|
7
|
+
include Rails::Generators::Migration
|
8
|
+
extend ActiveRecord::Generators::Migration
|
9
|
+
|
10
|
+
desc <<DESC
|
11
|
+
Description:
|
12
|
+
Copy saucy files to your application.
|
13
|
+
DESC
|
14
|
+
|
15
|
+
def generate_migration
|
16
|
+
migration_template "create_saucy_tables.rb", "db/migrate/create_saucy_tables.rb"
|
17
|
+
end
|
18
|
+
|
19
|
+
def create_models
|
20
|
+
directory "models", "app/models"
|
21
|
+
end
|
22
|
+
|
23
|
+
def update_user_model
|
24
|
+
insert_into_file "app/models/user.rb",
|
25
|
+
"\ninclude Saucy::User",
|
26
|
+
:after => "include Clearance::User"
|
27
|
+
end
|
28
|
+
|
29
|
+
def add_account_authorization
|
30
|
+
insert_into_file "app/controllers/application_controller.rb",
|
31
|
+
"\ninclude Saucy::AccountAuthorization",
|
32
|
+
:after => "include Clearance::Authentication"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
class CreateSaucyTables < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :account_memberships do |table|
|
4
|
+
table.integer :account_id
|
5
|
+
table.integer :user_id
|
6
|
+
table.boolean :admin
|
7
|
+
table.datetime :created_at
|
8
|
+
table.datetime :updated_at
|
9
|
+
end
|
10
|
+
|
11
|
+
add_index :account_memberships, [:account_id, :user_id], :unique => true
|
12
|
+
|
13
|
+
create_table :accounts do |table|
|
14
|
+
table.belongs_to :plan
|
15
|
+
table.string :name
|
16
|
+
table.string :url
|
17
|
+
table.datetime :created_at
|
18
|
+
table.datetime :updated_at
|
19
|
+
end
|
20
|
+
add_index :accounts, :plan_id
|
21
|
+
|
22
|
+
create_table :invitations do |table|
|
23
|
+
table.string :email
|
24
|
+
table.integer :account_id
|
25
|
+
table.boolean :admin
|
26
|
+
table.datetime :created_at
|
27
|
+
table.datetime :updated_at
|
28
|
+
end
|
29
|
+
|
30
|
+
add_index :invitations, [:account_id]
|
31
|
+
|
32
|
+
create_table :project_memberships do |table|
|
33
|
+
table.integer :user_id
|
34
|
+
table.integer :project_id
|
35
|
+
table.datetime :created_at
|
36
|
+
table.datetime :updated_at
|
37
|
+
end
|
38
|
+
|
39
|
+
add_index :project_memberships, [:user_id, :project_id]
|
40
|
+
|
41
|
+
create_table :projects do |table|
|
42
|
+
table.string :name
|
43
|
+
table.integer :account_id
|
44
|
+
table.datetime :created_at
|
45
|
+
table.datetime :updated_at
|
46
|
+
end
|
47
|
+
|
48
|
+
alter_table :users do |table|
|
49
|
+
table.string :name, :default => ""
|
50
|
+
end
|
51
|
+
|
52
|
+
create_table :plans do |t|
|
53
|
+
t.string :name
|
54
|
+
t.integer :price
|
55
|
+
|
56
|
+
t.timestamps
|
57
|
+
end
|
58
|
+
|
59
|
+
add_index :plans, :name
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.down
|
63
|
+
remove_column :users, :name
|
64
|
+
drop_table :plans
|
65
|
+
drop_table :projects
|
66
|
+
drop_table :project_memberships
|
67
|
+
drop_table :invitations
|
68
|
+
drop_table :accounts
|
69
|
+
drop_table :account_memberships
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|