digestifier 0.1.0 → 0.2.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 27be6b151cd80d803e6c983feb87ea0e352bb61e
4
- data.tar.gz: 7260331532953aaffeaa84f8d72ca492938aeb74
3
+ metadata.gz: 39498bf10b95798271d89f3db5eb5b871afe556e
4
+ data.tar.gz: 0d72ce2b9e333cde60c0c70bb172fecd17309f25
5
5
  SHA512:
6
- metadata.gz: 98e6c3b0b4f8ba45f75dd767ffc4de7a8bdb78bf61381e301b41c56d3f0fba7786fbeb7dacfeea761bc2dce191cde02b197a34cb9a24918506da026845ec4faf
7
- data.tar.gz: c504707b89804f761a826ae669e2ccf1f606183867b4be7e4ce4bbba6b78399fcd4904e02abb4f18ef6656a9df6227d58b00256926476f4347cf3d2f8f08d9e5
6
+ metadata.gz: b7fa6833c029c04c3e3ca31603058cbbad44422daebbb8d0dc7f6c0cb7a2070726c5d5ef703142ad8142134c390b182ebb533ca974c4bb662a1772b44822eb4b
7
+ data.tar.gz: 0f7693a1e3b202bbfc4e37ff82b6de376cc543dd9959acb6a0db163d9e1960d3de90ba165e13e683b6809a161a97e48ad372fdc03508cae31894639e44e2c610
data/README.md CHANGED
@@ -6,7 +6,7 @@ A simple Rails engine for sending out email digests of activity.
6
6
 
7
7
  Add this line to your application's Gemfile:
8
8
 
9
- gem 'digestifier', '0.1.0'
9
+ gem 'digestifier', '0.2.0'
10
10
 
11
11
  Don't forget to bundle:
12
12
 
@@ -28,11 +28,10 @@ Digestifier.sender = 'Hello <hello@inspire9.com>'
28
28
 
29
29
  # Set the digest object to a constant so it can be referred to elsewhere.
30
30
  DIGEST = Digestifier::Digest.new
31
- # Set the lambda that returns objects for the digest. This takes a single
32
- # argument - the time range - and should return a collection of objects. How
33
- # you get this collection is up to you, but the example below is a decent
34
- # starting point.
35
- DIGEST.contents = lambda { |range|
31
+ # Set the lambda that returns objects for the digest. This takes two arguments # - the recipient in question, and the time range - and should return a
32
+ # collection of objects. How you get this collection is up to you, but the
33
+ # example below is a decent starting point.
34
+ DIGEST.contents = lambda { |recipient, range|
36
35
  Article.where(created_at: range).order(:created_at)
37
36
  }
38
37
  # The digest recipients defaults to all User objects in your system. If you
@@ -118,6 +117,8 @@ Don't forget to include an unsubscribe link:
118
117
 
119
118
  ```erb
120
119
  <%= link_to 'Unsubscribe', unsubscribe_url_for(@recipient) %>
120
+ <!-- Or, if you've given your digest a label: -->
121
+ <%= link_to 'Unsubscribe', unsubscribe_url_for(@recipient, :news) %>
121
122
  ```
122
123
 
123
124
  Also: you'll very likely want to customise the email's subject - this is done via Rails' internationalisation:
@@ -151,6 +152,8 @@ class CustomMailer < ActionMailer::Base
151
152
 
152
153
  ### Contributing
153
154
 
155
+ Please note that this project is released with [a Contributor Code of Conduct](http://contributor-covenant.org/version/1/2/0/). By participating in this project you agree to abide by its terms.
156
+
154
157
  1. Fork this repository.
155
158
  2. Install [git-flow](https://github.com/nvie/gitflow/wiki/Installation) if you don't have it already, then initialise it within your local copy of this repository (`git flow init` - we stick with the defaults).
156
159
  3. Create your feature branch (`git flow feature start my-new-feature`)
@@ -160,4 +163,4 @@ class CustomMailer < ActionMailer::Base
160
163
 
161
164
  ## Licence
162
165
 
163
- Copyright (c) 2013-2014, Digestifier is developed and maintained by [Inspire9](http://inspire9.com), and is released under the open MIT Licence.
166
+ Copyright (c) 2013-2015, Digestifier is developed and maintained by [Inspire9](http://inspire9.com), and is released under the open MIT Licence.
@@ -1,11 +1,11 @@
1
1
  module Digestifier::UnsubscribesHelper
2
- def unsubscribe_path_for(user)
3
- setting = Digestifier::Setting.for(user)
2
+ def unsubscribe_path_for(user, digest = :digest)
3
+ setting = Digestifier::Setting.for(user, digest)
4
4
  digestifier.unsubscribe_path(setting.identifier)
5
5
  end
6
6
 
7
- def unsubscribe_url_for(user)
8
- setting = Digestifier::Setting.for(user)
7
+ def unsubscribe_url_for(user, digest = :digest)
8
+ setting = Digestifier::Setting.for(user, digest)
9
9
  digestifier.unsubscribe_url(setting.identifier)
10
10
  end
11
11
  end
@@ -12,11 +12,18 @@ class Digestifier::Setting < ActiveRecord::Base
12
12
  before_validation :set_identifier, on: :create
13
13
 
14
14
  def self.for(recipient, digest = :digest)
15
- where(
16
- digest: digest,
17
- recipient_type: recipient.class.name,
18
- recipient_id: recipient.id
19
- ).first || create(digest: digest, recipient: recipient)
15
+ attempts = 0
16
+ begin
17
+ where(
18
+ digest: digest,
19
+ recipient_type: recipient.class.name,
20
+ recipient_id: recipient.id
21
+ ).first || create(digest: digest, recipient: recipient)
22
+ rescue ActiveRecord::RecordNotUnique
23
+ attempts += 1
24
+ retry if attempts < 2
25
+ raise
26
+ end
20
27
  end
21
28
 
22
29
  def set_identifier!
@@ -4,7 +4,7 @@ class CreateSettings < ActiveRecord::Migration
4
4
  t.string :recipient_type, null: false
5
5
  t.integer :recipient_id, null: false
6
6
  t.text :preferences, null: false, default: '{}'
7
- t.timestamps
7
+ t.timestamps null: false
8
8
  end
9
9
 
10
10
  add_index :digestifier_settings, [:recipient_type, :recipient_id],
@@ -2,5 +2,6 @@ class AddEnabledToSettings < ActiveRecord::Migration
2
2
  def change
3
3
  add_column :digestifier_settings, :enabled, :boolean, default: true,
4
4
  null: false
5
+ Digestifier::Setting.reset_column_information
5
6
  end
6
7
  end
@@ -1,6 +1,7 @@
1
1
  class AddIdentifierToSettings < ActiveRecord::Migration
2
2
  def up
3
3
  add_column :digestifier_settings, :identifier, :string
4
+ Digestifier::Setting.reset_column_information
4
5
 
5
6
  Digestifier::Setting.find_each do |setting|
6
7
  setting.set_identifier!
@@ -12,5 +13,6 @@ class AddIdentifierToSettings < ActiveRecord::Migration
12
13
 
13
14
  def down
14
15
  remove_column :digestifier_settings, :identifier
16
+ Digestifier::Setting.reset_column_information
15
17
  end
16
18
  end
@@ -2,6 +2,7 @@ class AddDigestToSettings < ActiveRecord::Migration
2
2
  def up
3
3
  add_column :digestifier_settings, :digest, :string
4
4
  execute "UPDATE digestifier_settings SET digest = 'digest'"
5
+ Digestifier::Setting.reset_column_information
5
6
 
6
7
  change_column :digestifier_settings, :digest, :string, null: false
7
8
  add_index :digestifier_settings, :digest
@@ -14,6 +15,7 @@ class AddDigestToSettings < ActiveRecord::Migration
14
15
  def down
15
16
  remove_index :digestifier_settings, name: 'unique_recipients'
16
17
  remove_column :digestifier_settings, :digest
18
+ Digestifier::Setting.reset_column_information
17
19
 
18
20
  add_index :digestifier_settings, [:recipient_type, :recipient_id],
19
21
  unique: true
@@ -2,6 +2,7 @@ class AddDigestToReceipts < ActiveRecord::Migration
2
2
  def up
3
3
  add_column :digestifier_receipts, :digest, :string
4
4
  execute "UPDATE digestifier_receipts SET digest = 'digest'"
5
+ Digestifier::Receipt.reset_column_information
5
6
 
6
7
  change_column :digestifier_receipts, :digest, :string, null: false
7
8
  add_index :digestifier_receipts, :digest
@@ -14,6 +15,7 @@ class AddDigestToReceipts < ActiveRecord::Migration
14
15
  def down
15
16
  remove_index :digestifier_receipts, name: 'unique_digest_receipts'
16
17
  remove_column :digestifier_receipts, :digest
18
+ Digestifier::Receipt.reset_column_information
17
19
 
18
20
  add_index :digestifier_receipts, [:recipient_type, :recipient_id],
19
21
  unique: true
@@ -1,7 +1,7 @@
1
1
  # coding: utf-8
2
2
  Gem::Specification.new do |spec|
3
3
  spec.name = 'digestifier'
4
- spec.version = '0.1.0'
4
+ spec.version = '0.2.0'
5
5
  spec.authors = ['Pat Allan']
6
6
  spec.email = ['pat@freelancing-gods.com']
7
7
  spec.summary = 'Digests as a Rails Engine'
@@ -17,6 +17,6 @@ Gem::Specification.new do |spec|
17
17
  spec.add_runtime_dependency 'rails', '>= 3.2'
18
18
 
19
19
  spec.add_development_dependency 'combustion', '~> 0.5.1'
20
- spec.add_development_dependency 'rspec-rails', '~> 2.14.0'
21
- spec.add_development_dependency 'sqlite3', '~> 1.3.8'
20
+ spec.add_development_dependency 'rspec-rails', '~> 3.3.3'
21
+ spec.add_development_dependency 'sqlite3', '~> 1.3.10'
22
22
  end
@@ -1,7 +1,7 @@
1
1
  class Digestifier::Delivery
2
2
  def self.deliver(digest)
3
3
  digest.recipients.call.find_each do |recipient|
4
- new(digest, recipient).deliver_and_capture
4
+ Digestifier::Delivery.new(digest, recipient).deliver_and_capture
5
5
  end
6
6
  end
7
7
 
@@ -31,7 +31,7 @@ class Digestifier::Delivery
31
31
  delegate :default_frequency, to: :digest
32
32
 
33
33
  def contents
34
- digest.contents.call(last_sent..Time.zone.now)
34
+ digest.contents.call(recipient, last_sent..Time.zone.now)
35
35
  end
36
36
 
37
37
  def frequency
@@ -42,7 +42,7 @@ class Digestifier::Delivery
42
42
 
43
43
  def last_sent
44
44
  receipt = Digestifier::Receipt.last_for(recipient, digest.identifier)
45
- receipt.nil? ? frequency.ago : receipt.captured_at
45
+ receipt.nil? ? frequency.to_i.seconds.ago : receipt.captured_at
46
46
  end
47
47
 
48
48
  def settings
@@ -1,13 +1,13 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe 'Custom digest partials' do
3
+ RSpec.describe 'Custom digest partials' do
4
4
  let(:digest) { Digestifier::Digest.new }
5
5
  let(:user) { User.create! email: 'me@somewhere.com' }
6
6
 
7
7
  before :each do
8
8
  ActionMailer::Base.deliveries.clear
9
9
 
10
- digest.contents = lambda { |range|
10
+ digest.contents = lambda { |user, range|
11
11
  Book.where(created_at: range).order(:created_at)
12
12
  }
13
13
 
@@ -1,13 +1,13 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe 'Delivering digests' do
3
+ RSpec.describe 'Delivering digests' do
4
4
  let(:digest) { Digestifier::Digest.new }
5
5
  let(:user) { User.create! email: 'me@somewhere.com' }
6
6
 
7
7
  before :each do
8
8
  ActionMailer::Base.deliveries.clear
9
9
 
10
- digest.contents = lambda { |range|
10
+ digest.contents = lambda { |user, range|
11
11
  Article.where(created_at: range).order(:created_at)
12
12
  }
13
13
 
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe 'Multiple Digests' do
3
+ RSpec.describe 'Multiple Digests' do
4
4
  let(:food_digest) { Digestifier::Digest.new :food }
5
5
  let(:tech_digest) { Digestifier::Digest.new :tech }
6
6
  let(:user) { User.create! email: 'me@somewhere.com' }
@@ -8,10 +8,10 @@ describe 'Multiple Digests' do
8
8
  before :each do
9
9
  ActionMailer::Base.deliveries.clear
10
10
 
11
- food_digest.contents = lambda { |range|
11
+ food_digest.contents = lambda { |user, range|
12
12
  Article.category('food').where(created_at: range).order(:created_at)
13
13
  }
14
- tech_digest.contents = lambda { |range|
14
+ tech_digest.contents = lambda { |user, range|
15
15
  Article.category('tech').where(created_at: range).order(:created_at)
16
16
  }
17
17
 
@@ -85,16 +85,16 @@ describe 'Multiple Digests' do
85
85
 
86
86
  Digestifier::Delivery.deliver food_digest
87
87
 
88
- ActionMailer::Base.deliveries.detect { |mail|
88
+ expect(ActionMailer::Base.deliveries.detect { |mail|
89
89
  mail.to.include?('me@somewhere.com')
90
- }.should_not be_nil
90
+ }).not_to be_nil
91
91
 
92
92
  ActionMailer::Base.deliveries.clear
93
93
 
94
94
  Digestifier::Delivery.deliver tech_digest
95
95
 
96
- ActionMailer::Base.deliveries.detect { |mail|
96
+ expect(ActionMailer::Base.deliveries.detect { |mail|
97
97
  mail.to.include?('me@somewhere.com')
98
- }.should be_nil
98
+ }).to be_nil
99
99
  end
100
100
  end
@@ -1,13 +1,13 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe 'Custom digest frequency' do
3
+ RSpec.describe 'Custom digest frequency' do
4
4
  let(:digest) { Digestifier::Digest.new }
5
5
  let(:user) { User.create! email: 'me@somewhere.com' }
6
6
 
7
7
  before :each do
8
8
  ActionMailer::Base.deliveries.clear
9
9
 
10
- digest.contents = lambda { |range|
10
+ digest.contents = lambda { |user, range|
11
11
  Article.where(created_at: range).order(:created_at)
12
12
  }
13
13
  end
@@ -39,8 +39,8 @@ describe 'Custom digest frequency' do
39
39
 
40
40
  Digestifier::Delivery.deliver digest
41
41
 
42
- ActionMailer::Base.deliveries.detect { |mail|
42
+ expect(ActionMailer::Base.deliveries.detect { |mail|
43
43
  mail.to.include?('me@somewhere.com')
44
- }.should be_nil
44
+ }).to be_nil
45
45
  end
46
46
  end
@@ -1,15 +1,15 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe 'Unsubscribing' do
3
+ RSpec.describe 'Unsubscribing', type: :request do
4
4
  let(:user) { User.create! email: 'me@somewhere.com' }
5
5
 
6
6
  it "marks a user as unsubscribed" do
7
7
  setting = Digestifier::Setting.for(user)
8
- expect(setting.enabled).to be_true
8
+ expect(setting.enabled).to eq(true)
9
9
 
10
10
  get "/digests/unsubscribe/#{setting.identifier}"
11
11
 
12
12
  setting.reload
13
- expect(setting.enabled).to be_false
13
+ expect(setting.enabled).to eq(false)
14
14
  end
15
15
  end
@@ -2,16 +2,16 @@ ActiveRecord::Schema.define do
2
2
  create_table :articles, :force => true do |table|
3
3
  table.string :name
4
4
  table.string :category
5
- table.timestamps
5
+ table.timestamps null: false
6
6
  end
7
7
 
8
8
  create_table :books, :force => true do |table|
9
9
  table.string :title
10
- table.timestamps
10
+ table.timestamps null: false
11
11
  end
12
12
 
13
13
  create_table :users, :force => true do |table|
14
14
  table.string :email
15
- table.timestamps
15
+ table.timestamps null: false
16
16
  end
17
17
  end
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Digestifier::Setting, type: :model do
4
+ describe '.for' do
5
+ let(:setting) { double 'Setting' }
6
+ let(:recipient) { double 'Recipient', id: 389 }
7
+
8
+ it 'returns an existing setting' do
9
+ allow(Digestifier::Setting).to receive(:where).and_return([setting])
10
+
11
+ expect(Digestifier::Setting.for(recipient)).to eq(setting)
12
+ end
13
+
14
+ it 'creates a new setting if it does not exist' do
15
+ allow(Digestifier::Setting).to receive(:where).and_return([])
16
+ allow(Digestifier::Setting).to receive(:create).and_return(setting)
17
+
18
+ expect(Digestifier::Setting.for(recipient)).to eq(setting)
19
+ end
20
+
21
+ it 'retries find if create raises an exception' do
22
+ attempts = 0
23
+ allow(Digestifier::Setting).to receive(:where).and_return([])
24
+ allow(Digestifier::Setting).to receive(:create) do |attributes|
25
+ attempts += 1
26
+ raise ActiveRecord::RecordNotUnique, 'fail' if attempts <= 1
27
+ setting
28
+ end
29
+
30
+ expect(Digestifier::Setting.for(recipient)).to eq(setting)
31
+ end
32
+
33
+ it 'raises an error if create fails twice' do
34
+ attempts = 0
35
+ allow(Digestifier::Setting).to receive(:where).and_return([])
36
+ allow(Digestifier::Setting).to receive(:create) do |attributes|
37
+ attempts += 1
38
+ raise ActiveRecord::RecordNotUnique, 'fail' if attempts <= 2
39
+ setting
40
+ end
41
+
42
+ expect { Digestifier::Setting.for(recipient) }.
43
+ to raise_error(ActiveRecord::RecordNotUnique)
44
+ end
45
+ end
46
+ end
@@ -13,7 +13,4 @@ Dir["./spec/support/**/*.rb"].each { |file| require file }
13
13
 
14
14
  RSpec.configure do |config|
15
15
  config.use_transactional_fixtures = true
16
-
17
- config.include RSpec::Rails::RequestExampleGroup, type: :request,
18
- example_group: {file_path: /spec\/acceptance/}
19
16
  end
metadata CHANGED
@@ -1,71 +1,71 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: digestifier
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pat Allan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-28 00:00:00.000000000 Z
11
+ date: 2015-08-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '3.2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '3.2'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: combustion
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: 0.5.1
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: 0.5.1
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec-rails
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ~>
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 2.14.0
47
+ version: 3.3.3
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ~>
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 2.14.0
54
+ version: 3.3.3
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: sqlite3
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ~>
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 1.3.8
61
+ version: 1.3.10
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ~>
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 1.3.8
68
+ version: 1.3.10
69
69
  description: A Rails engine that lets you define and customise digest emails
70
70
  email:
71
71
  - pat@freelancing-gods.com
@@ -73,8 +73,8 @@ executables: []
73
73
  extensions: []
74
74
  extra_rdoc_files: []
75
75
  files:
76
- - .gitignore
77
- - .travis.yml
76
+ - ".gitignore"
77
+ - ".travis.yml"
78
78
  - Gemfile
79
79
  - LICENSE.txt
80
80
  - README.md
@@ -117,6 +117,7 @@ files:
117
117
  - spec/internal/db/schema.rb
118
118
  - spec/internal/log/.gitignore
119
119
  - spec/internal/public/favicon.ico
120
+ - spec/models/digestifier/setting_spec.rb
120
121
  - spec/spec_helper.rb
121
122
  homepage: https://github.com/inspire9/digestifier
122
123
  licenses:
@@ -128,17 +129,17 @@ require_paths:
128
129
  - lib
129
130
  required_ruby_version: !ruby/object:Gem::Requirement
130
131
  requirements:
131
- - - '>='
132
+ - - ">="
132
133
  - !ruby/object:Gem::Version
133
134
  version: '0'
134
135
  required_rubygems_version: !ruby/object:Gem::Requirement
135
136
  requirements:
136
- - - '>='
137
+ - - ">="
137
138
  - !ruby/object:Gem::Version
138
139
  version: '0'
139
140
  requirements: []
140
141
  rubyforge_project:
141
- rubygems_version: 2.2.2
142
+ rubygems_version: 2.4.8
142
143
  signing_key:
143
144
  specification_version: 4
144
145
  summary: Digests as a Rails Engine
@@ -159,4 +160,5 @@ test_files:
159
160
  - spec/internal/db/schema.rb
160
161
  - spec/internal/log/.gitignore
161
162
  - spec/internal/public/favicon.ico
163
+ - spec/models/digestifier/setting_spec.rb
162
164
  - spec/spec_helper.rb