devise_invitations 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7aac54a0d1a5d67f8a773fc598199289e6365b32
4
+ data.tar.gz: 6c54a34bd81348aa616628c776a05cfd545d88d7
5
+ SHA512:
6
+ metadata.gz: 3c83fcc55964355ae244cd81c401baa549a9a43a6dfb63a6609152fd7cf378ad318baecf058b6712a20e14bc17452d31e4dae83054f106393454610b61eafb9c
7
+ data.tar.gz: 484c2973f4247f5335773e28c370d1a61db1197e047a4524a8c0473c9bf52593e517a39d3f6f6dac37d81c4e2009424f205779c338a6e4ec4c7894e392533f4a
@@ -0,0 +1,3 @@
1
+ test_app/
2
+ .DS_Store
3
+ *.gem
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
3
+
4
+ gem 'rake', '~> 10.4'
@@ -0,0 +1,116 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ devise_invitations (0.1)
5
+ devise_invitable (~> 1.5)
6
+ faker (~> 1.6)
7
+ has_secure_token (~> 1.0)
8
+ shoulda-matchers (~> 2.0)
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ actionmailer (4.2.5)
14
+ actionpack (= 4.2.5)
15
+ actionview (= 4.2.5)
16
+ activejob (= 4.2.5)
17
+ mail (~> 2.5, >= 2.5.4)
18
+ rails-dom-testing (~> 1.0, >= 1.0.5)
19
+ actionpack (4.2.5)
20
+ actionview (= 4.2.5)
21
+ activesupport (= 4.2.5)
22
+ rack (~> 1.6)
23
+ rack-test (~> 0.6.2)
24
+ rails-dom-testing (~> 1.0, >= 1.0.5)
25
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
26
+ actionview (4.2.5)
27
+ activesupport (= 4.2.5)
28
+ builder (~> 3.1)
29
+ erubis (~> 2.7.0)
30
+ rails-dom-testing (~> 1.0, >= 1.0.5)
31
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
32
+ activejob (4.2.5)
33
+ activesupport (= 4.2.5)
34
+ globalid (>= 0.3.0)
35
+ activemodel (4.2.5)
36
+ activesupport (= 4.2.5)
37
+ builder (~> 3.1)
38
+ activerecord (4.2.5)
39
+ activemodel (= 4.2.5)
40
+ activesupport (= 4.2.5)
41
+ arel (~> 6.0)
42
+ activesupport (4.2.5)
43
+ i18n (~> 0.7)
44
+ json (~> 1.7, >= 1.7.7)
45
+ minitest (~> 5.1)
46
+ thread_safe (~> 0.3, >= 0.3.4)
47
+ tzinfo (~> 1.1)
48
+ arel (6.0.3)
49
+ bcrypt (3.1.10)
50
+ builder (3.2.2)
51
+ devise (3.5.4)
52
+ bcrypt (~> 3.0)
53
+ orm_adapter (~> 0.1)
54
+ railties (>= 3.2.6, < 5)
55
+ responders
56
+ thread_safe (~> 0.1)
57
+ warden (~> 1.2.3)
58
+ devise_invitable (1.5.5)
59
+ actionmailer (>= 3.2.6, < 5)
60
+ devise (>= 3.2.0)
61
+ erubis (2.7.0)
62
+ faker (1.6.1)
63
+ i18n (~> 0.5)
64
+ globalid (0.3.6)
65
+ activesupport (>= 4.1.0)
66
+ has_secure_token (1.0.0)
67
+ activerecord (>= 3.0)
68
+ i18n (0.7.0)
69
+ json (1.8.3)
70
+ loofah (2.0.3)
71
+ nokogiri (>= 1.5.9)
72
+ mail (2.6.3)
73
+ mime-types (>= 1.16, < 3)
74
+ mime-types (2.99)
75
+ mini_portile2 (2.0.0)
76
+ minitest (5.8.3)
77
+ nokogiri (1.6.7.1)
78
+ mini_portile2 (~> 2.0.0.rc2)
79
+ orm_adapter (0.5.0)
80
+ rack (1.6.4)
81
+ rack-test (0.6.3)
82
+ rack (>= 1.0)
83
+ rails-deprecated_sanitizer (1.0.3)
84
+ activesupport (>= 4.2.0.alpha)
85
+ rails-dom-testing (1.0.7)
86
+ activesupport (>= 4.2.0.beta, < 5.0)
87
+ nokogiri (~> 1.6.0)
88
+ rails-deprecated_sanitizer (>= 1.0.1)
89
+ rails-html-sanitizer (1.0.2)
90
+ loofah (~> 2.0)
91
+ railties (4.2.5)
92
+ actionpack (= 4.2.5)
93
+ activesupport (= 4.2.5)
94
+ rake (>= 0.8.7)
95
+ thor (>= 0.18.1, < 2.0)
96
+ rake (10.5.0)
97
+ responders (2.1.1)
98
+ railties (>= 4.2.0, < 5.1)
99
+ shoulda-matchers (2.8.0)
100
+ activesupport (>= 3.0.0)
101
+ thor (0.19.1)
102
+ thread_safe (0.3.5)
103
+ tzinfo (1.2.2)
104
+ thread_safe (~> 0.1)
105
+ warden (1.2.4)
106
+ rack (>= 1.0)
107
+
108
+ PLATFORMS
109
+ ruby
110
+
111
+ DEPENDENCIES
112
+ devise_invitations!
113
+ rake (~> 10.4)
114
+
115
+ BUNDLED WITH
116
+ 1.11.2
data/LICENSE ADDED
@@ -0,0 +1,9 @@
1
+ Copyright (c) 2016 Roxas Shadow <webmaster@giovannicapuano.net> All rights reserved.
2
+
3
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
4
+
5
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
6
+
7
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8
+
9
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,46 @@
1
+ [![Circle CI](https://circleci.com/gh/RoxasShadow/devise_invitations.svg?style=svg)](https://circleci.com/gh/RoxasShadow/devise_invitations)
2
+
3
+ DeviseInvitable
4
+ ===============
5
+ Allow multiple invitations on top of [devise_invitable](https://github.com/scambra/devise_invitable).
6
+
7
+ Why?
8
+ ----
9
+ Basically devise_invitable, by design, can't handle multiple invitations, since it doesn't use any support table but creates a new hidden `User` for every invitation, storing there both the inviter (through the polymorphic column `sent_by`) and the token.
10
+
11
+ This means that one user is invitable once and only once.
12
+ This means that you'll find many hidden `User`s that probably will never sign up your website.
13
+
14
+ So what?
15
+ --------
16
+ So let's create a new table that allows an email address to be invited multiple times by different people, allowing the user to ignore them and sign up normally or, instead, choosing which invitation mail s?he wants to accept. Invitations are not deleted after the related user signs up the website, and they'll be flagged too (`pending` are all the invitations sent, `accepted` is an invitation that has been accepted by an user and `ignored` are the invitations ignored by the user since s?he accepted the one marked as `accepted`).
17
+
18
+ But *devise_invitable* is useful!
19
+ ---------------------------------
20
+ I know, in fact I'm creating nothing but a layer on top of it. You still need and use *devise_invitable* (I mean, views, controller and the attributes it sets on the invited users).
21
+
22
+ Setup
23
+ -----
24
+ Create a model called `User`, then run both Devise and *devise_invitable* on it, following their instructions.
25
+
26
+ Then, add `gem 'devise_invitations'` to your Gemfile and run `$ bundle install`.
27
+
28
+ You can install *devise_invitations* just by running `$ bin/rails g devise_invitations:install` and `bin/rake db:migrate`.
29
+
30
+ This is what's new in your project:
31
+
32
+ - A migration for a new table called `invitations` is created
33
+ - A `has_many` association for `User` (useful to fetch the sent invitations) is injected
34
+ - A new route for said action is injected as well
35
+
36
+ If you need to customize something feel free to hard-copy it into your project (i.e. the mailer and the related view).
37
+
38
+ If you use *RSpec* and *FactoryGirl* you can run `$ bin/rails g devise_invitations:specs` to copy the specs for the new associations, controllers and models to your codebase. You can extend and customize them as you wish.
39
+
40
+ Now, you need an action to let your users invite other ones. Basically it's just
41
+
42
+ ```ruby
43
+ DeviseInvitations::Invitation.create!(email: params[:email], sent_by: current_user)
44
+ ```
45
+
46
+ You can add new columns to the table for new attributes too, like `user_type`, `message` or whatever you want.
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rake'
3
+
4
+ task default: [ :build, :install ]
5
+
6
+ task :build do
7
+ sh 'gem build devise_invitations.gemspec'
8
+ end
9
+
10
+ task :install do
11
+ sh 'gem install *.gem'
12
+ end
@@ -0,0 +1,5 @@
1
+ <h1><%= t('.hello', email: @sender.email, app_name: @app_name) %></h1>
2
+
3
+ <p class="action">
4
+ <%= link_to t('.join'), accept_invitation_request_url(token: @token) %>
5
+ </p>
@@ -0,0 +1,11 @@
1
+ machine:
2
+ ruby:
3
+ version: 2.3.0
4
+
5
+ dependencies:
6
+ post:
7
+ - ./magic.sh
8
+
9
+ test:
10
+ override:
11
+ - cd test_app; bundle exec rspec
@@ -0,0 +1,7 @@
1
+ en:
2
+ devise_invitations:
3
+ mailer:
4
+ instructions:
5
+ subject: 'You got an invite!'
6
+ hello: '%{email} invited you to join %{app_name}.'
7
+ join: 'Accept the invitation'
@@ -0,0 +1,22 @@
1
+ require_relative 'lib/devise_invitations/version.rb'
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'devise_invitations'
5
+ s.version = DeviseInvitations::VERSION
6
+ s.platform = Gem::Platform::RUBY
7
+ s.author = 'Roxas Shadow'
8
+ s.email = 'webmaster@giovannicapuano.net'
9
+ s.homepage = 'https://github.com/RoxasShadow/devise_invitations'
10
+ s.summary = 'Allow multiple invitations on top of devise_invitable'
11
+ s.description = 'Extend devise and devise_invitable allowing multiple invitations.'
12
+ s.license = 'BSD-2-Clause'
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files specs`.split("\n")
16
+ s.require_path = 'lib'
17
+
18
+ s.add_dependency 'devise_invitable', '~> 1.5'
19
+ s.add_dependency 'has_secure_token', '~> 1.0'
20
+ s.add_dependency 'shoulda-matchers', '~> 2.0'
21
+ s.add_dependency 'faker', '~> 1.6'
22
+ end
@@ -0,0 +1,14 @@
1
+ require 'has_secure_token' unless Rails.version.start_with?('5')
2
+
3
+ if Rails.env.test?
4
+ require 'shoulda-matchers'
5
+ require 'faker'
6
+ end
7
+
8
+ require 'devise_invitations/engine'
9
+
10
+ module DeviseInvitations
11
+ autoload :Mailer, 'devise_invitations/mailer'
12
+ autoload :InvitationsController, 'devise_invitations/controller'
13
+ autoload :Invitation, 'devise_invitations/model'
14
+ end
@@ -0,0 +1,26 @@
1
+ class DeviseInvitations::InvitationsController < Devise::InvitationsController
2
+ def accept
3
+ invitation = DeviseInvitations::Invitation.pending.find_by(token: params[:token])
4
+
5
+ if invitation.present? && invitation.valid?
6
+ invitation_params = { email: invitation.email }
7
+
8
+ user = User.invite!(invitation_params, invitation.sent_by) do |u|
9
+ u.skip_invitation = true
10
+ end
11
+
12
+ user.update(invitation_sent_at: Time.now.utc)
13
+
14
+ statuses = DeviseInvitations::Invitation.statuses
15
+ invitation.update(status: statuses[:accepted])
16
+ DeviseInvitations::Invitation.pending
17
+ .where(email: invitation.email)
18
+ .update_all(status: statuses[:ignored])
19
+
20
+ redirect_to accept_invitation_url(user, invitation_token: user.raw_invitation_token)
21
+ else
22
+ flash[:error] = t('en.invitations.accept.not_valid')
23
+ redirect_to root_path
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,4 @@
1
+ module DeviseInvitations
2
+ class Engine < Rails::Engine
3
+ end
4
+ end
@@ -0,0 +1,24 @@
1
+ class DeviseInvitations::Mailer < ApplicationMailer
2
+ def instructions(invitation)
3
+ @token = invitation.token
4
+ @sender = invitation.sent_by
5
+ @app_name = app_name
6
+
7
+ mail(
8
+ subject: t('.subject'),
9
+ from: @sender.email,
10
+ to: invitation.email,
11
+ )
12
+ end
13
+
14
+ private
15
+
16
+ def app_name
17
+ Rails.application.class.parent_name
18
+ .underscore
19
+ .humanize
20
+ .split
21
+ .map(&:capitalize)
22
+ .join(' ')
23
+ end
24
+ end
@@ -0,0 +1,18 @@
1
+ class DeviseInvitations::Invitation < ActiveRecord::Base
2
+ belongs_to :sent_by, class_name: 'User', foreign_key: 'sent_by_id'
3
+ has_secure_token :token
4
+
5
+ validates :email, presence: true, format: { with: Devise.email_regexp }
6
+ validates :email, :sent_by, uniqueness: { scope: [:email, :sent_by] }
7
+ validate :presence_as_user, on: :create
8
+
9
+ enum status: [:pending, :accepted, :ignored]
10
+
11
+ after_create { DeviseInvitations::Mailer.instructions(self).deliver_later }
12
+
13
+ private
14
+
15
+ def presence_as_user
16
+ errors.add(:email, :user_already_exists) if User.exists?(email: email)
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ module DeviseInvitations
2
+ VERSION = '0.1'
3
+ end
@@ -0,0 +1,61 @@
1
+ module DeviseInvitations
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+ def install
5
+ %w(migrations models routes).each do |m|
6
+ invoke "devise_invitations:#{m}"
7
+ end
8
+ end
9
+ end
10
+
11
+ class MigrationsGenerator < Rails::Generators::Base
12
+ include Rails::Generators::Migration
13
+
14
+ source_root File.expand_path('../migrations/templates', __FILE__)
15
+
16
+ def copy_migration
17
+ migration_template('migration.rb', 'db/migrate/create_invitations.rb')
18
+ end
19
+
20
+ def self.next_migration_number(path)
21
+ if @prev_migration
22
+ @prev_migration += 1
23
+ else
24
+ @prev_migration = Time.now.utc.strftime('%Y%m%d%H%M%S').to_i
25
+ end
26
+
27
+ @prev_migration.to_s
28
+ end
29
+ end
30
+
31
+ class ModelsGenerator < Rails::Generators::Base
32
+ source_root File.expand_path('../models/templates', __FILE__)
33
+
34
+ def inject_associations
35
+ inject_into_file('app/models/user.rb', after: 'ActiveRecord::Base') do
36
+ File.read(
37
+ File.join(
38
+ File.expand_path('../models/templates', __FILE__),
39
+ 'associations.rb'
40
+ )
41
+ )
42
+ end
43
+ end
44
+ end
45
+
46
+ class RoutesGenerator < Rails::Generators::Base
47
+ source_root File.expand_path('../routes/templates', __FILE__)
48
+
49
+ def inject_routes
50
+ inject_into_file('config/routes.rb', after: 'devise_for :users') do
51
+ File.read(
52
+ File.join(
53
+ File.expand_path('../routes/templates', __FILE__),
54
+ 'routes.rb'
55
+ )
56
+ )
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,19 @@
1
+ class CreateInvitations < ActiveRecord::Migration
2
+ def change
3
+ create_table :invitations do |t|
4
+ t.integer :sent_by_id, null: false
5
+ t.string :email, null: false
6
+ t.integer :status, null: false, default: 0
7
+ t.string :token, null: false
8
+
9
+ t.timestamps null: false
10
+ end
11
+
12
+ add_index :invitations, :sent_by_id
13
+ add_index :invitations, :email
14
+ add_index :invitations, :status
15
+ add_index :invitations, :token
16
+
17
+ add_foreign_key :invitations, :users, column: :sent_by_id
18
+ end
19
+ end
@@ -0,0 +1,3 @@
1
+
2
+ has_many :invitations, class_name: 'DeviseInvitations::Invitation',
3
+ foreign_key: :sent_by_id, dependent: :destroy
@@ -0,0 +1,6 @@
1
+
2
+ devise_scope :user do
3
+ get 'invitation/accept',
4
+ to: 'devise_invitations/invitations#accept',
5
+ as: :accept_invitation_request
6
+ end
@@ -0,0 +1,2 @@
1
+
2
+ it { is_expected.to have_many :invitations }
@@ -0,0 +1,71 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.describe DeviseInvitations::InvitationsController do
4
+ describe 'GET #accept' do
5
+ before { @request.env['devise.mapping'] = Devise.mappings[:user] }
6
+
7
+ let(:email) { Faker::Internet.safe_email }
8
+ let(:user) { User.find_by(email: email) }
9
+
10
+ let(:joe) { create(:user) }
11
+ let(:sender) { create(:user) }
12
+ let(:jack) { create(:user) }
13
+
14
+ let!(:joe_invitation) { create(:invitation, email: email, sent_by: joe) }
15
+ let!(:sender_invitation) { create(:invitation, email: email, sent_by: sender) }
16
+ let!(:jack_invitation) { create(:invitation, email: email, sent_by: jack) }
17
+
18
+ context 'token is valid' do
19
+ subject { get :accept, token: sender_invitation.token }
20
+
21
+ it { is_expected.to have_http_status(302) }
22
+
23
+ it 'creates a new user' do
24
+ expect { subject }.to change { User.unscoped.find_by(email: email).class }
25
+ .from(NilClass)
26
+ .to(User)
27
+ end
28
+
29
+ it 'sets a invited_by attribute to the new user' do
30
+ subject
31
+ expect(user.invited_by).to eq sender
32
+ end
33
+
34
+ it 'flags as accepted the current invitation' do
35
+ expect { subject }.to change { sender_invitation.reload.status }
36
+ .from('pending')
37
+ .to('accepted')
38
+ end
39
+
40
+ it 'flags as ignored the remanining invitations' do
41
+ expect { subject }.to change { joe_invitation.reload.status }
42
+ .from('pending')
43
+ .to('ignored')
44
+ end
45
+
46
+ it 'does not accept additional requests' do
47
+ subject
48
+
49
+ expect { get :accept, token: sender_invitation.token }
50
+ .to change { flash[:error] }
51
+ .from(nil)
52
+ .to(I18n.t('en.invitations.accept.not_valid'))
53
+ end
54
+ end
55
+
56
+ context 'token is valid' do
57
+ subject { get :accept, token: 'lolwut' }
58
+
59
+ it { is_expected.to have_http_status(302) }
60
+
61
+ it 'generates a flash error' do
62
+ subject
63
+ expect(flash[:error]).to eq I18n.t('en.invitations.accept.not_valid')
64
+ end
65
+
66
+ it 'does not create any new user' do
67
+ expect { subject }.to_not change { User.unscoped.count }
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,7 @@
1
+ FactoryGirl.define do
2
+ factory :invitation, class: DeviseInvitations::Invitation do
3
+ email { Faker::Internet.safe_email }
4
+ token { Devise.token_generator.generate(DeviseInvitations::Invitation, :token) }
5
+ association :sent_by, factory: :user
6
+ end
7
+ end
@@ -0,0 +1,21 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.describe DeviseInvitations::Invitation do
4
+ it { is_expected.to belong_to :sent_by }
5
+
6
+ let(:valid) { build(:invitation) }
7
+ it { expect(valid.pending?).to be_truthy }
8
+ it { expect(valid.valid?).to be_truthy }
9
+
10
+ let(:invalid) { build(:invitation, email: 'lolwut') }
11
+ it { expect(invalid.valid?).to be_falsy }
12
+
13
+ context 'use an email that is already registered inside the platform' do
14
+ before { create(:user, email: 'joe@example.com') }
15
+ subject { create(:invitation, email: 'joe@example.com') }
16
+
17
+ it 'raises an error' do
18
+ expect { subject }.to raise_error(ActiveRecord::RecordInvalid)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,30 @@
1
+ module DeviseInvitations
2
+ module Generators
3
+ class SpecsGenerator < Rails::Generators::Base
4
+ source_root File.expand_path('../specs/templates', __FILE__)
5
+
6
+ def copy_factory
7
+ copy_file('factory.rb', 'spec/factories/invitations.rb')
8
+ end
9
+
10
+ def copy_controller
11
+ copy_file('controller.rb', 'spec/controllers/invitations_controller_spec.rb')
12
+ end
13
+
14
+ def copy_model
15
+ copy_file('model.rb', 'spec/models/invitation_spec.rb')
16
+ end
17
+
18
+ def inject_association
19
+ inject_into_file('spec/models/user_spec.rb', after: 'RSpec.describe User, type: :model do') do
20
+ File.read(
21
+ File.join(
22
+ File.expand_path('../specs/templates', __FILE__),
23
+ 'association.rb'
24
+ )
25
+ )
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,83 @@
1
+ ##
2
+ # Hello, I'm a magical little girl in aid of CI-kun.
3
+ # I'll create and setup a new Rails application from scratch so CI-kun
4
+ # can test it. Bye-chi!
5
+ ##
6
+
7
+ gem install rails
8
+
9
+ rails new test_app
10
+
11
+ cd test_app
12
+
13
+ echo "gem 'rspec-rails'
14
+ gem 'factory_girl_rails'
15
+ gem 'letter_opener'
16
+ gem 'faker'
17
+
18
+ gem 'devise'
19
+ gem 'devise_invitable'
20
+ gem 'devise_invitations', path: '../'
21
+ " >> Gemfile
22
+
23
+ echo "`sed '45d' Gemfile`" > Gemfile # spring a shit
24
+
25
+ bundle install
26
+
27
+ rails g rspec:install
28
+
29
+ # we need a root_path
30
+ rails g controller welcome index
31
+ contents="root 'welcome#index'"
32
+ echo "`sed \"8s/^/$contents/\" config/routes.rb`" > config/routes.rb
33
+
34
+ rails g model user
35
+ rails g mailer UserMailer # we need an ApplicationMailer too
36
+
37
+ rails g devise:install
38
+ rails g devise user
39
+
40
+ rails g devise_invitable:install
41
+ rails g devise_invitable user
42
+
43
+ ## Uncomment these to check the diff later
44
+ # git init
45
+ # git add .
46
+ # git commit -m "Initial commit"
47
+
48
+ rails g devise_invitations:install
49
+ rails g devise_invitations:specs
50
+
51
+ rake db:migrate
52
+
53
+ # Enable FactoryGirl and Shoulda
54
+ echo "
55
+ RSpec.configure do |config|
56
+ config.include FactoryGirl::Syntax::Methods
57
+ end
58
+
59
+ Shoulda::Matchers.configure do |config|
60
+ config.integrate do |with|
61
+ with.test_framework :rspec
62
+ with.library :rails
63
+ end
64
+ end
65
+
66
+ " >> spec/rails_helper.rb
67
+
68
+ echo "FactoryGirl.define do
69
+ factory :user do
70
+ email { Faker::Internet.safe_email }
71
+ password { Faker::Internet.password(8) }
72
+ end
73
+ end
74
+ " > spec/factories/users.rb
75
+
76
+ contents="config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }"
77
+ echo "`sed \"39s/^/$contents/\" config/environments/test.rb`" > config/environments/test.rb
78
+
79
+ contents="config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }"
80
+ echo "`sed \"38s/^/$contents/\" config/environments/development.rb`" > config/environments/development.rb
81
+
82
+ contents="config.action_mailer.delivery_method = :letter_opener"
83
+ echo "`sed \"33s/^/$contents/\" config/environments/development.rb`" > config/environments/development.rb
metadata ADDED
@@ -0,0 +1,129 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: devise_invitations
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ platform: ruby
6
+ authors:
7
+ - Roxas Shadow
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-01-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: devise_invitable
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: has_secure_token
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: shoulda-matchers
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: faker
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.6'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.6'
69
+ description: Extend devise and devise_invitable allowing multiple invitations.
70
+ email: webmaster@giovannicapuano.net
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - ".gitignore"
76
+ - Gemfile
77
+ - Gemfile.lock
78
+ - LICENSE
79
+ - README.md
80
+ - Rakefile
81
+ - app/views/devise_invitations/mailer/instructions.html.erb
82
+ - circle.yml
83
+ - config/locales/devise_invitations.en.yml
84
+ - devise_invitations.gemspec
85
+ - lib/devise_invitations.rb
86
+ - lib/devise_invitations/controller.rb
87
+ - lib/devise_invitations/engine.rb
88
+ - lib/devise_invitations/mailer.rb
89
+ - lib/devise_invitations/model.rb
90
+ - lib/devise_invitations/version.rb
91
+ - lib/generators/devise_invitations/.DS_Store
92
+ - lib/generators/devise_invitations/install_generator.rb
93
+ - lib/generators/devise_invitations/migrations/.DS_Store
94
+ - lib/generators/devise_invitations/migrations/templates/migration.rb
95
+ - lib/generators/devise_invitations/models/.DS_Store
96
+ - lib/generators/devise_invitations/models/templates/associations.rb
97
+ - lib/generators/devise_invitations/routes/templates/routes.rb
98
+ - lib/generators/devise_invitations/specs/.DS_Store
99
+ - lib/generators/devise_invitations/specs/templates/association.rb
100
+ - lib/generators/devise_invitations/specs/templates/controller.rb
101
+ - lib/generators/devise_invitations/specs/templates/factory.rb
102
+ - lib/generators/devise_invitations/specs/templates/model.rb
103
+ - lib/generators/devise_invitations/specs_generator.rb
104
+ - magic.sh
105
+ homepage: https://github.com/RoxasShadow/devise_invitations
106
+ licenses:
107
+ - BSD-2-Clause
108
+ metadata: {}
109
+ post_install_message:
110
+ rdoc_options: []
111
+ require_paths:
112
+ - lib
113
+ required_ruby_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ requirements: []
124
+ rubyforge_project:
125
+ rubygems_version: 2.5.1
126
+ signing_key:
127
+ specification_version: 4
128
+ summary: Allow multiple invitations on top of devise_invitable
129
+ test_files: []