saucy 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/Gemfile +15 -1
  2. data/Gemfile.lock +67 -1
  3. data/Rakefile +26 -0
  4. data/app/controllers/memberships_controller.rb +33 -1
  5. data/app/models/invitation.rb +1 -1
  6. data/app/models/membership.rb +22 -0
  7. data/app/models/permission.rb +17 -0
  8. data/app/models/signup.rb +3 -3
  9. data/app/views/memberships/edit.html.erb +18 -0
  10. data/app/views/memberships/index.html.erb +4 -4
  11. data/config/routes.rb +2 -3
  12. data/features/run_features.feature +4 -3
  13. data/features/step_definitions/rails_steps.rb +3 -0
  14. data/lib/generators/saucy/features/templates/factories.rb +4 -4
  15. data/lib/generators/saucy/features/templates/step_definitions/session_steps.rb +6 -3
  16. data/lib/generators/saucy/features/templates/step_definitions/user_steps.rb +6 -4
  17. data/lib/generators/saucy/install/templates/create_saucy_tables.rb +8 -6
  18. data/lib/saucy/account.rb +9 -5
  19. data/lib/saucy/project.rb +28 -5
  20. data/lib/saucy/user.rb +5 -12
  21. data/spec/controllers/memberships_controller_spec.rb +87 -5
  22. data/spec/environment.rb +91 -0
  23. data/spec/models/account_spec.rb +17 -6
  24. data/spec/models/membership_spec.rb +37 -0
  25. data/spec/models/permission_spec.rb +19 -0
  26. data/spec/models/project_spec.rb +39 -9
  27. data/spec/models/user_spec.rb +16 -42
  28. data/spec/scaffold/config/routes.rb +5 -0
  29. data/spec/spec_helper.rb +8 -1
  30. data/spec/support/authentication_helpers.rb +16 -6
  31. metadata +75 -74
  32. data/app/controllers/permissions_controller.rb +0 -17
  33. data/app/models/account_membership.rb +0 -8
  34. data/app/models/project_membership.rb +0 -14
  35. data/app/views/permissions/edit.html.erb +0 -15
  36. data/spec/controllers/permissions_controller_spec.rb +0 -69
  37. data/spec/models/account_membership_spec.rb +0 -13
  38. data/spec/models/project_membership_spec.rb +0 -22
data/Gemfile CHANGED
@@ -2,7 +2,21 @@ source "http://rubygems.org"
2
2
  gem "cucumber"
3
3
  gem "aruba"
4
4
  gem "rake"
5
- gem "rspec", :require => false
5
+ gem "rspec-rails", :require => false
6
6
  gem "rails", ">= 3.0.3"
7
7
  gem "thin"
8
+ gem "clearance", "0.9.0.rc9", :require => false
9
+ gem "shoulda", :require => false
10
+ gem "bourne", :require => false
11
+ gem "sqlite3-ruby", :require => false
12
+ gem "factory_girl", :require => false
13
+
14
+ # used by the rails app in cucumber
15
+ gem "cucumber-rails", :require => false
16
+ gem "capybara", :require => false
17
+ gem "factory_girl_rails", :require => false
18
+ gem "formtastic", :require => false
19
+ gem "database_cleaner", :require => false
20
+ gem "dynamic_form", :require => false
21
+ gem "launchy", :require => false
8
22
 
data/Gemfile.lock CHANGED
@@ -33,29 +33,68 @@ GEM
33
33
  background_process
34
34
  cucumber (~> 0.9.4)
35
35
  background_process (1.2)
36
+ bourne (1.0)
37
+ mocha (= 0.9.8)
36
38
  builder (2.1.2)
39
+ capybara (0.4.0)
40
+ celerity (>= 0.7.9)
41
+ culerity (>= 0.2.4)
42
+ mime-types (>= 1.16)
43
+ nokogiri (>= 1.3.3)
44
+ rack (>= 1.0.0)
45
+ rack-test (>= 0.5.4)
46
+ selenium-webdriver (>= 0.0.27)
47
+ xpath (~> 0.1.2)
48
+ celerity (0.8.5)
49
+ childprocess (0.1.4)
50
+ ffi (~> 0.6.3)
51
+ clearance (0.9.0.rc9)
52
+ rails (~> 3.0.0)
53
+ configuration (1.2.0)
37
54
  cucumber (0.9.4)
