acts_as_expirable 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b899168c5eb93007211f94db8bb907b43eb629c9
4
- data.tar.gz: a0975e616f04ec8409f158d007ecbf958ac86ead
3
+ metadata.gz: 45f75fd75552f99c578b3da1af5ca12835d028b2
4
+ data.tar.gz: ede4bdd74972e87c869d509d71d816bbe8bcf4b4
5
5
  SHA512:
6
- metadata.gz: 751c14d25cfd54b0484ef5782412ebfadf8981918fc7070da93a7894e214cf3826b07ef8cf022d24f409e813e1d26e46cc2fbef94263f3515368f368555591fb
7
- data.tar.gz: 9d45a7a348d6a0c3dec36704cd2bbf8864a0cc31b9ae682c537254427dd5150b60d625c09c9935b6d4529a46abe07762f27babd81c13568ef43b796864c71956
6
+ metadata.gz: 9da3266d44de4c31fc8a607ab4af0119cf1b77ea6616df8aa7a3a57d2d8086a3074621034dadb662d2c0e3d97ca90b2acd74e5632b349d0a3cc7e07393c0bdbb
7
+ data.tar.gz: 12f5cea4de035042e16a6dad5aa1c6c16c05a8d287761520eec94f6122452d7aaef22387c9140f54e42a5fec71451050380a8f8287c333e6890406808422a4b0
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) {{year}} {{fullname}}
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,26 @@
1
+ Acts As Expirable
2
+ =================
3
+
4
+ `acts_as_expirable` is an ActiveRecord mixin that enables simple handling of expiring records. It gives you `expired` and `unexpired` scopes as well as global handling of all expirable classes.
5
+
6
+ ## Usage
7
+
8
+ ```
9
+ class SomeModel < ActiveRecord::Base
10
+ acts_as_expirable
11
+ end
12
+ ```
13
+
14
+ ## Configuration Options
15
+
16
+ To add configuration options, simply add a Hash of options to the `acts_as_expirable` call:
17
+
18
+ ```
19
+ ...
20
+ acts_as_expirable column: 'some_timestamp', default: ->(r) { Time.now + 1.day }
21
+ ```
22
+
23
+ ### Options
24
+
25
+ * `column` - the name of the ORM's field that you want to treat as the expiry time.
26
+ * `default` - a default value to set on create if the expiry field is not yet set. Can be a value or a proc, yielding the record instance.
data/Rakefile CHANGED
@@ -7,6 +7,7 @@ task :default => :test
7
7
  desc 'Test the acts_as_expirable plugin.'
8
8
  Rake::TestTask.new(:test) do |t|
9
9
  t.libs << 'lib'
10
+ t.libs << 'test'
10
11
  t.pattern = 'test/**/*_test.rb'
11
12
  t.verbose = true
12
13
  end
@@ -11,7 +11,9 @@ Gem::Specification.new do |gem|
11
11
  gem.homepage = 'http://github.com/chingor13/acts_as_expirable'
12
12
  gem.license = 'MIT'
13
13
 
14
- gem.add_runtime_dependency 'rails', '>= 3.0'
14
+ gem.add_runtime_dependency 'activerecord', '>= 3.0'
15
+ gem.add_runtime_dependency 'activesupport', '>= 3.0'
16
+ gem.add_development_dependency 'rake'
15
17
  gem.add_development_dependency 'sqlite3'
16
18
  gem.add_development_dependency 'mysql2', '~> 0.3.7'
17
19
 
@@ -1,72 +1,41 @@
1
1
  module ActsAsExpirable
2
- def self.included(base)
3
- base.extend(ClassMethods)
4
- end
2
+ extend ActiveSupport::Concern
5
3
 
6
- def self.cleanup!
7
- expirable_classes.each do |klass|
8
- klass.unscoped.destroy_expired
4
+ module ClassMethods
5
+ def acts_as_expirable(options = {})
6
+ include Expirable
7
+ self.acts_as_expirable_configuration = options.reverse_merge({
8
+ column: "expires_at"
9
+ })
9
10
  end
10
11
  end
11
12
 
12
- def self.expirable_classes
13
- @expirable_classes ||= []
14
- end
15
-
16
- def self.register_expirable(klass)
17
- @expirable_classes ||= []
18
- @expirable_classes << klass
19
- end
13
+ module Expirable
14
+ extend ActiveSupport::Concern
20
15
 
21
- module ClassMethods
22
- def acts_as_expirable(options = {})
16
+ included do
23
17
  ActsAsExpirable.register_expirable(self)
