transient 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,9 @@
1
+ = 1.0.1 2009-12-29
2
+
3
+ * Added call back to populate effective_at with DateTime.now if it is not explicitly set to something else.
4
+ * Added presence validation to effective_at.
5
+
6
+
1
7
  = 1.0.0 2009-12-26
2
8
 
3
9
  * Initial release Ported from another project.
@@ -13,6 +13,9 @@ Provides an API for making any ActiveRecord object transient.
13
13
  * Convenience methods for transient objects, ie. current?, expired?, expire!, etc.
14
14
  * Callbacks for expiring current 'active' record prior to creating new one where certain configured fields
15
15
  match. See the Transient::ActiveRecordExtensions::InstanceMethods docs for more information.
16
+ * A callback to populate the expiring at field of a new record with DateTime.now unless a value was explicitly
17
+ specified for the effective at field.
18
+ * Automatically adds a presence validation for effective_at to the model.
16
19
 
17
20
 
18
21
  == REQUIREMENTS
@@ -31,7 +34,7 @@ Provides an API for making any ActiveRecord object transient.
31
34
 
32
35
  Add to environment file:
33
36
 
34
- config.gem "transient", :version => '1.0.0', :source => 'http://gemcutter.org'
37
+ config.gem "transient", :version => '1.0.1', :source => 'http://gemcutter.org'
35
38
 
36
39
  Run:
37
40
 
@@ -40,6 +43,13 @@ Run:
40
43
 
41
44
  == USAGE
42
45
 
46
+ Add the transient fields to your model:
47
+
48
+ def self.up
49
+ add_column :users, :effective_at, :datetime, :null => false
50
+ add_column :users, :expiring_at, :datetime
51
+ end
52
+
43
53
  Call the macro from your ActiveRecord descendant class:
44
54
 
45
55
  class User < ActiveRecord::Base
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.0
1
+ 1.0.1
@@ -4,7 +4,7 @@ require 'date_time_extensions'
4
4
  require 'transient/active_record_extensions'
5
5
 
6
6
  module Transient
7
- VERSION = '1.0.0'
7
+ VERSION = '1.0.1'
8
8
  end
9
9
 
10
10
  ActiveRecord::Base.send( :include, Transient::ActiveRecordExtensions ) if defined?( ActiveRecord::Base )
@@ -21,16 +21,21 @@ module Transient
21
21
  end
22
22
 
23
23
  module InstanceMethods
24
- def self.included( includee ) #:nodoc:
25
- #includee.validates_presence_of :effective_at
26
- #includee.validates_presence_of :expiring_at
24
+ def self.included( base ) #:nodoc:
25
+ base.validates_presence_of :effective_at
26
+ #base.validates_presence_of :expiring_at
27
27
 