38
55
  builder (~> 2.1.2)
39
56
  diff-lcs (~> 1.1.2)
40
57
  gherkin (~> 2.2.9)
41
58
  json (~> 1.4.6)
42
59
  term-ansicolor (~> 1.0.5)
60
+ cucumber-rails (0.3.2)
61
+ cucumber (>= 0.8.0)
62
+ culerity (0.2.12)
43
63
  daemons (1.1.0)
64
+ database_cleaner (0.6.0)
44
65
  diff-lcs (1.1.2)
66
+ dynamic_form (1.1.3)
45
67
  erubis (2.6.6)
46
68
  abstract (>= 1.0.0)
47
69
  eventmachine (0.12.10)
70
+ factory_girl (1.3.2)
71
+ factory_girl_rails (1.0)
72
+ factory_girl (~> 1.3)
73
+ rails (>= 3.0.0.beta4)
74
+ ffi (0.6.3)
75
+ rake (>= 0.8.7)
76
+ formtastic (1.2.2)
77
+ actionpack (>= 2.3.7)
78
+ activesupport (>= 2.3.7)
79
+ i18n (>= 0.4.0)
48
80
  gherkin (2.2.9)
49
81
  json (~> 1.4.6)
50
82
  term-ansicolor (~> 1.0.5)
51
83
  i18n (0.5.0)
52
84
  json (1.4.6)
85
+ json_pure (1.4.6)
86
+ launchy (0.3.7)
87
+ configuration (>= 0.0.5)
88
+ rake (>= 0.8.1)
53
89
  mail (2.2.11)
54
90
  activesupport (>= 2.3.6)
55
91
  i18n (~> 0.5.0)
56
92
  mime-types (~> 1.16)
57
93
  treetop (~> 1.4.8)
58
94
  mime-types (1.16)
95
+ mocha (0.9.8)
96
+ rake
97
+ nokogiri (1.4.4)
59
98
  polyglot (0.3.1)
60
99
  rack (1.2.1)
61
100
  rack-mount (0.6.13)
@@ -84,6 +123,19 @@ GEM
84
123
  rspec-expectations (2.2.0)
85
124
  diff-lcs (~> 1.1.2)
86
125
  rspec-mocks (2.2.0)
126
+ rspec-rails (2.2.1)
127
+ actionpack (~> 3.0)
128
+ activesupport (~> 3.0)
129
+ railties (~> 3.0)
130
+ rspec (~> 2.2.0)
131
+ rubyzip (0.9.4)
132
+ selenium-webdriver (0.1.1)
133
+ childprocess (= 0.1.4)
134
+ ffi (~> 0.6.3)
135
+ json_pure
136
+ rubyzip
137
+ shoulda (2.11.3)
138
+ sqlite3-ruby (1.3.2)
87
139
  term-ansicolor (1.0.5)
88
140
  thin (1.2.7)
89
141
  daemons (>= 1.0.9)
@@ -93,14 +145,28 @@ GEM
93
145
  treetop (1.4.9)
94
146
  polyglot (>= 0.3.1)
95
147
  tzinfo (0.3.23)
148
+ xpath (0.1.2)
149
+ nokogiri (~> 1.3)
96
150
 
97
151
  PLATFORMS
98
152
  ruby
99
153
 
100
154
  DEPENDENCIES
101
155
  aruba
156
+ bourne
157
+ capybara
158
+ clearance (= 0.9.0.rc9)
102
159
  cucumber
160
+ cucumber-rails
161
+ database_cleaner
162
+ dynamic_form
163
+ factory_girl
164
+ factory_girl_rails
165
+ formtastic
166
+ launchy
103
167
  rails (>= 3.0.3)
104
168
  rake
105
- rspec
169
+ rspec-rails
170
+ shoulda
171
+ sqlite3-ruby
106
172
  thin
