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