limited 0.0.1 → 0.1.0
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.
- checksums.yaml +4 -4
- data/README.md +9 -4
- data/lib/limited/action.rb +35 -3
- data/lib/limited/config.rb +2 -2
- data/lib/limited/interval.rb +60 -0
- data/lib/limited/version.rb +1 -1
- data/lib/limited.rb +1 -0
- data/spec/limited_action_spec.rb +25 -0
- data/spec/limited_config_spec.rb +23 -1
- data/spec/limited_interval_spec.rb +77 -0
- data/spec/spec_helper.rb +12 -0
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e0c628b05e6dd3db011e8ae8aa7299da4ab0664a
|
4
|
+
data.tar.gz: c5185402f1a9f258c641276f36e640994b17c10e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8a5dce139e3e678c083855773ac616ee638124fdce8d07dfa3c00ba1f5c2b634adfaefa43e36ca99f646f83d24addea085a1095a08904c6449cc2eeca6dbc2b4
|
7
|
+
data.tar.gz: bdcee5091e679f9cdd3f12bb05f9bd3df953d8f929b0921405091b8538e35921cf897eb720473a36492d2e1fe1321e1c0e32c67016e9fcf63a7b692078339851
|
data/README.md
CHANGED
@@ -23,9 +23,14 @@ Or install it yourself as:
|
|
23
23
|
You need to define your actions somewhere in your application like this:
|
24
24
|
|
25
25
|
Limited.configure do
|
26
|
+
# this action should only be 1337 times at most
|
26
27
|
action :name_of_action, 1337
|
27
|
-
|
28
|
-
|
28
|
+
|
29
|
+
# only 1 login all 10 seconds
|
30
|
+
action :login, 1, 10
|
31
|
+
|
32
|
+
# at maximum 123 contact emails a day
|
33
|
+
action :sending_contact_email, 123, :day
|
29
34
|
end
|
30
35
|
|
31
36
|
The second parameter given to action defines how many times the action
|
@@ -42,11 +47,11 @@ Here are a few commonly used methods which every Action provides:
|
|
42
47
|
|
43
48
|
<table>
|
44
49
|
<tr>
|
45
|
-
<td
|
50
|
+
<td>executed</td>
|
46
51
|
<td>Call this method everytime the specified action is being executed</td>
|
47
52
|
</tr>
|
48
53
|
<tr>
|
49
|
-
<td
|
54
|
+
<td>limit_reached</td>
|
50
55
|
<td>Wheter the limit has been reached or not</td>
|
51
56
|
</tr>
|
52
57
|
</table>
|
data/lib/limited/action.rb
CHANGED
@@ -8,8 +8,6 @@ module Limited
|
|
8
8
|
attr_reader :name
|
9
9
|
# the amount of times the action can be executed
|
10
10
|
attr_reader :limit
|
11
|
-
# the amount of times the action already has been executed
|
12
|
-
attr_reader :num_executed
|
13
11
|
|
14
12
|
##
|
15
13
|
# :call-seq:
|
@@ -20,7 +18,7 @@ module Limited
|
|
20
18
|
# === Example
|
21
19
|
#
|
22
20
|
# Limited::Action.new :do_stuff, 1000
|
23
|
-
def initialize(name, limit)
|
21
|
+
def initialize(name, limit, interval = nil)
|
24
22
|
raise ArgumentError.new("Limited::Action::name needs to be a Symbol") unless name.is_a?(Symbol)
|
25
23
|
raise ArgumentError.new("Limited::Action::limit needs to be an Integer") unless limit.is_a?(Integer)
|
26
24
|
raise ArgumentError.new("Limited::Action::limit needs to be positive") if limit < 0
|
@@ -28,12 +26,30 @@ module Limited
|
|
28
26
|
@name = name
|
29
27
|
@limit = limit
|
30
28
|
@num_executed = 0
|
29
|
+
@interval = Interval.new(interval.nil? ? :endless : interval)
|
30
|
+
check_new_interval
|
31
|
+
end
|
32
|
+
|
33
|
+
##
|
34
|
+
# returns the interval for which the limit counts
|
35
|
+
def interval
|
36
|
+
check_new_interval
|
37
|
+
@interval
|
38
|
+
end
|
39
|
+
|
40
|
+
##
|
41
|
+
# returns the amount of times the action already
|
42
|
+
# has been executed
|
43
|
+
def num_executed
|
44
|
+
check_new_interval
|
45
|
+
@num_executed
|
31
46
|
end
|
32
47
|
|
33
48
|
##
|
34
49
|
# returns how many times the action can be executed
|
35
50
|
# until the given limit is reached
|
36
51
|
def num_left
|
52
|
+
check_new_interval
|
37
53
|
@limit - @num_executed
|
38
54
|
end
|
39
55
|
|
@@ -42,6 +58,7 @@ module Limited
|
|
42
58
|
# the action gets executed
|
43
59
|
# so the internal counter is always up-to-date
|
44
60
|
def executed
|
61
|
+
check_new_interval
|
45
62
|
@num_executed += 1
|
46
63
|
end
|
47
64
|
|
@@ -49,7 +66,22 @@ module Limited
|
|
49
66
|
# wheter the limit of executions
|
50
67
|
# has been exceeded
|
51
68
|
def limit_reached
|
69
|
+
check_new_interval
|
52
70
|
@limit <= @num_executed
|
53
71
|
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
##
|
76
|
+
# checks if the interval
|
77
|
+
# passes and resets the number
|
78
|
+
# of executions so
|
79
|
+
# the limit can be reached again
|
80
|
+
def check_new_interval
|
81
|
+
if @interval.passed?
|
82
|
+
@interval.reset_start
|
83
|
+
@num_executed = 0
|
84
|
+
end
|
85
|
+
end
|
54
86
|
end
|
55
87
|
end
|
data/lib/limited/config.rb
CHANGED
@@ -11,8 +11,8 @@ module Limited
|
|
11
11
|
#
|
12
12
|
# raises an ArgumentError if the same name
|
13
13
|
# for an action is not unique
|
14
|
-
def self.action(name, limit)
|
15
|
-
action = Limited::Action.new(name, limit)
|
14
|
+
def self.action(name, limit, interval_length = nil)
|
15
|
+
action = Limited::Action.new(name, limit, interval_length)
|
16
16
|
raise ArgumentError.new("action with name :#{name.to_s} has already been added") if Limited.actions.has_key?(name)
|
17
17
|
Limited.actions[name] = action
|
18
18
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Limited
|
2
|
+
##
|
3
|
+
# This represents a timespan within a limit counts
|
4
|
+
# after this timespan ends the limit
|
5
|
+
# should be reset
|
6
|
+
class Interval
|
7
|
+
# the length of the interval in seconds
|
8
|
+
attr_reader :length
|
9
|
+
# a timestamp when the last interval started
|
10
|
+
attr_reader :last_start
|
11
|
+
|
12
|
+
# common lengths of the intervals
|
13
|
+
# and shortcuts for them
|
14
|
+
@@interval_lengths = {
|
15
|
+
second: 1,
|
16
|
+
minute: 60,
|
17
|
+
hour: 60 * 60,
|
18
|
+
day: 60 * 60 * 24,
|
19
|
+
endless: 1.0/0.0
|
20
|
+
}
|
21
|
+
|
22
|
+
##
|
23
|
+
# initializes an interval
|
24
|
+
# by either supplying the length of the
|
25
|
+
# interval in seconds as an Numeric
|
26
|
+
# or by supplying one of the symbols
|
27
|
+
# :second, :minute, :hour or :day
|
28
|
+
def initialize(length)
|
29
|
+
is_sym = length.is_a?(Symbol) and @@interval_lengths.has_key?(length)
|
30
|
+
raise ArgumentError.new("Limited::Interval.length needs to be a Numeric or one of the symbols :second, :minute, :hour or :day") unless length.is_a?(Numeric) or is_sym
|
31
|
+
@length = is_sym ? @@interval_lengths[length] : length
|
32
|
+
reset_start
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# start a new interval and
|
37
|
+
# reset the last_start variable
|
38
|
+
def reset_start
|
39
|
+
now = Time.now
|
40
|
+
@last_start = (now.to_f / @length).to_i * @length
|
41
|
+
@last_start = 0 if @last_start.is_a?(Float) and @last_start.nan?
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# calculate the amount of seconds remaining
|
46
|
+
# in seconds for the interval to end
|
47
|
+
#
|
48
|
+
# when the interval ended 0 is returned so
|
49
|
+
# this method never returns negative numbers
|
50
|
+
def time_left
|
51
|
+
[0, (last_start.to_f + length - Time.now.to_f)].max
|
52
|
+
end
|
53
|
+
|
54
|
+
##
|
55
|
+
# wheter the interval has finished
|
56
|
+
def passed?
|
57
|
+
time_left == 0
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/limited/version.rb
CHANGED
data/lib/limited.rb
CHANGED
data/spec/limited_action_spec.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
1
3
|
require 'limited'
|
2
4
|
require 'limited/action'
|
3
5
|
|
@@ -7,6 +9,7 @@ describe Limited::Action do
|
|
7
9
|
|
8
10
|
it { should respond_to(:name) }
|
9
11
|
it { should respond_to(:limit) }
|
12
|
+
it { should respond_to(:interval) }
|
10
13
|
it { should respond_to(:num_executed) }
|
11
14
|
it { should respond_to(:num_left) }
|
12
15
|
|
@@ -72,4 +75,26 @@ describe Limited::Action do
|
|
72
75
|
@action.limit_reached.should be_true
|
73
76
|
end
|
74
77
|
end
|
78
|
+
|
79
|
+
describe "with an ending interval" do
|
80
|
+
before { @interval_action = Limited::Action.new :ending_interval, 5, :minute }
|
81
|
+
it "should be able to reach the limit before the interval ends" do
|
82
|
+
@interval_action.limit_reached.should be_false
|
83
|
+
@interval_action.executed
|
84
|
+
@interval_action.limit_reached.should be_false
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "after the limit has been reached" do
|
88
|
+
before { 5.times { @interval_action.executed } }
|
89
|
+
it { @interval_action.limit_reached.should be_true }
|
90
|
+
|
91
|
+
describe "after the interval passed" do
|
92
|
+
before { Time.testing_offset += @interval_action.interval.time_left }
|
93
|
+
it "should reset num_executed" do
|
94
|
+
@interval_action.num_executed.should be 0
|
95
|
+
@interval_action.limit_reached.should be_false
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
75
100
|
end
|
data/spec/limited_config_spec.rb
CHANGED
@@ -7,10 +7,32 @@ describe Limited::Config do
|
|
7
7
|
|
8
8
|
it "should add an Limited::Action to Limited::actions when calling Limited::Config::action" do
|
9
9
|
expect do
|
10
|
-
Limited::Config.action :new, 123
|
10
|
+
Limited::Config.action :new, 123, :day
|
11
11
|
end.to change(Limited, :actions)
|
12
12
|
end
|
13
13
|
|
14
|
+
describe "the Action objects in the Limited::actions array" do
|
15
|
+
before(:all) do
|
16
|
+
Limited::Config.action :value_check, 123, :day
|
17
|
+
Limited::Config.action :value_check1, 3
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should have the correct name" do
|
21
|
+
Limited.actions[:value_check].name.should eq :value_check
|
22
|
+
Limited.actions[:value_check1].name.should eq :value_check1
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should have the correct limit" do
|
26
|
+
Limited.actions[:value_check].limit.should eq 123
|
27
|
+
Limited.actions[:value_check1].limit.should eq 3
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should have the correct interval" do
|
31
|
+
Limited.actions[:value_check].interval.length.should eq 24 * 60 * 60
|
32
|
+
Limited.actions[:value_check1].interval.length.should eq 1.0/0.0
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
14
36
|
it "should not be possible to add an action with the same name twice" do
|
15
37
|
expect do
|
16
38
|
Limited::Config.action :same_name, 123
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'limited'
|
3
|
+
|
4
|
+
describe Limited::Interval do
|
5
|
+
let(:infinity) { 1.0/0.0 }
|
6
|
+
let(:endless) { Limited::Interval.new(:endless) }
|
7
|
+
|
8
|
+
subject { Limited::Interval.new 234 }
|
9
|
+
|
10
|
+
it { should respond_to(:length) }
|
11
|
+
it { should respond_to(:last_start) }
|
12
|
+
it { should respond_to(:time_left) }
|
13
|
+
it { should respond_to(:reset_start) }
|
14
|
+
it { should respond_to(:passed?) }
|
15
|
+
|
16
|
+
|
17
|
+
describe "length" do
|
18
|
+
it "should be set by the constructor" do
|
19
|
+
i = Limited::Interval.new(123)
|
20
|
+
i.length.should eq 123
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "can also be set via symbols :second, :minute, :hour, :day" do
|
24
|
+
it { Limited::Interval.new(:second ).length.should eq 1 }
|
25
|
+
it { Limited::Interval.new(:minute ).length.should eq 60 }
|
26
|
+
it { Limited::Interval.new(:hour ).length.should eq 60 * 60 }
|
27
|
+
it { Limited::Interval.new(:day ).length.should eq 60 * 60 * 24 }
|
28
|
+
it { endless.length.should eq infinity }
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should raise error when no integer or symbol given" do
|
32
|
+
expect { Limited::Interval.new(nil) }.to raise_error(ArgumentError)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "time_left" do
|
37
|
+
it "should return a value equal or lower than length" do
|
38
|
+
Limited::Interval.new(541).time_left.should be <= 541
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should be infinite if interval has the length Infinify" do
|
42
|
+
endless.time_left.should eq infinity
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "reset_start" do
|
47
|
+
it "should be calculated to a time near Time.now which difference is shorter than length" do
|
48
|
+
c = Limited::Interval.new(100)
|
49
|
+
(Time.now.to_f - c.last_start.to_f).should be <= 100
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should set last_start to 0 when interval is endless" do
|
53
|
+
endless.last_start.should eq 0
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "passed" do
|
58
|
+
let(:i) { Limited::Interval.new(541) }
|
59
|
+
it "should return false if length seconds have not yet passed" do
|
60
|
+
i.passed?.should be_false
|
61
|
+
Time.testing_offset += i.time_left - 1
|
62
|
+
i.passed?.should be_false
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should return true when enough time passed" do
|
66
|
+
Time.testing_offset += i.time_left
|
67
|
+
i.time_left.should eq 0
|
68
|
+
i.passed?.should be_true
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should always return false when interval is endless" do
|
72
|
+
endless.passed?.should be_false
|
73
|
+
Time.testing_offset += i.time_left
|
74
|
+
endless.passed?.should be_false
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: limited
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Moritz Küttel
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-06-
|
11
|
+
date: 2013-06-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -81,11 +81,14 @@ files:
|
|
81
81
|
- lib/limited.rb
|
82
82
|
- lib/limited/action.rb
|
83
83
|
- lib/limited/config.rb
|
84
|
+
- lib/limited/interval.rb
|
84
85
|
- lib/limited/version.rb
|
85
86
|
- limited.gemspec
|
86
87
|
- spec/limited_action_spec.rb
|
87
88
|
- spec/limited_config_spec.rb
|
89
|
+
- spec/limited_interval_spec.rb
|
88
90
|
- spec/limited_spec.rb
|
91
|
+
- spec/spec_helper.rb
|
89
92
|
homepage: https://github.com/mkuettel/limited
|
90
93
|
licenses:
|
91
94
|
- MIT
|
@@ -115,4 +118,6 @@ summary: Some utility functions to help you limit some actions in your applicati
|
|
115
118
|
test_files:
|
116
119
|
- spec/limited_action_spec.rb
|
117
120
|
- spec/limited_config_spec.rb
|
121
|
+
- spec/limited_interval_spec.rb
|
118
122
|
- spec/limited_spec.rb
|
123
|
+
- spec/spec_helper.rb
|