data/Rakefile ADDED
@@ -0,0 +1,26 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'rake'
4
+ require 'rake/gempackagetask'
5
+ require 'cucumber/rake/task'
6
+ require 'rspec/core/rake_task'
7
+
8
+ desc 'Default: run all tests'
9
+ task :default => [:spec, :cucumber]
10
+
11
+ Cucumber::Rake::Task.new(:cucumber) do |t|
12
+ t.fork = true
13
+ t.cucumber_opts = ['--format', (ENV['CUCUMBER_FORMAT'] || 'progress')]
14
+ end
15
+
16
+ RSpec::Core::RakeTask.new do |t|
17
+ t.pattern = "spec/**/*_spec.rb"
18
+ t.rspec_opts = "--format progress"
19
+ end
20
+
21
+ eval("$specification = begin; #{IO.read('saucy.gemspec')}; end")
22
+ Rake::GemPackageTask.new($specification) do |package|
23
+ package.need_zip = true
24
+ package.need_tar = true
25
+ end
26
+
@@ -3,7 +3,39 @@ class MembershipsController < ApplicationController
3
3
  layout Saucy::Layouts.to_proc
4
4
 
5
5
  def index
6
- @users = current_account.users_by_name
6
+ @memberships = current_account.memberships_by_name
7
7
  render
8
8
  end
9
+
10
+ def edit
11
+ find_membership
12
+ @projects = current_account.projects_by_name
13
+ render
14
+ end
15
+
16
+ def update
17
+ find_membership.update_attributes!(params[:membership])
18
+ flash[:success] = "Permissions updated."
19
+ redirect_to account_memberships_url(current_account)
20
+ end
21
+
22
+ def destroy
23
+ find_membership.destroy
24
+ flash[:success] = "User removed."
25
+ redirect_to account_memberships_url(current_account)
26
+ end
27
+
28
+ private
29
+
30
+ def find_membership
31
+ @membership ||= Membership.find(params[:id], :include => :account)
32
+ end
33
+
34
+ def current_account
35
+ if params[:id]
36
+ find_membership.account
37
+ else
38
+ super
39
+ end
40
+ end
9
41
  end
@@ -22,7 +22,7 @@ class Invitation < ActiveRecord::Base
22
22
  @user = existing_user || new_user
23
23
  if valid?
24
24
  @user.save!
25
- @user.account_memberships.create!(:account => account, :admin => admin)
25
+ @user.memberships.create!(:account => account, :admin => admin)
26
26
  end
27
27
  end
28
28
 
@@ -0,0 +1,22 @@
1
+ class Membership < ActiveRecord::Base
2
+ belongs_to :user
3
+ belongs_to :account
4
+ has_many :permissions
5
+ has_many :projects, :through => :permissions
6
+
7
+ validates_presence_of :user_id
8
+ validates_presence_of :account_id
9
+ validates_uniqueness_of :user_id, :scope => :account_id
10
+
11
+ def name
12
+ user.name
13
+ end
14
+
15
+ def email
16
+ user.email
17
+ end
18
+
19
+ def self.by_name
20
+ joins(:user).order('users.name')
21
+ end
22
+ end
@@ -0,0 +1,17 @@
1
+ class Permission < ActiveRecord::Base
2
+ belongs_to :membership
3
+ belongs_to :project
4
+ belongs_to :user
5
+
6
+ before_validation :assign_user_id_from_membership
7
+
8
+ def user=(ignored)
9
+ raise NotImplementedError, "Use Permission#membership= instead"
10
+ end
11
+
12
+ private
13
+
14
+ def assign_user_id_from_membership
15
+ self.user_id = membership.user_id
16
+ end
17
+ end
data/app/models/signup.rb CHANGED
@@ -66,8 +66,8 @@ class Signup
66
66
  @existing_user ||= User.find_by_email(email)
67
67
  end
68
68
 
