invitation 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e0724862de922a3160c5377adb5b82c528338d99
4
+ data.tar.gz: 4da9685c29934fac4f2032745cd82f26bfc4e659
5
+ SHA512:
6
+ metadata.gz: 00cafe245f0461abbed65b703385fd947966f34ff3c5951ae5ec400b4afefae8c72a3a10094a76c7cc2e41b28efc2777e0825093e3db244fba460be42fe49a9b
7
+ data.tar.gz: 7d4cf63f017e0df43630c5eced0746534f7805a4f68a8dc67d76078129c69f61514782b2ff21ca01a53457cba6e26c2182b70b0a68e34164979e5c58b957b958
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rspec/core/rake_task'
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,66 @@
1
+ class Invitation::InvitesController < ApplicationController
2
+
3
+ def new
4
+ @invite = invite_from_params
5
+ render template: 'invites/new'
6
+ end
7
+
8
+ def create
9
+ @invite = invite_from_params
10
+ @invite.sender_id = current_user.id
11
+ logger.info '@invite: ' + @invite.inspect
12
+ if @invite.save
13
+ #if the user already exists
14
+ if @invite.recipient != nil
15
+ deliver_email(InviteMailer.existing_user(@invite))
16
+ after_invite_existing_user
17
+ else
18
+ deliver_email(InviteMailer.new_user(@invite))
19
+ after_invite_new_user
20
+ end
21
+ flash[:notice] = t('invitation.flash.invite_issued', email: @invite.email)
22
+ else
23
+ flash[:error] = t('invitation.flash.invite_error')
24
+ end
25
+ redirect_to url_after_invite
26
+ end
27
+
28
+
29
+ private
30
+
31
+
32
+ # Override this if you want to do something more complicated for existing users.
33
+ def after_invite_existing_user
34
+ # Add the user to the organization
35
+ @invite.invitable.add_invited_user(@invite.recipient)
36
+ end
37
+
38
+ # Override if you want to do something more complicated for new users. By default we do nothing.
39
+ def after_invite_new_user
40
+ end
41
+
42
+ # Url sender is redirected to after creating invite.
43
+ def url_after_invite
44
+ Invitation.configuration.url_after_invite
45
+ end
46
+
47
+ # Build new Invite from params.
48
+ def invite_from_params
49
+ Invite.new(invite_params)
50
+ end
51
+
52
+ def invite_params
53
+ return params.require(:invite).permit(:invitable_id, :invitable_type, :email) if params[:invite]
54
+ Hash.new
55
+ end
56
+
57
+ # Use deliver_later from rails 4.2+ if available.
58
+ def deliver_email(mail)
59
+ if mail.respond_to?(:deliver_later)
60
+ mail.deliver_later
61
+ else
62
+ mail.deliver
63
+ end
64
+ end
65
+
66
+ end
@@ -0,0 +1,20 @@
1
+ class InviteMailer < ActionMailer::Base
2
+ def existing_user(invite)
3
+ @invite = invite
4
+ mail(
5
+ from: Invitation.configuration.mailer_sender,
6
+ to: @invite.email,
7
+ subject: I18n.t('invitation.invite_mailer.existing_user.subject')
8
+ )
9
+ end
10
+
11
+ def new_user(invite)
12
+ @invite = invite
13
+ @user_registration_url = Invitation.configuration.user_registration_url.call(:invite_token => @invite.token)
14
+ mail(
15
+ from: Invitation.configuration.mailer_sender,
16
+ to: @invite.email,
17
+ subject: I18n.t('invitation.invite_mailer.new_user.subject')
18
+ )
19
+ end
20
+ end
@@ -0,0 +1,28 @@
1
+ # An invitation, tracks the sender and recipient, and what the recipient is invited to.
2
+ # Generates a unique token for each invitation. The token is used in the invite url
3
+ # to (more) securely identify the invite when a new user clicks to register.
4
+ #
5
+ class Invite < ActiveRecord::Base
6
+ belongs_to :invitable, polymorphic: true
7
+ belongs_to :sender, class_name: Invitation.configuration.user_model_class_name
8
+ belongs_to :recipient, class_name: Invitation.configuration.user_model_class_name
9
+
10
+ before_create :generate_token
11
+ before_save :check_recipient_existence
12
+
13
+ validates :email, presence: true
14
+ validates :invitable, presence: true
15
+ validates :sender, presence: true
16
+
17
+
18
+ def generate_token
19
+ self.token = SecureRandom.hex(20).encode('UTF-8')
20
+ end
21
+
22
+ def check_recipient_existence
23
+ recipient = Invitation.configuration.user_model.find_by_email(email)
24
+ if recipient
25
+ self.recipient_id = recipient.id
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,7 @@
1
+ <p><%= t('invitation.invite_mailer.existing_user.hello', email: @invite.email) %></p>
2
+
3
+ <p><%= raw t('invitation.invite_mailer.existing_user.someone_invited_you',
4
+ sender: @invite.sender.email, invitable: @invite.invitable.invitable_name, url: root_url) %></p>
5
+
6
+ <p><%= t('invitation.invite_mailer.existing_user.ignore', sender: @invite.sender.email) %></p>
7
+
@@ -0,0 +1,9 @@
1
+ <p><%= t('invitation.invite_mailer.new_user.hello', email: @invite.email) %></p>
2
+
3
+ <p><%= raw t('invitation.invite_mailer.new_user.someone_invited_you',
4
+ sender: @invite.sender.email, invitable: @invite.invitable.invitable_name, url: root_url) %></p>
5
+
6
+ <p><%= link_to t('invitation.invite_mailer.new_user.accept'), @user_registration_url %></p>
7
+
8
+ <p><%= t('invitation.invite_mailer.new_user.ignore').html_safe %></p>
9
+
@@ -0,0 +1,17 @@
1
+ <div id="invitation" class="new">
2
+
3
+
4
+ <p>
5
+ Issue an invitation to join <%= @invite.invitable.invitable_name %>
6
+ </p>
7
+
8
+ <%= form_for @invite, url: invites_path do |f| %>
9
+ <%= f.hidden_field :invitable_id, value: @invite.invitable_id %>
10
+ <%= f.hidden_field :invitable_type, value: @invite.invitable_type %>
11
+ <%= f.label :email %>
12
+ <%= f.email_field :email %>
13
+ <%= f.submit 'Send' %>
14
+ <% end %>
15
+
16
+ </div>
17
+
@@ -0,0 +1,21 @@
1
+ en:
2
+ activerecord:
3
+ attributes:
4
+ invite:
5
+ email: "Email"
6
+ invitation:
7
+ flash:
8
+ invite_issued: "Invitation issued to %{email}"
9
+ invite_error: "Unable to issue invitation"
10
+ invite_mailer:
11
+ existing_user:
12
+ subject: "Invitation instructions"
13
+ hello: "Hello %{email}"
14
+ someone_invited_you: "%{sender} has invited you to <b>%{invitable}</b> at %{url}. You now have permissions to access it."
15
+ ignore: "If you don't want this permission added or feel it is in error, please contact %{sender}."
16
+ new_user:
17
+ subject: "Invitation instructions"
18
+ hello: "Hello %{email}"
19
+ someone_invited_you: "%{sender} has invited you to <b>%{invitable}</b> at %{url}. You can accept the invitation with the url below."
20
+ accept: "Accept invitation"
21
+ ignore: "If you don't want to accept the invitation, please ignore this email.<br />Your account won't be created until you access the link above and set your password."
data/config/routes.rb ADDED
@@ -0,0 +1,5 @@
1
+ if Invitation.configuration.routes_enabled?
2
+ Rails.application.routes.draw do
3
+ resources :invites, controller: 'invitation/invites', only: [:new, :create]
4
+ end
5
+ end
@@ -0,0 +1,10 @@
1
+ Description:
2
+ Override the default invitation controller and mailer. This generator will copy all of the
3
+ invitation controllers and mailers into your project.
4
+
5
+ Examples:
6
+ rails generate invitation:controllers
7
+
8
+ Controller: app/controllers/invitation/invites_controller.rb
9
+ Mailer: app/mailers/invitation_mailer.rb
10
+
@@ -0,0 +1,21 @@
1
+ require 'rails/generators/base'
2
+
3
+ #
4
+ # deploy view and locale assets
5
+ #
6
+ module Invitation
7
+ module Generators
8
+ class ControllersGenerator < Rails::Generators::Base
9
+ source_root File.expand_path("../../../../..", __FILE__)
10
+
11
+ def create_controllers
12
+ directory 'app/controllers'
13
+ end
14
+
15
+ def create_mailers
16
+ directory 'app/mailers'
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,78 @@
1
+ module Invitation
2
+ module Generators
3
+ module Helpers
4
+ private
5
+
6
+ # Either return the model passed in a classified form or return the default "User".
7
+ def model_class_name
8
+ options[:model] ? options[:model].classify : 'User'
9
+ end
10
+
11
+ def model_path
12
+ @model_path ||= File.join('app', 'models', "#{file_path}.rb")
13
+ end
14
+
15
+ def file_path
16
+ model_name.underscore
17
+ end
18
+
19
+ def namespace
20
+ Rails::Generators.namespace if Rails::Generators.respond_to?(:namespace)
21
+ end
22
+
23
+ def namespaced?
24
+ !!namespace
25
+ end
26
+
27
+ def model_name
28
+ if namespaced?
29
+ [namespace.to_s] + [model_class_name]
30
+ else
31
+ [model_class_name]
32
+ end.join('::')
33
+ end
34
+
35
+ def table_name
36
+ @table_name ||= begin
37
+ base = plural_name
38
+ (class_path + [base]).join('_')
39
+ end
40
+ end
41
+
42
+ def class_path
43
+ @class_path
44
+ end
45
+
46
+ def singular_name
47
+ @file_name
48
+ end
49
+
50
+ def plural_name
51
+ singular_name.pluralize
52
+ end
53
+
54
+ def assign_names!(name) #:nodoc:
55
+ @class_path = name.include?('/') ? name.split('/') : name.split('::')
56
+ @class_path.map!(&:underscore)
57
+ @file_name = @class_path.pop
58
+ end
59
+
60
+
61
+
62
+
63
+
64
+ def invitable_file_path invitable_class_name
65
+ File.join('app', 'models', "#{invitable_model_name(invitable_class_name).underscore}.rb")
66
+ end
67
+
68
+ def invitable_model_name invitable_class_name
69
+ if namespaced?
70
+ [namespace.to_s] + [invitable_class_name.classify]
71
+ else
72
+ [invitable_class_name.classify]
73
+ end.join('::')
74
+ end
75
+
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Explain the generator
3
+
4
+ Example:
5
+ rails generate initializer Thing
6
+
7
+ This will create:
8
+ what/will/it/create
@@ -0,0 +1,77 @@
1
+ require 'rails/generators/base'
2
+ require 'rails/generators/active_record'
3
+ require 'generators/invitation/helpers'
4
+
5
+ module Invitation
6
+ module Generators
7
+ class InstallGenerator < Rails::Generators::Base
8
+ include Rails::Generators::Migration
9
+ include Invitation::Generators::Helpers
10
+
11
+ source_root File.expand_path('../templates', __FILE__)
12
+
13
+ class_option :model, optional: true, type: :string, banner: 'model',
14
+ desc: "Specify the model class name if you will use anything other than 'User'"
15
+
16
+ # class_option :invitable, optional: true, type: :array, banner: 'invitable',
17
+ # desc: "Specify the model class name if you will use anything other than 'User'"
18
+
19
+ def verify
20
+ if options[:model] && !File.exists?(model_path)
21
+ puts "Exiting: the model class you specified, #{options[:model]}, is not found."
22
+ exit 1
23
+ end
24
+ end
25
+
26
+ # def verify_invitable
27
+ # return unless options[:invitable]
28
+ # options[:invitable].each do |invitable|
29
+ # unless File.exists?(invitable_file_path invitable)
30
+ # puts "Exiting: the model class you specified to make invitable, #{invitable}, is not found."
31
+ # exit 1
32
+ # end
33
+ # end
34
+ # end
35
+
36
+ def inject_into_user_model
37
+ inject_into_class model_path, model_class_name, " include Invitation::User\n\n"
38
+ end
39
+
40
+ # def inject_into_invitables
41
+ # return unless options[:invitable]
42
+ # options[:invitable].each do |invitable|
43
+ # path = invitable_file_path(invitable)
44
+ # class_name = invitable.classify
45
+ # inject_into_class path, class_name, " include Invitation::Invitable\n\n"
46
+ # end
47
+ # end
48
+
49
+ def copy_migration_files
50
+ copy_migration 'create_invites.rb'
51
+ end
52
+
53
+ def create_initializer
54
+ copy_file 'invitation.rb', 'config/initializers/invitation.rb'
55
+ if options[:model]
56
+ inject_into_file(
57
+ 'config/initializers/invitation.rb',
58
+ " config.user_model = '#{options[:model]}' \n",
59
+ after: "Invitation.configure do |config|\n",
60
+ )
61
+ end
62
+ end
63
+
64
+ private
65
+
66
+ def copy_migration migration_name
67
+ migration_template "db/migrate/#{migration_name}", "db/migrate/#{migration_name}"
68
+ end
69
+
70
+ # for generating a timestamp when using `create_migration`
71
+ def self.next_migration_number(dir)
72
+ ActiveRecord::Generators::Base.next_migration_number(dir)
73
+ end
74
+
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,18 @@
1
+ class CreateInvites < ActiveRecord::Migration
2
+ def change
3
+ create_table :invites do |t|
4
+ t.string :email
5
+ t.string :token
6
+ t.integer :sender_id
7
+ t.integer :recipient_id
8
+ t.integer :invitable_id
9
+ t.string :invitable_type
10
+ t.timestamps
11
+ t.index :email
12
+ t.index :token
13
+ t.index [:invitable_id, :invitable_type]
14
+ t.index :recipient_id
15
+ t.index :sender_id
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,7 @@
1
+ Invitation.configure do |config|
2
+ # config.user_model = ::User
3
+ # config.user_registration_url = ->(params) { Rails.application.routes.url_helpers.sign_up_url(params) }
4
+ # config.mailer_sender = 'reply@example.com'
5
+ # config.url_after_invite = '/'
6
+ # config.routes = true
7
+ end
@@ -0,0 +1,35 @@
1
+ require 'rails/generators/base'
2
+
3
+ module Invitation
4
+ module Generators
5
+ class RoutesGenerator < Rails::Generators::Base
6
+
7
+ source_root File.expand_path('../templates', __FILE__)
8
+
9
+ def add_invitation_routes
10
+ route(invitation_routes)
11
+ end
12
+
13
+ def disable_invitation_internal_routes
14
+ inject_into_file(
15
+ 'config/initializers/invitation.rb',
16
+ " config.routes = false \n",
17
+ after: "Invitation.configure do |config|\n",
18
+ )
19
+ end
20
+
21
+
22
+ private
23
+
24
+
25
+ def invitation_routes
26
+ File.read(routes_file_path)
27
+ end
28
+
29
+ def routes_file_path
30
+ File.expand_path(find_in_source_paths('routes.rb'))
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1 @@
1
+ resources :invites, controller: 'invitation/invites', only: [:new, :create]
@@ -0,0 +1,11 @@
1
+ Description:
2
+ Override the default invitation views and locale files. This generator will copy all of the
3
+ base invitation views and locale files into your project.
4
+
5
+ Examples:
6
+ rails generate invitation:views
7
+
8
+ View: app/views/invite_mailer/exiting_user.html.erb
9
+ View: app/views/invite_mailer/new_user.html.erb
10
+ View: app/views/invites/new.html.erb
11
+ Locale: config/locales/en.yml
@@ -0,0 +1,21 @@
1
+ require 'rails/generators/base'
2
+
3
+ #
4
+ # deploy view and locale assets
5
+ #
6
+ module Authenticate
7
+ module Generators
8
+ class ViewsGenerator < Rails::Generators::Base
9
+ source_root File.expand_path("../../../../..", __FILE__)
10
+
11
+ def create_views
12
+ directory 'app/views'
13
+ end
14
+
15
+ def create_locales
16
+ directory 'config/locales'
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,90 @@
1
+ module Invitation
2
+ class Configuration
3
+
4
+ # ActiveRecord model class name that represents your user.
5
+ #
6
+ # Defaults to '::User'.
7
+ # @return [ActiveRecord::Base]
8
+ attr_accessor :user_model
9
+
10
+
11
+ # Url for new users to register for your application. New users are invited to
12
+ # sign up at this url via email. The url should be expressed as a lambda that
13
+ # accepts one argument, a params hash. This hash will contain the invitation token.
14
+ #
15
+ # Defaults to: ->(params) { Rails.application.routes.url_helpers.sign_up_url(params) }
16
+ #
17
+ # Note that the default assumes you have `sign_up_url`.
18
+ #
19
+ # @return [Lambda]
20
+ attr_accessor :user_registration_url
21
+
22
+
23
+ # Controls the 'from' address for Invitation emails.
24
+ # Set this to a value appropriate to your application.
25
+ #
26
+ # Defaults to reply@example.com.
27
+ #
28
+ # @return [String]
29
+ attr_accessor :mailer_sender
30
+
31
+
32
+ # Path that Invitation will redirect users to after an invitation is issued.
33
+ #
34
+ # Defaults to '/'
35
+ #
36
+ # Override the invites_controller method if a more complex url is required.
37
+ # @return [String]
38
+ attr_accessor :url_after_invite
39
+
40
+
41
+ # Enable or disable Invitation's built-in routes.
42
+ #
43
+ # Defaults to 'true'.
44
+ #
45
+ # If you disable the routes, your application is responsible for all routes.
46
+ #
47
+ # You can deploy a copy of Invitations's routes with `rails generate invitation:routes`,
48
+ # which will also set `config.routes = false`.
49
+ #
50
+ # @return [Boolean]
51
+ attr_accessor :routes
52
+
53
+
54
+ def initialize
55
+ @user_model = ::User
56
+ @user_registration_url = ->(params) { Rails.application.routes.url_helpers.sign_up_url(params) }
57
+ @mailer_sender = 'reply@example.com'
58
+ @url_after_invite = '/'
59
+ @routes = true
60
+ end
61
+
62
+ def user_model_class_name
63
+ @user_model.name.to_s
64
+ end
65
+
66
+ def user_model_instance_var
67
+ '@' + @user_model.name.demodulize.underscore
68
+ end
69
+
70
+ # @return [Boolean] are Invitation's built-in routes enabled?
71
+ def routes_enabled?
72
+ @routes
73
+ end
74
+
75
+ end
76
+
77
+
78
+ def self.configuration
79
+ @configuration ||= Configuration.new
80
+ end
81
+
82
+ def self.configuration=(config)
83
+ @configuration = config
84
+ end
85
+
86
+ def self.configure
87
+ yield configuration
88
+ end
89
+
90
+ end
@@ -0,0 +1,10 @@
1
+ module Invitation
2
+ class Engine < ::Rails::Engine
3
+
4
+ config.generators do |g|
5
+ g.test_framework :rspec
6
+ g.fixture_replacement :factory_girl, dir: 'spec/factories'
7
+ end
8
+
9
+ end
10
+ end
@@ -0,0 +1,64 @@
1
+ #
2
+ # Any model you wish to invite users to join should extend this concern. This is typically an
3
+ # organization or resource with limited membership like an "account" or "project".
4
+ #
5
+ # Your code is responsible for managing associations between your Invitable and your user model.
6
+ #
7
+ # For example, to make the model class Account an organization that can receive an invitation
8
+ #
9
+ # class Account < ActiveRecord::Base
10
+ # invitable named_by: :name
11
+ #
12
+ # has_many :account_memberships
13
+ # has_many :users, through: :account_memberships
14
+ # end
15
+ #
16
+ #
17
+ module Invitation
18
+ module Invitable
19
+
20
+ def invitable(options = {})
21
+ has_many :invites, as: :invitable
22
+ class_attribute :invitable_options
23
+
24
+ self.invitable_options = options.dup # named_by: :name, named: 'Gug'
25
+ self.invitable_options[:named_by] = options[:named_by] if options[:named_by]
26
+ self.invitable_options[:named] = options[:named] if options[:named]
27
+
28
+ unless self.invitable_options[:named] || self.invitable_options[:named_by]
29
+ raise <<-eos
30
+ invitable requires options be set, either :name or :named_by.
31
+ invitable named: "string"
32
+ or
33
+ invitable named_by: :method_name
34
+ eos
35
+ end
36
+
37
+ include Invitation::Invitable::InstanceMethods
38
+ end
39
+
40
+
41
+ module InstanceMethods
42
+
43
+ # Add the invited user to the organization. Called by InvitesController.
44
+ def add_invited_user(user)
45
+ method = Invitation.configuration.user_model.name.underscore.pluralize
46
+ self.send(method).push(user)
47
+ end
48
+
49
+ # Get the name of the organization for use in invitations.
50
+ def invitable_name
51
+ if invitable_options[:named_by]
52
+ self.send(invitable_options[:named_by])
53
+ elsif invitable_options[:named]
54
+ invitable_options[:named]
55
+ else
56
+ raise 'Invitation runtime error: invitable does not have name: or named_by: set, should not be possible! ' +
57
+ self.inspect
58
+ end
59
+ end
60
+ end
61
+
62
+ end
63
+ end
64
+
@@ -0,0 +1,38 @@
1
+ #
2
+ # Your user model must include this concern to send and receive invitations. Your user class must also be
3
+ # specified in the invitation configuration `Invitation.configure.user_model`.
4
+ #
5
+ # Your user model code is responsible for managing associations to any organizations you wish
6
+ # to issue invitations to. Your user model will probably also include an authentication model.
7
+ #
8
+ # For example, to make your user class `User` able to issue invitations to model `Account`:
9
+ #
10
+ # class User < ActiveRecord::Base
11
+ # include Invitation::User
12
+ # include Authenticate::User
13
+ #
14
+ # has_many :account_memberships
15
+ # has_many :accounts, through: :account_memberships
16
+ # end
17
+ #
18
+ module Invitation
19
+ module User
20
+ extend ActiveSupport::Concern
21
+
22
+ included do
23
+ has_many :invitations, class_name: 'Invite', foreign_key: :recipient_id
24
+ has_many :sent_invites, class_name: 'Invite', foreign_key: :sender_id
25
+ end
26
+
27
+ def claim_invite(token)
28
+ invite = Invite.find_by_token(token)
29
+ return if invite.nil?
30
+ invitable = invite.invitable
31
+ invitable.add_invited_user self
32
+ invite.recipient = self
33
+ invite.save
34
+ end
35
+
36
+ end
37
+ end
38
+
@@ -0,0 +1,52 @@
1
+ # Your user registration controller should include this concern.
2
+ #
3
+ module Invitation
4
+ module UserRegistration
5
+ extend ActiveSupport::Concern
6
+
7
+
8
+ # Copy params[:invite_token] to @invite_token. Your user registration form needs
9
+ # to include :invite_token, this method is the controller half of the glue.
10
+ #
11
+ # Use this in your user registration controller in a before_action for the new action.
12
+ #
13
+ # before_action :set_token, only: [:new]
14
+ #
15
+ def set_invite_token
16
+ @invite_token = params[:invite_token]
17
+ end
18
+
19
+
20
+ # Check for an invitation token and process the invite. If an invitation is found, the
21
+ # user claims the invite.
22
+ #
23
+ # Use this only when creating a new user. Invoke manually or from an after_action:
24
+ #
25
+ # after_action :process_invite, only: [:create]
26
+ #
27
+ # Invoke with new_user, or set an instance variable with the standard 'underscore' name of your user model class.
28
+ # For example, if your user model is UserProfile, this method will check for @user_profile.
29
+ #
30
+ def process_invite_token(new_user = nil)
31
+ if new_user.nil?
32
+ new_user = user_instance_variable
33
+ end
34
+
35
+ token = params[:invite_token]
36
+ if token != nil && new_user != nil
37
+ new_user.claim_invite token
38
+ end
39
+ end
40
+
41
+
42
+ private
43
+
44
+
45
+ def user_instance_variable
46
+ name = Invitation.configuration.user_model_instance_var
47
+ self.instance_variable_get(name)
48
+ end
49
+
50
+ end
51
+ end
52
+
@@ -0,0 +1,3 @@
1
+ module Invitation
2
+ VERSION = "0.0.1"
3
+ end
data/lib/invitation.rb ADDED
@@ -0,0 +1,11 @@
1
+ require 'invitation/engine'
2
+ require 'invitation/configuration'
3
+ require 'invitation/user'
4
+ require 'invitation/invitable'
5
+ require 'invitation/user_registration'
6
+
7
+ module Invitation
8
+ end
9
+
10
+ # ActiveRecord::Base.send :include, Invitation::Invitable
11
+ ActiveRecord::Base.extend Invitation::Invitable
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :invitation do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,218 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: invitation
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Justin Tomich
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-04-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '5.1'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '4.0'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '5.1'
33
+ - !ruby/object:Gem::Dependency
34
+ name: factory_girl
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '4.4'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '4.4'
47
+ - !ruby/object:Gem::Dependency
48
+ name: rspec-rails
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '3.1'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '3.1'
61
+ - !ruby/object:Gem::Dependency
62
+ name: rspec-mocks
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '3.1'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '3.1'
75
+ - !ruby/object:Gem::Dependency
76
+ name: pry
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '0.10'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '0.10'
89
+ - !ruby/object:Gem::Dependency
90
+ name: sqlite3
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '1.3'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '1.3'
103
+ - !ruby/object:Gem::Dependency
104
+ name: shoulda-matchers
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '2.8'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: '2.8'
117
+ - !ruby/object:Gem::Dependency
118
+ name: capybara
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '2.6'
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: '2.6'
131
+ - !ruby/object:Gem::Dependency
132
+ name: database_cleaner
133
+ requirement: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - "~>"
136
+ - !ruby/object:Gem::Version
137
+ version: '1.5'
138
+ type: :development
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - "~>"
143
+ - !ruby/object:Gem::Version
144
+ version: '1.5'
145
+ - !ruby/object:Gem::Dependency
146
+ name: timecop
147
+ requirement: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - "~>"
150
+ - !ruby/object:Gem::Version
151
+ version: '0.8'
152
+ type: :development
153
+ prerelease: false
154
+ version_requirements: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - "~>"
157
+ - !ruby/object:Gem::Version
158
+ version: '0.8'
159
+ description: Allow users to invite other users to join your organization
160
+ email:
161
+ - justin@tomich.org
162
+ executables: []
163
+ extensions: []
164
+ extra_rdoc_files: []
165
+ files:
166
+ - Rakefile
167
+ - app/controllers/invitation/invites_controller.rb
168
+ - app/mailers/invite_mailer.rb
169
+ - app/models/invite.rb
170
+ - app/views/invite_mailer/existing_user.html.erb
171
+ - app/views/invite_mailer/new_user.html.erb
172
+ - app/views/invites/new.html.erb
173
+ - config/locales/invitation.en.yml
174
+ - config/routes.rb
175
+ - lib/generators/invitation/controllers/USAGE
176
+ - lib/generators/invitation/controllers/controllers_generator.rb
177
+ - lib/generators/invitation/helpers.rb
178
+ - lib/generators/invitation/install/USAGE
179
+ - lib/generators/invitation/install/install_generator.rb
180
+ - lib/generators/invitation/install/templates/db/migrate/create_invites.rb
181
+ - lib/generators/invitation/install/templates/invitation.rb
182
+ - lib/generators/invitation/routes/routes_generator.rb
183
+ - lib/generators/invitation/routes/templates/routes.rb
184
+ - lib/generators/invitation/views/USAGE
185
+ - lib/generators/invitation/views/views_generator.rb
186
+ - lib/invitation.rb
187
+ - lib/invitation/configuration.rb
188
+ - lib/invitation/engine.rb
189
+ - lib/invitation/invitable.rb
190
+ - lib/invitation/user.rb
191
+ - lib/invitation/user_registration.rb
192
+ - lib/invitation/version.rb
193
+ - lib/tasks/invitation_tasks.rake
194
+ homepage: http://github.com/tomichj/invitation
195
+ licenses:
196
+ - MIT
197
+ metadata: {}
198
+ post_install_message:
199
+ rdoc_options: []
200
+ require_paths:
201
+ - lib
202
+ required_ruby_version: !ruby/object:Gem::Requirement
203
+ requirements:
204
+ - - ">="
205
+ - !ruby/object:Gem::Version
206
+ version: '2.0'
207
+ required_rubygems_version: !ruby/object:Gem::Requirement
208
+ requirements:
209
+ - - ">="
210
+ - !ruby/object:Gem::Version
211
+ version: '0'
212
+ requirements: []
213
+ rubyforge_project:
214
+ rubygems_version: 2.5.1
215
+ signing_key:
216
+ specification_version: 4
217
+ summary: Allow users to invite other users to join your organization
218
+ test_files: []