toolong-dontread 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +45 -0
- data/README.md +68 -0
- data/Rakefile +10 -0
- data/lib/generators/tldr/USAGE +5 -0
- data/lib/generators/tldr/install_generator.rb +24 -0
- data/lib/generators/tldr/templates/migration/create_cancelled_subscriptions_table.rb +12 -0
- data/lib/tldr/cancelled_subscription.rb +6 -0
- data/lib/tldr/subscriber.rb +15 -0
- data/lib/tldr/token_generator.rb +25 -0
- data/lib/tldr/version.rb +3 -0
- data/lib/tldr.rb +17 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/subscriber_spec.rb +26 -0
- data/spec/token_generator_spec.rb +31 -0
- data/spec/unsubscribe_spec.rb +29 -0
- data/tldr.gemspec +29 -0
- metadata +110 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 3927d48fa7ed1bc2ffaa5b949fcc5e537ab8b1b9
|
4
|
+
data.tar.gz: 009a5e9ab421831e0b301dd0c0680507959d255a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 54245e42ae469a77d759074aa612d1a75d070721a812d00d333140d8e080e36de10a8370205b502e90bff3240e3a415556b6a17f16411070e56fa1023e551257
|
7
|
+
data.tar.gz: 160b82c6df46aa3eb5fcbcfe6315fe86482a45d03196f393fb3e25f48e591e357e5cb97213b3adc7cf25290f51b035d09bce1957aa99e000e5174714c6ea10f1
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
tldr (0.0.1)
|
5
|
+
activerecord
|
6
|
+
rake
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
activemodel (4.0.2)
|
12
|
+
activesupport (= 4.0.2)
|
13
|
+
builder (~> 3.1.0)
|
14
|
+
activerecord (4.0.2)
|
15
|
+
activemodel (= 4.0.2)
|
16
|
+
activerecord-deprecated_finders (~> 1.0.2)
|
17
|
+
activesupport (= 4.0.2)
|
18
|
+
arel (~> 4.0.0)
|
19
|
+
activerecord-deprecated_finders (1.0.3)
|
20
|
+
activesupport (4.0.2)
|
21
|
+
i18n (~> 0.6, >= 0.6.4)
|
22
|
+
minitest (~> 4.2)
|
23
|
+
multi_json (~> 1.3)
|
24
|
+
thread_safe (~> 0.1)
|
25
|
+
tzinfo (~> 0.3.37)
|
26
|
+
arel (4.0.1)
|
27
|
+
atomic (1.1.14)
|
28
|
+
builder (3.1.4)
|
29
|
+
i18n (0.6.9)
|
30
|
+
metaclass (0.0.1)
|
31
|
+
minitest (4.7.5)
|
32
|
+
mocha (0.14.0)
|
33
|
+
metaclass (~> 0.0.1)
|
34
|
+
multi_json (1.8.2)
|
35
|
+
rake (10.1.1)
|
36
|
+
thread_safe (0.1.3)
|
37
|
+
atomic
|
38
|
+
tzinfo (0.3.38)
|
39
|
+
|
40
|
+
PLATFORMS
|
41
|
+
ruby
|
42
|
+
|
43
|
+
DEPENDENCIES
|
44
|
+
mocha
|
45
|
+
tldr!
|
data/README.md
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
tl;dr
|
2
|
+
====
|
3
|
+
|
4
|
+
Enable unsubscribe links within your emails
|
5
|
+
|
6
|
+
# Description
|
7
|
+
|
8
|
+
Some of your users don't want to hear from you or your shitty application. You can add unsubscribe links to your mail views so that your users can relieve themselves of the pain you have endured on them.
|
9
|
+
|
10
|
+
# Installation
|
11
|
+
|
12
|
+
```rb
|
13
|
+
# Gemfile
|
14
|
+
gem 'toolong-dontread'
|
15
|
+
```
|
16
|
+
|
17
|
+
```sh
|
18
|
+
rails g tldr:install
|
19
|
+
|
20
|
+
rake db:migrate
|
21
|
+
```
|
22
|
+
|
23
|
+
# Usage
|
24
|
+
|
25
|
+
Inside your mailer you can generate an uninstall url.
|
26
|
+
|
27
|
+
```rb
|
28
|
+
class AccountMailer < ActionMailer::Base
|
29
|
+
def new_follower_notification(user, follower)
|
30
|
+
...
|
31
|
+
token = Tldr::TokenGenerator.new(user, :new_follower_notification).token
|
32
|
+
@unsubscribe_url = unsubscribe_url(token)
|
33
|
+
...
|
34
|
+
end
|
35
|
+
end
|
36
|
+
```
|
37
|
+
|
38
|
+
Inside your model to test if someone is subscribed
|
39
|
+
|
40
|
+
```rb
|
41
|
+
class User < ActiveRecord::Base
|
42
|
+
include Tldr::Subscriber
|
43
|
+
end
|
44
|
+
|
45
|
+
# elsewhere
|
46
|
+
user = User.find params[:id]
|
47
|
+
user.subscribed_to? :new_follower_notification
|
48
|
+
```
|
49
|
+
|
50
|
+
Inside your controller if you are using Rails
|
51
|
+
|
52
|
+
```rb
|
53
|
+
class AccountsController < ApplicationController
|
54
|
+
def unsubscribe
|
55
|
+
subscription = Tldr.unsubscribe params[:token]
|
56
|
+
redirect_to dashboard_path(subscription.values[:user]), notice: 'You have successfully been unsubscribed from that stupid ass email'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
```
|
60
|
+
|
61
|
+
# Contributing
|
62
|
+
|
63
|
+
1. Clone the repository `git clone https://github.com/brilliantfantastic/tldr`
|
64
|
+
1. Create a feature branch `git checkout -b my-awesome-feature`
|
65
|
+
1. Codez!
|
66
|
+
1. Commit your changes (small commits please)
|
67
|
+
1. Push your new branch `git push origin my-awesome-feature`
|
68
|
+
1. Create a pull request `hub pull-request -b brilliantfantastic:master -h brilliantfantastic:my-awesome-feature`
|
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
|
3
|
+
module Tldr
|
4
|
+
module Generators
|
5
|
+
class InstallGenerator < Rails::Generators::Base
|
6
|
+
include Rails::Generators::Migration
|
7
|
+
|
8
|
+
source_root File.expand_path("../templates", __FILE__)
|
9
|
+
|
10
|
+
def copy_migrations
|
11
|
+
migration_template "migration/create_cancelled_subscriptions_table.rb", "db/migrate/create_cancelled_subscriptions_table.rb"
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.next_migration_number(dirname)
|
15
|
+
if ActiveRecord::Base.timestamped_migrations
|
16
|
+
sleep 1 # make sure each time we get a different timestamp
|
17
|
+
Time.new.utc.strftime("%Y%m%d%H%M%S")
|
18
|
+
else
|
19
|
+
"%.3d" % (current_migration_number(dirname) + 1)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class CreateCancelledSubscriptionsTable < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :cancelled_subscriptions do |t|
|
4
|
+
t.integer :subscriber_id, null: false
|
5
|
+
t.string :email_name, null: false
|
6
|
+
|
7
|
+
t.timestamps
|
8
|
+
end
|
9
|
+
|
10
|
+
add_index :cancelled_subscriptions, [:subscriber_id, :email_name]
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Tldr
|
2
|
+
module Subscriber
|
3
|
+
def self.included(klass)
|
4
|
+
klass.class_eval do
|
5
|
+
include InstanceMethods
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
module InstanceMethods
|
10
|
+
def subscribed_to?(email)
|
11
|
+
!Tldr::CancelledSubscription.exists?(subscriber_id: id, email_name: email)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'base64'
|
2
|
+
|
3
|
+
module Tldr
|
4
|
+
class TokenGenerator
|
5
|
+
attr_reader :token
|
6
|
+
|
7
|
+
def initialize(subscriber_id, email_name)
|
8
|
+
@subscriber_id = subscriber_id
|
9
|
+
@email_name = email_name
|
10
|
+
generate
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.decode(token)
|
14
|
+
result = Base64.urlsafe_decode64 token
|
15
|
+
values = result.split '|'
|
16
|
+
{subscriber_id: values[0], email_name: values[1].to_sym} if values.length == 2
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def generate
|
22
|
+
@token = Base64.urlsafe_encode64 "#{@subscriber_id}|#{@email_name}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/tldr/version.rb
ADDED
data/lib/tldr.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative 'tldr/version'
|
2
|
+
require_relative 'tldr/subscriber'
|
3
|
+
require_relative 'tldr/cancelled_subscription'
|
4
|
+
require_relative 'tldr/token_generator'
|
5
|
+
|
6
|
+
module Tldr
|
7
|
+
def self.unsubscribe(token)
|
8
|
+
values = Tldr::TokenGenerator.decode(token)
|
9
|
+
if values
|
10
|
+
conditions = {subscriber_id: values[:subscriber_id],
|
11
|
+
email_name: values[:email_name]}
|
12
|
+
unless Tldr::CancelledSubscription.exists? conditions
|
13
|
+
Tldr::CancelledSubscription.create! conditions
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe Tldr::Subscriber do
|
4
|
+
class User
|
5
|
+
include Tldr::Subscriber
|
6
|
+
attr_reader :id
|
7
|
+
|
8
|
+
def initialize(attrs={})
|
9
|
+
@id = attrs[:id]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#subscribed_to?' do
|
14
|
+
it 'returns true if the subscription exists for the subscriber' do
|
15
|
+
Tldr::CancelledSubscription.expects(:exists?).with(subscriber_id: 123, email_name: :some_email).returns false
|
16
|
+
user = User.new(id: 123)
|
17
|
+
user.subscribed_to?(:some_email).must_equal true
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'returns false if the subscriber has cancelled' do
|
21
|
+
Tldr::CancelledSubscription.expects(:exists?).with(subscriber_id: 123, email_name: :some_other_email).returns 1
|
22
|
+
user = User.new(id: 123)
|
23
|
+
user.subscribed_to?(:some_other_email).must_equal false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe Tldr::TokenGenerator do
|
4
|
+
it 'generates a url safe token for a given user and email' do
|
5
|
+
token = Tldr::TokenGenerator.new(123, :some_email).token
|
6
|
+
token.wont_be_nil
|
7
|
+
token.wont_match /^\s*$/
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'generates the same token for the same user and email' do
|
11
|
+
token1 = Tldr::TokenGenerator.new(123, :some_email).token
|
12
|
+
token2 = Tldr::TokenGenerator.new(123, :some_email).token
|
13
|
+
token1.must_equal token2
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '.decode' do
|
17
|
+
it 'returns a hash of values based on the token' do
|
18
|
+
subscriber_id = 123
|
19
|
+
email_name = :some_email
|
20
|
+
token = Tldr::TokenGenerator.new(subscriber_id, email_name).token
|
21
|
+
values = Tldr::TokenGenerator.decode(token)
|
22
|
+
values[:subscriber_id].must_equal subscriber_id.to_s
|
23
|
+
values[:email_name].must_equal email_name
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'handles a non base 64 token' do
|
27
|
+
values = Tldr::TokenGenerator.decode 'blah'
|
28
|
+
values.must_be_nil
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe 'unsubscribe a user' do
|
4
|
+
let(:subscriber_id) { 123 }
|
5
|
+
let(:email_name) { :some_email }
|
6
|
+
|
7
|
+
before(:all) do
|
8
|
+
@token = Tldr::TokenGenerator.new(subscriber_id, email_name).token
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'adds the subscriber to the CancelledSubscribers' do
|
12
|
+
Tldr::CancelledSubscription.expects(:exists?).returns(false)
|
13
|
+
Tldr::CancelledSubscription.expects(:create!).with({subscriber_id: subscriber_id.to_s, email_name: email_name})
|
14
|
+
Tldr.unsubscribe @token
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'does not try to insert an invalid token' do
|
18
|
+
Tldr::CancelledSubscription.expects(:create!).never
|
19
|
+
Tldr.unsubscribe 'blah'
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'does not unsubscribe twice' do
|
23
|
+
Tldr::CancelledSubscription.expects(:exists?).returns(false)
|
24
|
+
Tldr::CancelledSubscription.expects(:create!).with({subscriber_id: subscriber_id.to_s, email_name: email_name}).once
|
25
|
+
Tldr.unsubscribe @token
|
26
|
+
Tldr::CancelledSubscription.expects(:exists?).returns(true)
|
27
|
+
Tldr.unsubscribe @token
|
28
|
+
end
|
29
|
+
end
|
data/tldr.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'tldr/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "toolong-dontread"
|
8
|
+
spec.version = Tldr::VERSION
|
9
|
+
|
10
|
+
spec.authors = ["Jamie Wright"]
|
11
|
+
spec.email = ["jamie@brilliantfantastic.com"]
|
12
|
+
|
13
|
+
spec.summary = "Enable unsubscribe links in your email"
|
14
|
+
spec.description = %q{
|
15
|
+
Some of your users don't want to hear from you or your shitty application.
|
16
|
+
You can add unsubscribe links to your mail views so that your users can relieve themselves of the pain you have endured on them.
|
17
|
+
}
|
18
|
+
|
19
|
+
spec.homepage = "http://github.com/brilliantfantastic/tldr"
|
20
|
+
spec.license = "MIT"
|
21
|
+
|
22
|
+
spec.files = `git ls-files`.split($/)
|
23
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
24
|
+
spec.require_paths = ["lib"]
|
25
|
+
|
26
|
+
spec.add_dependency "rake"
|
27
|
+
spec.add_dependency "activerecord"
|
28
|
+
spec.add_development_dependency "mocha"
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: toolong-dontread
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jamie Wright
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-01-11 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activerecord
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: mocha
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: "\n Some of your users don't want to hear from
|
56
|
+
you or your shitty application. \n You can add unsubscribe
|
57
|
+
links to your mail views so that your users can relieve themselves of the pain you
|
58
|
+
have endured on them.\n "
|
59
|
+
email:
|
60
|
+
- jamie@brilliantfantastic.com
|
61
|
+
executables: []
|
62
|
+
extensions: []
|
63
|
+
extra_rdoc_files: []
|
64
|
+
files:
|
65
|
+
- Gemfile
|
66
|
+
- Gemfile.lock
|
67
|
+
- README.md
|
68
|
+
- Rakefile
|
69
|
+
- lib/generators/tldr/USAGE
|
70
|
+
- lib/generators/tldr/install_generator.rb
|
71
|
+
- lib/generators/tldr/templates/migration/create_cancelled_subscriptions_table.rb
|
72
|
+
- lib/tldr.rb
|
73
|
+
- lib/tldr/cancelled_subscription.rb
|
74
|
+
- lib/tldr/subscriber.rb
|
75
|
+
- lib/tldr/token_generator.rb
|
76
|
+
- lib/tldr/version.rb
|
77
|
+
- spec/spec_helper.rb
|
78
|
+
- spec/subscriber_spec.rb
|
79
|
+
- spec/token_generator_spec.rb
|
80
|
+
- spec/unsubscribe_spec.rb
|
81
|
+
- tldr.gemspec
|
82
|
+
homepage: http://github.com/brilliantfantastic/tldr
|
83
|
+
licenses:
|
84
|
+
- MIT
|
85
|
+
metadata: {}
|
86
|
+
post_install_message:
|
87
|
+
rdoc_options: []
|
88
|
+
require_paths:
|
89
|
+
- lib
|
90
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - '>='
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - '>='
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
requirements: []
|
101
|
+
rubyforge_project:
|
102
|
+
rubygems_version: 2.0.3
|
103
|
+
signing_key:
|
104
|
+
specification_version: 4
|
105
|
+
summary: Enable unsubscribe links in your email
|
106
|
+
test_files:
|
107
|
+
- spec/spec_helper.rb
|
108
|
+
- spec/subscriber_spec.rb
|
109
|
+
- spec/token_generator_spec.rb
|
110
|
+
- spec/unsubscribe_spec.rb
|