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 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,7 @@
1
+ class ActsAsExpiredOnMigrationGenerator < Rails::Generator::Base
2
+ def manifest
3
+ record do |m|
4
+ m.migration_template 'migration.rb', 'db/migrate', :migration_file_name => "acts_as_expired_on_migration"
5
+ end
6
+ end
7
+ end
@@ -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,5 @@
1
+ require 'acts_as_expired'
2
+
3
+ ActiveRecord::Base.send(:include, ActsAsExpired)
4
+
5
+ RAILS_DEFAULT_LOGGER.info "** acts_as_expired: initialized properly."
@@ -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
+