gudleik-acts_as_expired 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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
+