18
+ class_attribute :acts_as_expirable_configuration
19
+ scope :expired, -> { where(["#{acts_as_expirable_configuration[:column]} <= ?", Time.now]) }
20
+ scope :unexpired, -> { where(["#{acts_as_expirable_configuration[:column]} IS NULL OR #{acts_as_expirable_configuration[:column]} > ?", Time.now]) }
21
+ delegate :expiry_column, to: :class
22
+ before_validation :set_expiry_default, on: :create
23
+ end
24
24
 
25
- configuration = { :column => "expires_at" }
26
- configuration.update(options) if options.is_a?(Hash)
27
-
28
- class_eval %{
29
- include ActsAsExpirable::InstanceMethods
30
-
31
- scope :expired, where('#{configuration[:column]} <= UTC_TIMESTAMP()')
32
- scope :unexpired, where('#{configuration[:column]} IS NULL OR #{configuration[:column]} > UTC_TIMESTAMP()')
33
-
34
- class << self
35
- def expiry_column
36
- '#{configuration[:column]}'
37
- end
38
-
39
- def destroy_expired
40
- expired.destroy_all
41
- end
42
-
43
- def delete_expired
44
- expired.delete_all
45
- end
46
-
47
- def default_scope
48
- unexpired
49
- end
50
- end
51
- }
52
-
53
- case configuration[:default]
54
- when Proc
55
- before_validation configuration[:default], :on => :create do
56
- write_attribute(configuration[:column], configuration[:default].call(self)) if read_attribute(configuration[:column]).nil?
57
- true
58
- end
59
- when NilClass
60
- else
61
- before_validation :on => :create do
62
- write_attribute(configuration[:column], configuration[:default]) if read_attribute(configuration[:column]).nil?
63
- true
64
- end
25
+ module ClassMethods
26
+ def expiry_column
27
+ acts_as_expirable_configuration[:column]
28
+ end
29
+
30
+ def destroy_expired
31
+ expired.destroy_all
32
+ end
33
+
34
+ def delete_expired
35
+ expired.delete_all
65
36
  end
66
37
  end
67
- end
68
38
 
69
- module InstanceMethods
70
39
  def expire
71
40
  write_attribute(self.class.expiry_column, Time.now)
72
41
  end
@@ -80,5 +49,36 @@ module ActsAsExpirable
80
49
  return false if expire_time.nil?
81
50
  expire_time <= Time.now
82
51
  end
52
+
53
+ protected
54
+
55
+ def set_expiry_default
56
+ default = acts_as_expirable_configuration[:default]
57
+ return true if default.nil?
58
+
59
+ # set the value if the current value is not set
60
+ if read_attribute(acts_as_expirable_configuration[:column]).nil?
61
+ write_attribute(acts_as_expirable_configuration[:column],
62
+ default.respond_to?(:call) ? default.call(self) : default
63
+ )
64
+ end
65
+ true
66
+ end
67
+ end
68
+
69
+ def self.cleanup!
70
+ expirable_classes.each do |klass|
71
+ klass.unscoped.destroy_expired
72
+ end
83
73
  end
74
+
75
+ def self.expirable_classes
76
+ @expirable_classes ||= []
77
+ end
78
+
79
+ def self.register_expirable(klass)
80
+ @expirable_classes ||= []
81
+ @expirable_classes << klass
82
+ end
83
+
84
84
  end
@@ -1,3 +1,6 @@
1
1
  module ActsAsExpirable
2
- VERSION = "0.0.3"
2
+ MAJOR = 0
3
+ MINOR = 1
4
+ BUILD = 0
5
+ VERSION = [MAJOR, MINOR, BUILD].join(".")
3
6
  end
@@ -1,2 +1,4 @@
1
+ require 'active_record'
2
+ require 'active_support/concern'
1
3
  require 'acts_as_expirable/expirable'
2
4
  ActiveRecord::Base.send(:include, ActsAsExpirable)
