saucy 0.1.3 → 0.1.4

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.
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