gudleik-acts_as_expired 0.0.2
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.
- data/MIT-LICENSE +20 -0
- data/README.rdoc +76 -0
- data/generators/acts_as_expired_mailer/acts_as_expired_mailer_generator.rb +11 -0
- data/generators/acts_as_expired_mailer/templates/notification.text.html.erb +26 -0
- data/generators/acts_as_expired_mailer/templates/notification.text.plain.erb +12 -0
- data/generators/acts_as_expired_on_migration/acts_as_expired_on_migration_generator.rb +7 -0
- data/generators/acts_as_expired_on_migration/templates/migration.rb +26 -0
- data/init.rb +1 -0
- data/lib/acts_as_expired.rb +71 -0
- data/lib/expire.rb +64 -0
- data/lib/expired_mailer.rb +18 -0
- data/rails/init.rb +5 -0
- data/tasks/acts_as_expired_tasks.rake +25 -0
- metadata +65 -0
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright (c) 2009 [name of plugin creator]
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
= ActsAsExpired
|
|
2
|
+
|
|
3
|
+
Acts as Expired allows you to set expiration information to any ActiveRecord based model.
|
|
4
|
+
|
|
5
|
+
== Installation
|
|
6
|
+
|
|
7
|
+
Install using gems:
|
|
8
|
+
|
|
9
|
+
# config/environment.rb
|
|
10
|
+
config.gem 'gudleik-acts_as_expired', :lib => 'acts_as_expired', :source => 'http://gems.github.com'
|
|
11
|
+
|
|
12
|
+
$ sudo rake gems:install
|
|
13
|
+
$ script/generate acts_as_expired_on_migration
|
|
14
|
+
$ rake db:migrate
|
|
15
|
+
|
|
16
|
+
== Usage
|
|
17
|
+
|
|
18
|
+
Add acts_as_expired to your ActiveRecord model:
|
|
19
|
+
|
|
20
|
+
class Foobar < ActiveRecord::Base
|
|
21
|
+
acts_as_expired
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
Now you can set expiry date using +expires!+
|
|
25
|
+
# Set expiry using default settings
|
|
26
|
+
Foobar.first.expires!
|
|
27
|
+
|
|
28
|
+
# Set expiry date 1 year ahead, and notification time 2 days before expiry
|
|
29
|
+
Foobar.first.expires! :at => 1.year.from.now, :notify_at => 2.days
|
|
30
|
+
|
|
31
|
+
# Set expiry date to 2010-01-01 and notification set to 12-01-2009
|
|
32
|
+
Foobar.first.expires! :at => Time.mktime(2010), :notify_at => Time.mktime(2009, 12)
|
|
33
|
+
|
|
34
|
+
# Find out if object has expired
|
|
35
|
+
Foobar.first.expired? # => true / false
|
|
36
|
+
|
|
37
|
+
Expire has some named scopes you can use to find expired/expiring objects.
|
|
38
|
+
|
|
39
|
+
# Find objects that has expired
|
|
40
|
+
Expire.expired # => array of expired objects
|
|
41
|
+
|
|
42
|
+
# Loop thru objects that are about to expire
|
|
43
|
+
Expire.within(3.months.from_now).each { |expire| puts "#{expire.expirable.to_s} expires in #{time_ago_in_words(expire.at)}" }
|
|
44
|
+
|
|
45
|
+
== Notifications
|
|
46
|
+
|
|
47
|
+
You can also set notification options to the Expire object, using +notify_at+ and +notify_email+.
|
|
48
|
+
+notify_at+ is when notification should be sent, and +notify_email+ is the email address the notification should be sent to.
|
|
49
|
+
|
|
50
|
+
The gem does not provide any methods to automatically send notifications, this is up to you.
|
|
51
|
+
But here is an example of how this can be done. First create an ExpiredMailer:
|
|
52
|
+
|
|
53
|
+
# app/models/expired_mailer.rb
|
|
54
|
+
class ExpiredMailer < ActionMailer::Base
|
|
55
|
+
def notification(object)
|
|
56
|
+
raise ArgumentError, "notify_email not set!" if object.notify_email.blank?
|
|
57
|
+
|
|
58
|
+
recipients object.notify_email
|
|
59
|
+
subject "Notification about expiring object"
|
|
60
|
+
from "dev-null@localhost"
|
|
61
|
+
body :object => object
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
Then setup a cronjob and run something like this using a rake task or script/runner:
|
|
66
|
+
|
|
67
|
+
Expire.notifiable.each do |expired|
|
|
68
|
+
ExpiredMailer.deliver_notification(expired)
|
|
69
|
+
expired.update_attribute(:notified_at, Time.now)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
The gem ships with an ExpiredMailer, you can install it with 'script/generate acts_as_expired_mailer'.
|
|
73
|
+
But it's not made to be portable, so it probably won't work out-of-the-box.
|
|
74
|
+
I recommend you create your own expired_mailer.
|
|
75
|
+
|
|
76
|
+
Copyright (c) 2009 Gudleik Rasch <gudleik@rastamatra.org>, released under the MIT license
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
class ActsAsExpiredMailerGenerator < Rails::Generator::Base
|
|
2
|
+
|
|
3
|
+
def manifest
|
|
4
|
+
record do |m|
|
|
5
|
+
m.directory "app/views/expired_mailer"
|
|
6
|
+
m.file 'notification.text.html.erb', 'app/views/expired_mailer/notification.text.html.erb'
|
|
7
|
+
m.file 'notification.text.plain.erb', 'app/views/expired_mailer/notification.text.plain.erb'
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<p>
|
|
2
|
+
<%= t('.intro') %>
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<ul>
|
|
6
|
+
<li>
|
|
7
|
+
<a href="<%= Settings.mail.url_options.protocol %>://<%= Settings.mail.url_options.host %><%= url_for(@object.expirable) %>"><%= @object.expirable.to_s %></a>
|
|
8
|
+
|
|
9
|
+
<br/>
|
|
10
|
+
<b><%= Expire.human_attribute_name('at') %></b>: <%= @object.at.strftime("%Y-%m-%d") -%>
|
|
11
|
+
</li>
|
|
12
|
+
</ul>
|
|
13
|
+
|
|
14
|
+
<% if @object.note -%>
|
|
15
|
+
<p>
|
|
16
|
+
<%= Expire.human_attribute_name("notes") -%>:
|
|
17
|
+
<div style="margin:1em">
|
|
18
|
+
<%= @object.note -%>
|
|
19
|
+
</div>
|
|
20
|
+
</p>
|
|
21
|
+
<% end -%>
|
|
22
|
+
|
|
23
|
+
<p>
|
|
24
|
+
--<br/>
|
|
25
|
+
<%= t('.signature', :app_name => Settings.app.name) %>
|
|
26
|
+
</p>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<%= t('.intro') %>
|
|
2
|
+
|
|
3
|
+
* <%= @object.expirable.to_s %> <<%= Settings.mail.url_options.protocol %>://<%= Settings.mail.url_options.host %><%= url_for(@object.expirable) %>>
|
|
4
|
+
<%= Expire.human_attribute_name('at') %>: <%= @object.at.strftime("%Y-%m-%d") -%>
|
|
5
|
+
|
|
6
|
+
<% if @object.note -%>
|
|
7
|
+
<%= Expire.human_attribute_name("notes") -%>:
|
|
8
|
+
<%= @object.note -%>
|
|
9
|
+
<% end -%>
|
|
10
|
+
|
|
11
|
+
--
|
|
12
|
+
<%= t('.signature', :app_name => Settings.app.name) %>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
class ActsAsExpiredOnMigration < ActiveRecord::Migration
|
|
2
|
+
|
|
3
|
+
def self.up
|
|
4
|
+
create_table :expires do |t|
|
|
5
|
+
t.integer :expirable_id
|
|
6
|
+
t.string :expirable_type, :limit => 30
|
|
7
|
+
|
|
8
|
+
t.text :note
|
|
9
|
+
t.timestamp :at
|
|
10
|
+
t.string :notify_email
|
|
11
|
+
t.timestamp :notify_at, :default => nil
|
|
12
|
+
t.timestamp :notified_at, :default => nil
|
|
13
|
+
|
|
14
|
+
t.timestamps
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
add_index :expires, [ :expirable_id, :expirable_type ], :unique => true
|
|
18
|
+
add_index :expires, :notify_at
|
|
19
|
+
add_index :expires, :at
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.down
|
|
23
|
+
drop_table :expires
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
data/init.rb
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + "/rails/init"
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# ActsAsExpired
|
|
2
|
+
#
|
|
3
|
+
# This module is included in ActiveRecord::Base, so you can add this feature
|
|
4
|
+
# to your model using +acts_as_expirable+.
|
|
5
|
+
#
|
|
6
|
+
# Making an ActiveRecord class "acts as expired" means you can add expiry
|
|
7
|
+
# information to it.
|
|
8
|
+
|
|
9
|
+
module ActsAsExpired
|
|
10
|
+
|
|
11
|
+
#
|
|
12
|
+
# Called when plugin is included
|
|
13
|
+
#
|
|
14
|
+
def self.included(base)
|
|
15
|
+
base.extend(ClassMethods)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
module ClassMethods
|
|
19
|
+
def acts_as_expired
|
|
20
|
+
include ActsAsExpired::InstanceMethods
|
|
21
|
+
has_one :expire, :as => :expirable
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
module InstanceMethods
|
|
26
|
+
|
|
27
|
+
# Returns true if the object has expired.
|
|
28
|
+
def expired?
|
|
29
|
+
return false if expire.nil?
|
|
30
|
+
expire.expired?
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
#
|
|
34
|
+
# Creates or updates the Expire object for the class.
|
|
35
|
+
#
|
|
36
|
+
# The options hash is passed directly to the Expire object, so you can pass
|
|
37
|
+
# any valid attribute found in the Expire class.
|
|
38
|
+
#
|
|
39
|
+
# Some values have default settings:
|
|
40
|
+
# * :at Time when object should expire. Default is 1.year.from_now
|
|
41
|
+
# * :notify_at Time when notification should be sent. Default is 30.days before :at
|
|
42
|
+
# You can pass both a Time object or a Fixnum, like 30.days
|
|
43
|
+
# * :notify_email Email address that should receive expiry email. Default is nil.
|
|
44
|
+
#
|
|
45
|
+
# Returns the expire object.
|
|
46
|
+
# An error is raised if the record is invalid.
|
|
47
|
+
#
|
|
48
|
+
def expires!(options = {})
|
|
49
|
+
options = {
|
|
50
|
+
:at => 1.year.from_now,
|
|
51
|
+
:notify_at => 30.days,
|
|
52
|
+
:notify_email => nil
|
|
53
|
+
}.update(options)
|
|
54
|
+
|
|
55
|
+
# set notify_at
|
|
56
|
+
if options[:notify_at].is_a?(Fixnum)
|
|
57
|
+
options[:notify_at] = options[:notify_at].until(options[:at])
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Create or update existing object
|
|
61
|
+
if self.expire.nil?
|
|
62
|
+
self.expire = Expire.create!(options)
|
|
63
|
+
else
|
|
64
|
+
self.expire.update_attributes!(options)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
self.expire
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
end
|
data/lib/expire.rb
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# This class holds information about the expiration,
|
|
2
|
+
# such as time when object expires and notification options.
|
|
3
|
+
#
|
|
4
|
+
# create_table :expires do |t|
|
|
5
|
+
# t.integer :expirable_id
|
|
6
|
+
# t.string :expirable_type, :limit => 30
|
|
7
|
+
#
|
|
8
|
+
# t.text :note
|
|
9
|
+
# t.timestamp :at
|
|
10
|
+
# t.string :notify_email
|
|
11
|
+
# t.timestamp :notify_at, :default => nil
|
|
12
|
+
# t.timestamp :notified_at, :default => nil
|
|
13
|
+
#
|
|
14
|
+
# t.timestamps
|
|
15
|
+
# end
|
|
16
|
+
#
|
|
17
|
+
# There are also some named scopes you can use to fetch all expired/expiring objects:
|
|
18
|
+
# Some examples:
|
|
19
|
+
# Expire.expired # => all expired objects
|
|
20
|
+
# Expire.notifiable # => all objects that are about to expire with notification options set.
|
|
21
|
+
# Expire.within # => all objects that expires within 2 weeks from now
|
|
22
|
+
# Expire.within 3.months.from_now # => returns all objects that expires within 3 months from now
|
|
23
|
+
#
|
|
24
|
+
class Expire < ActiveRecord::Base
|
|
25
|
+
|
|
26
|
+
belongs_to :expirable, :polymorphic => true
|
|
27
|
+
|
|
28
|
+
validate :validate_dates
|
|
29
|
+
|
|
30
|
+
# All expired objects
|
|
31
|
+
named_scope :expired, :conditions => [ 'NOW() >= at' ], :order => 'expires.at'
|
|
32
|
+
|
|
33
|
+
# All notifiable objects that are about to expire
|
|
34
|
+
named_scope :notifiable, :conditions => [ "NOW() >= notify_at AND (NOW() <= notified_at OR notified_at IS NULL) AND notify_email != ''"], :order => 'expires.at'
|
|
35
|
+
|
|
36
|
+
# All objects that are about to expire
|
|
37
|
+
named_scope :within, lambda { |*args| { :conditions => [ "at <= ?", (args.first || 2.weeks.from_now )]} }
|
|
38
|
+
|
|
39
|
+
#
|
|
40
|
+
# Returns true if object has expired
|
|
41
|
+
#
|
|
42
|
+
def expired?
|
|
43
|
+
return false if at.nil?
|
|
44
|
+
return at.past?
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
#
|
|
48
|
+
# Notification is only enabled if notify_email and notify_at is set
|
|
49
|
+
#
|
|
50
|
+
def notification_enabled?
|
|
51
|
+
not notify_email.blank? and not notify_at.nil?
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
#
|
|
57
|
+
# Make sure expiry date is in future and notification date is before expiry date
|
|
58
|
+
#
|
|
59
|
+
def validate_dates
|
|
60
|
+
errors.add(:at, :expire_date_is_in_past) if self.at < Time.now
|
|
61
|
+
errors.add(:notify_at, :notify_date_is_before_expiry_date) if self.notify_at > self.at
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Class for sending alerts when objects are about to expire.
|
|
2
|
+
|
|
3
|
+
class ExpiredMailer < ActionMailer::Base
|
|
4
|
+
|
|
5
|
+
#
|
|
6
|
+
# Send notification about an expiring object
|
|
7
|
+
#
|
|
8
|
+
def notification(object)
|
|
9
|
+
raise ArgumentError, "notify_email not set!" if object.notify_email.blank?
|
|
10
|
+
|
|
11
|
+
recipients object.notify_email
|
|
12
|
+
subject I18n.t('expired_mailer.notification.subject', :expirable => object.expirable)
|
|
13
|
+
from Settings.mail.headers.from
|
|
14
|
+
headers 'reply-to' => Settings.mail.headers.devnull
|
|
15
|
+
body :object => object
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
end
|
data/rails/init.rb
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Rake file for acts_as_expired
|
|
2
|
+
#
|
|
3
|
+
# To send email alerts to expiring objects, run:
|
|
4
|
+
# rake expires:notify
|
|
5
|
+
#
|
|
6
|
+
|
|
7
|
+
namespace :expires do
|
|
8
|
+
|
|
9
|
+
desc 'Notify about objects that are about to expire (by email)'
|
|
10
|
+
task 'notify' => :environment do
|
|
11
|
+
Expire.notifiable.each do |object|
|
|
12
|
+
|
|
13
|
+
puts %{Sending notification to #{object.notify_email} for object "#{object.expirable}"}
|
|
14
|
+
|
|
15
|
+
begin
|
|
16
|
+
mail = ExpiredMailer.deliver_notification(object)
|
|
17
|
+
object.notified_at = Time.now
|
|
18
|
+
object.save
|
|
19
|
+
rescue => error
|
|
20
|
+
puts error
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: gudleik-acts_as_expired
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.2
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Gudleik Rasch
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
|
|
12
|
+
date: 2009-05-07 00:00:00 -07:00
|
|
13
|
+
default_executable:
|
|
14
|
+
dependencies: []
|
|
15
|
+
|
|
16
|
+
description: Rails plugin that allows expiring of ActiveRecord models
|
|
17
|
+
email: gudleik@rastamatra.org
|
|
18
|
+
executables: []
|
|
19
|
+
|
|
20
|
+
extensions: []
|
|
21
|
+
|
|
22
|
+
extra_rdoc_files: []
|
|
23
|
+
|
|
24
|
+
files:
|
|
25
|
+
- README.rdoc
|
|
26
|
+
- MIT-LICENSE
|
|
27
|
+
- init.rb
|
|
28
|
+
- rails/init.rb
|
|
29
|
+
- tasks/acts_as_expired_tasks.rake
|
|
30
|
+
- lib/acts_as_expired.rb
|
|
31
|
+
- lib/expire.rb
|
|
32
|
+
- lib/expired_mailer.rb
|
|
33
|
+
- generators/acts_as_expired_mailer/acts_as_expired_mailer_generator.rb
|
|
34
|
+
- generators/acts_as_expired_mailer/templates/notification.text.html.erb
|
|
35
|
+
- generators/acts_as_expired_mailer/templates/notification.text.plain.erb
|
|
36
|
+
- generators/acts_as_expired_on_migration/acts_as_expired_on_migration_generator.rb
|
|
37
|
+
- generators/acts_as_expired_on_migration/templates/migration.rb
|
|
38
|
+
has_rdoc: false
|
|
39
|
+
homepage: http://github.com/gudleik/acts_as_expired/tree
|
|
40
|
+
post_install_message:
|
|
41
|
+
rdoc_options: []
|
|
42
|
+
|
|
43
|
+
require_paths:
|
|
44
|
+
- lib
|
|
45
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
46
|
+
requirements:
|
|
47
|
+
- - ">="
|
|
48
|
+
- !ruby/object:Gem::Version
|
|
49
|
+
version: "0"
|
|
50
|
+
version:
|
|
51
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
52
|
+
requirements:
|
|
53
|
+
- - ">="
|
|
54
|
+
- !ruby/object:Gem::Version
|
|
55
|
+
version: "0"
|
|
56
|
+
version:
|
|
57
|
+
requirements: []
|
|
58
|
+
|
|
59
|
+
rubyforge_project:
|
|
60
|
+
rubygems_version: 1.2.0
|
|
61
|
+
signing_key:
|
|
62
|
+
specification_version: 2
|
|
63
|
+
summary: Rails plugin that allows expiring of ActiveRecord models
|
|
64
|
+
test_files: []
|
|
65
|
+
|