@@ -0,0 +1,51 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.require(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+
12
+ ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
13
+ ActiveRecord::Schema.verbose = false
14
+
15
+ def setup_db
16
+ ActiveRecord::Schema.define(version: 1) do
17
+ create_table :names do |t|
18
+ t.column :name, :string
19
+ t.column :expires_at, :datetime
20
+ end
21
+
22
+ create_table :tokens do |t|
23
+ t.column :token, :string
24
+ t.column :good_until, :datetime
25
+ end
26
+ end
27
+ end
28
+
29
+ def teardown_db
30
+ ActiveRecord::Base.connection.tables.each do |table|
31
+ ActiveRecord::Base.connection.drop_table(table)
32
+ end
33
+ end
34
+
35
+ class Name < ActiveRecord::Base
36
+ def self.table_name
37
+ "names"
38
+ end
39
+ end
40
+
41
+ class ExpirableName < Name
42
+ acts_as_expirable
43
+ end
44
+
45
+ class ExpirableNameDefault < Name
46
+ acts_as_expirable default: "2014-02-03 09:00:45 UTC"
47
+ end
48
+
49
+ class Token < ActiveRecord::Base
50
+ acts_as_expirable column: :good_until, default: ->(r) { Time.now + 1.day }
51
+ end
@@ -0,0 +1,87 @@
1
+ require 'test_helper'
2
+
3
+ class ExpirableTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ super
7
+ setup_db
8
+ Name.create(name: "expired record", expires_at: Time.now - 1.hour)
9
+ Name.create(name: "future expired record", expires_at: Time.now + 2.hours)
10
+ Name.create(name: "doesn't expire", expires_at: nil)
11
+
12
+ Token.create(token: "expired", good_until: Time.now - 2.days)
13
+ end
14
+
15
+ def teardown
16
+ teardown_db
17
+ super
18
+ end
19
+
20
+ def test_class_registration
21
+ assert_equal([ExpirableName, ExpirableNameDefault, Token], ActsAsExpirable.expirable_classes)
22
+ end
23
+
24
+ def test_default_value
25
+ assert name = ExpirableNameDefault.create(name: "foo")
26
+ assert name.expires_at, "expires_at should be set"
27
+ assert_equal Time.parse("2014-02-03 09:00:45 UTC"), name.expires_at
28
+ end
29
+
30
+ def test_default_value_lambda
31
+ assert token = Token.create(token: "foo")
32
+ assert token.good_until
33
+ assert (Time.now.to_i + 1.day) - token.good_until.to_i <= 1, "should be set to nowish"
34
+ end
35
+
36
+ def test_expired
37
+ assert_equal(1, ExpirableName.expired.count)
38
+ end
39
+
40
+ def test_unexpired
41
+ assert_equal(2, ExpirableName.unexpired.count)
42
+ end
43
+
44
+ def test_destroy_all
45
+ count = ExpirableName.count
46
+ ExpirableName.destroy_expired
47
+ assert_equal count - 1, ExpirableName.count
48
+ end
49
+
50
+ def test_destroy_all_special_column
51
+ count = Token.count
52
+ Token.destroy_expired
53
+ assert_equal count - 1, Token.count
54
+ end
55
+
56
+ def test_cleanup
57
+ name_count = ExpirableName.count
58
+ token_count = Token.count
59
+
60
+ ActsAsExpirable.cleanup!
61
+
62
+ assert_equal name_count - 1, ExpirableName.count
63
+ assert_equal token_count - 1, Token.count
64
+ end
65
+
66
+ def test_expired
67
+ name = ExpirableName.find_by_name("expired record")
68
+ assert name.expired?
69
+ end
70
+
71
+ def test_expiring
72
+ name = ExpirableName.find_by_name("doesn't expire")
73
+ assert !name.expired?
74
+
75
+ # doesn't actually write
76
+ name.expire
77
+ assert name.expired?
78
+
79
+ name.reload
80
+ assert !name.expired?
81
+ name.expire!
82
+
83
+ name.reload
84
+ assert name.expired?
85
+ end
86
+
87
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acts_as_expirable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeff Ching
@@ -11,7 +11,7 @@ cert_chain: []
11
11
  date: 2012-10-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: rails
14
+ name: activerecord
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - '>='
@@ -24,6 +24,34 @@ dependencies:
24
24
  - - '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: '3.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '3.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '3.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
27
55
  - !ruby/object:Gem::Dependency
28
56
  name: sqlite3
29
57
  requirement: !ruby/object:Gem::Requirement
@@ -61,11 +89,15 @@ extra_rdoc_files: []
61
89
  files:
62
90
  - .gitignore
63
91
  - Gemfile
92
+ - LICENSE
93
+ - README.md
64
94
  - Rakefile
65
95
  - acts_as_expirable.gemspec
66
96
  - lib/acts_as_expirable.rb
67
97
  - lib/acts_as_expirable/expirable.rb
68
98
  - lib/acts_as_expirable/version.rb
99
+ - test/test_helper.rb
100
+ - test/unit/expirable_test.rb
69
101
  homepage: http://github.com/chingor13/acts_as_expirable
70
102
  licenses:
71
103
  - MIT
@@ -90,4 +122,6 @@ rubygems_version: 2.0.3
90
122
  signing_key:
91
123
  specification_version: 4
92
124
  summary: Basic expiry for Rails.
93
- test_files: []
125
+ test_files:
126
+ - test/test_helper.rb
127
+ - test/unit/expirable_test.rb