69
- def account_membership
70
- @account_membership ||= AccountMembership.new(:user => user,
69
+ def membership
70
+ @membership ||= Membership.new(:user => user,
71
71
  :account => account,
72
72
  :admin => true)
73
73
  end
@@ -128,7 +128,7 @@ class Signup
128
128
  Account.transaction do
129
129
  account.save!
130
130
  user.save!
131
- account_membership.save!
131
+ membership.save!
132
132
  end
133
133
  end
134
134
  end
@@ -0,0 +1,18 @@
1
+ <h2>Permissions for <span><%= @membership.name %></span> on <%= current_account.name %></h2>
2
+
3
+ <%= render :partial => 'accounts/tab_bar' %>
4
+
5
+ <%= semantic_form_for @membership do |form| -%>
6
+ <%= form.inputs do -%>
7
+ <%= form.input :admin %>
8
+ <%= form.input :projects, :as => :check_boxes, :collection => @projects %>
9
+ <% end -%>
10
+ <%= form.buttons do -%>
11
+ <%= form.commit_button "Update" %>
12
+ <li><%= link_to "Remove from account",
13
+ @membership,
14
+ :method => :delete,
15
+ :confirm => "Are you sure?" %></li>
16
+ <% end -%>
17
+ <% end -%>
18
+
@@ -3,10 +3,10 @@
3
3
  <%= render :partial => 'accounts/tab_bar' %>
4
4
 
5
5
  <ul class="users">
6
- <% @users.each do |user| -%>
7
- <%= content_tag_for :li, user do -%>
8
- <%= link_to edit_account_user_permissions_path(current_account, user) do %>
9
- <%= user.name %> (<%= user.email %>)
6
+ <% @memberships.each do |membership| -%>
7
+ <%= content_tag_for :li, membership.user do -%>
8
+ <%= link_to [:edit, membership] do %>
9
+ <%= membership.name %> (<%= membership.email %>)
10
10
  <% end -%>
11
11
  <% end -%>
12
12
  <% end -%>
data/config/routes.rb CHANGED
@@ -3,11 +3,10 @@ Rails.application.routes.draw do
3
3
  resources :projects, :only => [:new, :create, :index, :show]
4
4
  resources :memberships, :only => [:index]
5
5
  resources :invitations, :only => [:new, :create]
6
- resources :users, :only => [] do
7
- resource :permissions, :only => [:edit, :update]
8
- end
9
6
  end
10
7
 
8
+ resources :memberships, :only => [:edit, :update, :destroy]
9
+
11
10
  resources :plans, :only => [:index] do
12
11
  resources :accounts, :only => [:new, :create]
13
12
  end
@@ -1,4 +1,4 @@
1
- @puts @announce @disable-bundler
1
+ @disable-bundler @puts @announce
2
2
  Feature: generate a saucy application and run rake
3
3
 
4
4
  Background:
@@ -16,9 +16,10 @@ Feature: generate a saucy application and run rake
16
16
  gem "rspec-rails"
17
17
  gem "bourne"
18
18
  gem "shoulda"
19
+ gem "launchy"
19
20
  """
20
21
  When I add the "saucy" gem from this project as a dependency
21
- And I successfully run "bundle install"
22
+ And I successfully run "bundle install --local"
22
23
  And I bootstrap the application for clearance
23
24
 
24
25
  Scenario: generate a saucy application and run rake
@@ -70,4 +71,4 @@ Feature: generate a saucy application and run rake
70
71
  """
71
72
  0 failures
72
73
  """
73
- Then the output should not contain "0 examples"
74
+ Then at least one example should have run
@@ -68,3 +68,6 @@ When /^I copy the specs for this project$/ do
68
68
  end
69
69
  end
70
70
 
71
+ Then /^at least one example should have run$/ do
72
+ Then %{the output should match /[1-9]0? examples/}
73
+ end
@@ -22,7 +22,7 @@ Factory.define :account do |f|
22
22
  f.url { Factory.next(:name) }
23
23
  end
24
24
 
25
- Factory.define :account_membership do |f|
25
+ Factory.define :membership do |f|
26
26
  f.association :user
27
27
  f.association :account
28
28
  end
@@ -40,9 +40,9 @@ Factory.define :project do |f|
40
40
  f.association :account
41
41
  end
42
42
 
43
- Factory.define :project_membership do |f|
44
- f.association :user
45
- f.project {|a| a.association(:project, :account => a.user.account)}
43
+ Factory.define :permission do |f|
44
+ f.association :membership
45
+ f.project {|a| a.association(:project, :account => a.membership.account)}
46
46
  end
47
47
 
48
48
  Factory.define :invitation do |f|
@@ -1,15 +1,18 @@
1
1
  Given /^I (?:am signed in|sign in) as an admin of the "([^"]+)" project$/ do |project_name|
2
2
  project = Project.find_by_name!(project_name)
3
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)
4
+ membership = Factory(:membership, :user => user,
5
+ :account => project.account,
6
+ :admin => true)
7
+ Factory(:permission, :membership => membership,
8
+ :project => project)
6
9
  When %{I sign in as "#{user.email}"}
7
10
  end
8
11
 
9
12
  Given /^I am signed in as an admin of the "([^"]*)" account$/ do |account_name|
10
13
  account = Account.find_by_name!(account_name)
11
14
  user = Factory(:email_confirmed_user)
12
- Factory(:account_membership, :user => user,
15
+ Factory(:membership, :user => user,
13
16
  :account => account,
14
17
  :admin => true)
15
18
  When %{I sign in as "#{user.email}"}
@@ -1,20 +1,22 @@
1
1
  Given /^"([^"]*)" is a member of the "([^"]*)" project$/ do |email, project_name|
2
2
  user = User.find_by_email!(email)
3
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)
4
+ membership = Factory(:membership, :user => user,
5
+ :account => project.account)
6
+ Factory(:permission, :membership => membership,
7
+ :project => project)
6
8
  end
7
9
 
8
10
  Given /^"([^"]*)" is a member of the "([^"]*)" account/ do |email, account_name|
9
11
  user = User.find_by_email!(email)
10
12
  account = Account.find_by_name!(account_name)
11
- Factory(:account_membership, :user => user, :account => account)
13
+ Factory(:membership, :user => user, :account => account)
12
14
  end
13
15
 
14
16
  Given /^"([^"]*)" is an admin of the "([^"]*)" account/ do |email, account_name|
15
17
  user = User.find_by_email!(email)
16
18
  account = Account.find_by_name!(account_name)
17
- Factory(:account_membership, :user => user, :account => account, :admin => true)
19
+ Factory(:membership, :user => user, :account => account, :admin => true)
18
20
  end
19
21
 
20
22
  Then /^the user "([^"]*)" should be an admin of "([^"]*)"$/ do |email, account_name|
@@ -1,6 +1,6 @@
1
1
  class CreateSaucyTables < ActiveRecord::Migration
2
2
  def self.up
3
- create_table :account_memberships do |table|
3
+ create_table :memberships do |table|
4
4
  table.integer :account_id
5
5
  table.integer :user_id
6
6
  table.boolean :admin
@@ -8,7 +8,7 @@ class CreateSaucyTables < ActiveRecord::Migration
8
8
  table.datetime :updated_at
9
9
  end
10
10
 
11
- add_index :account_memberships, [:account_id, :user_id], :unique => true
11
+ add_index :memberships, [:account_id, :user_id], :unique => true
12
12
 
13
13
  create_table :accounts do |table|
14
14
  table.belongs_to :plan
@@ -29,14 +29,16 @@ class CreateSaucyTables < ActiveRecord::Migration
29
29
 
30
30
  add_index :invitations, [:account_id]
31
31
 
32
- create_table :project_memberships do |table|
32
+ create_table :permissions do |table|
33
+ table.integer :membership_id
33
34
  table.integer :user_id
34
35
  table.integer :project_id
35
36
  table.datetime :created_at
36
37
  table.datetime :updated_at
37
38
  end
38
39
 
39
- add_index :project_memberships, [:user_id, :project_id]
40
+ add_index :permissions, [:user_id, :project_id]
41
+ add_index :permissions, [:membership_id, :project_id], :name => [:membership_and_project]
40
42
 
41
43
  create_table :projects do |table|
42
44
  table.string :name
@@ -63,10 +65,10 @@ class CreateSaucyTables < ActiveRecord::Migration
63
65
  remove_column :users, :name
64
66
  drop_table :plans
65
67
  drop_table :projects
66
- drop_table :project_memberships
68
+ drop_table :permissions
67
69
  drop_table :invitations
68
70
  drop_table :accounts
69
- drop_table :account_memberships
71
+ drop_table :memberships
70
72
  end
71
73
  end
72
74