28
- #includee.default(:effective_at) { DateTime.beginning_of }
29
- #includee.default(:expiring_at) { DateTime.end_of }
30
-
31
- includee.named_scope :current, lambda { { :conditions => ["effective_at <= ? AND (expiring_at IS NULL OR expiring_at > ?)",
28
+ base.named_scope :effective, lambda { { :conditions => ["effective_at <= ? AND (expiring_at IS NULL OR expiring_at > ?)",
32
29
  DateTime.now.utc, DateTime.now.utc] } }
33
30
 
31
+ base.before_validation_on_create :check_and_set_effective_at
32
+
33
+ protected
34
+
35
+ def check_and_set_effective_at
36
+ self[:effective_at] = DateTime.now if self[:effective_at].nil?
37
+ end
38
+
34
39
  public
35
40
 
36
41
  # Validates this record's effective dates occur in correct sequence (ie. effective_at is before
@@ -46,18 +51,11 @@ module Transient
46
51
  super
47
52
  end
48
53
 
49
- # The date this record becomes effective. Returns DateTime.beginning_of for records that have a
50
- # nil value in the database.
51
- #
52
- def effective_at
53
- return self[:effective_at].blank? ? DateTime.beginning_of : self[:effective_at]
54
- end
55
-
56
54
  # The date this record expires. Returns DateTime.end_of for records that have a
57
55
  # nil value in the database.
58
56
  #
59
57
  def expiring_at
60
- return self[:expiring_at].blank? ? DateTime.end_of : self[:expiring_at]
58
+ return self[:expiring_at].nil? ? DateTime.end_of : self[:expiring_at]
61
59
  end
62
60
 
63
61
  # The range this record is effective wihtin.
@@ -122,8 +120,8 @@ module Transient
122
120
  end
123
121
 
124
122
  module SingleActive
125
- def self.included( includee ) #:nodoc:
126
- includee.before_create :expire_current_active
123
+ def self.included( base ) #:nodoc:
124
+ base.before_create :expire_current_active
127
125
 
128
126
  private
129
127
 
@@ -137,7 +135,7 @@ module Transient
137
135
 
138
136
  conditions = {}
139
137
  self.transient_options[:single_active].each { |attr| conditions.merge!( attr.to_sym => attributes[attr] ) }
140
- old = self.class.current.find( :first, :conditions => conditions )
138
+ old = self.class.effective.first( :conditions => conditions )
141
139
  old.expire! unless old.nil?
142
140
  end
143
141
  end
@@ -54,10 +54,23 @@ shared_examples_for "Any transient" do
54
54
  @instance.should_not be_past
55
55
  @instance.should be_future
56
56
  end
57
+
58
+ it "should respond to :effective" do
59
+ @klass.respond_to?( :effective ).should be_true
60
+ end
57
61
 
58
62
  it "should invoke callbacks around expire!" do
59
63
  @instance.should_receive(:before_expire!)
60
64
  @instance.should_receive(:after_expire!)
61
65
  @instance.expire!
62
66
  end
67
+
68
+ it "should set effective_at to now if it was not explicitly set to something else" do
69
+ @instance_no_dates.effective_at.should_not be_nil
70
+ end
71
+
72
+ it "should not allow records without an effective_at date to be saved" do
73
+ @instance_no_dates.effective_at = nil
74
+ @instance_no_dates.save.should be_false
75
+ end
63
76
  end
@@ -12,8 +12,9 @@ describe "Transient" do
12
12
  describe "having models descending from ActiveRecord" do
13
13
  describe "that are not single active" do
14
14
  before(:each) do
15
- @instance = User.new( :name => 'John Smith', :effective_at => (DateTime.now - 1.days), :expiring_at => DateTime.end_of )
16
- @instance.save!
15
+ @klass = User
16
+ @instance = @klass.create( :name => 'John Smith', :effective_at => (DateTime.now - 1.days), :expiring_at => DateTime.end_of )
17
+ @instance_no_dates = @klass.create( :name => 'Jack Smith' )
17
18
  end
18
19
 
19
20
  it_should_behave_like "Any transient"
@@ -30,34 +31,32 @@ describe "Transient" do
30
31
  describe "that are single active" do
31
32
  before(:each) do
32
33
  @klass = ContactNumber
33
- @instance = @klass.new( :number => '012345678901', :location => 'home', :effective_at => (DateTime.now - 1.days) )
34
- @instance.save!
34
+ @instance = @klass.create( :number => '012345678901', :location => 'home', :effective_at => (DateTime.now - 1.days) )
35
+ @instance_no_dates = @klass.create( :number => '012345678901', :location => 'home' )
35
36
  end
36
37
 
37
38
  it_should_behave_like "Any transient"
38
39
  it_should_behave_like "Any transient that is single active"
39
40
 
40
41
  it "should expire the current active before saving a new one" do
41
- @new_contact = ContactNumber.new( :number => '019876543210', :location => 'home', :effective_at => DateTime.now )
42
- @new_contact.save!
42
+ @new_contact = ContactNumber.create( :number => '019876543210', :location => 'home', :effective_at => DateTime.now )
43
43
  @instance.reload
44
44
  @instance.expired?.should be_true
45
45
  end
46
46
  end
47
47
 
48
48
  describe "that are single active with check exists" do
49
- before(:each) do
49
+ before :each do
50
50
  @klass = Address
51
- @instance = @klass.new( :street => '26 street', :location => 'home', :effective_at => (DateTime.now - 1.days) )
52
- @instance.save!
51
+ @instance = @klass.create( :street => '26 street', :location => 'home', :effective_at => (DateTime.now - 1.days) )
52
+ @instance_no_dates = @klass.create( :street => '26 street', :location => 'home' )
53
53
  end
54
54
 
55
55
  it_should_behave_like "Any transient"
56
56
  it_should_behave_like "Any transient that is single active"
57
57
 
58
58
  it "should expire the current active before saving a new one" do
59
- @new_address = Address.new( :street => '27 street', :location => 'home', :effective_at => DateTime.now )
60
- @new_address.save!
59
+ @new_address = Address.create( :street => '27 street', :location => 'home', :effective_at => DateTime.now )
61
60
  @instance.reload
62
61
  @instance.expired?.should be_true
63
62
  end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{transient}
8
- s.version = "1.0.0"
8
+ s.version = "1.0.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["C. Jason Harrelson (midas)"]
12
- s.date = %q{2009-12-27}
12
+ s.date = %q{2009-12-29}
13
13
  s.description = %q{Provides an API for making any ActiveRecord object transient. In addition, provides functionality for models where only a single instance of the model can be current at one time.}
14
14
  s.email = %q{jason@lookforwardenterprises.com}
15
15
  s.extra_rdoc_files = [
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: transient
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - C. Jason Harrelson (midas)
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-12-27 00:00:00 -06:00
12
+ date: 2009-12-29 00:00:00 -06:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency