rate_limiter 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ *.gem
2
+ .bundle
3
+ pkg/*
4
+ .DS_Store
5
+ ._*
6
+ .idea/
7
+ .redcar/
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --tty
2
+ --colour
3
+ --format p
data/.rvmrc ADDED
@@ -0,0 +1,80 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # This is an RVM Project .rvmrc file, used to automatically load the ruby
4
+ # development environment upon cd'ing into the directory
5
+
6
+ # First we specify our desired <ruby>[@<gemset>], the @gemset name is optional.
7
+ environment_id="ruby-1.9.3-p327@rate_limiter"
8
+
9
+ #
10
+ # Uncomment the following lines if you want to verify rvm version per project
11
+ #
12
+ # rvmrc_rvm_version="1.10.2" # 1.10.1 seams as a safe start
13
+ # eval "$(echo ${rvm_version}.${rvmrc_rvm_version} | awk -F. '{print "[[ "$1*65536+$2*256+$3" -ge "$4*65536+$5*256+$6" ]]"}' )" || {
14
+ # echo "This .rvmrc file requires at least RVM ${rvmrc_rvm_version}, aborting loading."
15
+ # return 1
16
+ # }
17
+ #
18
+
19
+ #
20
+ # Uncomment following line if you want options to be set only for given project.
21
+ #
22
+ # PROJECT_JRUBY_OPTS=( --1.9 )
23
+ #
24
+ # The variable PROJECT_JRUBY_OPTS requires the following to be run in shell:
25
+ #
26
+ # chmod +x ${rvm_path}/hooks/after_use_jruby_opts
27
+ #
28
+
29
+ #
30
+ # First we attempt to load the desired environment directly from the environment
31
+ # file. This is very fast and efficient compared to running through the entire
32
+ # CLI and selector. If you want feedback on which environment was used then
33
+ # insert the word 'use' after --create as this triggers verbose mode.
34
+ #
35
+ if [[ -d "${rvm_path:-$HOME/.rvm}/environments" \
36
+ && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
37
+ then
38
+ \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
39
+
40
+ if [[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]]
41
+ then
42
+ . "${rvm_path:-$HOME/.rvm}/hooks/after_use"
43
+ fi
44
+ else
45
+ # If the environment file has not yet been created, use the RVM CLI to select.
46
+ if ! rvm --create "$environment_id"
47
+ then
48
+ echo "Failed to create RVM environment '${environment_id}'."
49
+ return 1
50
+ fi
51
+ fi
52
+
53
+ #
54
+ # If you use an RVM gemset file to install a list of gems (*.gems), you can have
55
+ # it be automatically loaded. Uncomment the following and adjust the filename if
56
+ # necessary.
57
+ #
58
+ # filename=".gems"
59
+ # if [[ -s "$filename" ]]
60
+ # then
61
+ # rvm gemset import "$filename" | grep -v already | grep -v listed | grep -v complete | sed '/^$/d'
62
+ # fi
63
+
64
+ # If you use bundler, this might be useful to you:
65
+ # if [[ -s Gemfile ]] && ! command -v bundle >/dev/null
66
+ # then
67
+ # printf "%b" "The rubygem 'bundler' is not installed. Installing it now.\n"
68
+ # gem install bundler
69
+ # fi
70
+ # if [[ -s Gemfile ]] && command -v bundle
71
+ # then
72
+ # bundle install
73
+ # fi
74
+
75
+ if [[ $- == *i* ]] # check for interactive shells
76
+ then
77
+ echo "Using: $(tput setaf 2)$GEM_HOME$(tput sgr0)" # show the user the ruby and gemset they are using in green
78
+ else
79
+ echo "Using: $GEM_HOME" # don't use colors in interactive shells
80
+ fi
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ ## v0.0.1
2
+
3
+ * Initial release.
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,80 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ rate_limiter (0.0.1)
5
+ activerecord (~> 3.0)
6
+ railties (~> 3.0)
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ actionpack (3.2.9)
12
+ activemodel (= 3.2.9)
13
+ activesupport (= 3.2.9)
14
+ builder (~> 3.0.0)
15
+ erubis (~> 2.7.0)
16
+ journey (~> 1.0.4)
17
+ rack (~> 1.4.0)
18
+ rack-cache (~> 1.2)
19
+ rack-test (~> 0.6.1)
20
+ sprockets (~> 2.2.1)
21
+ activemodel (3.2.9)
22
+ activesupport (= 3.2.9)
23
+ builder (~> 3.0.0)
24
+ activerecord (3.2.9)
25
+ activemodel (= 3.2.9)
26
+ activesupport (= 3.2.9)
27
+ arel (~> 3.0.2)
28
+ tzinfo (~> 0.3.29)
29
+ activesupport (3.2.9)
30
+ i18n (~> 0.6)
31
+ multi_json (~> 1.0)
32
+ arel (3.0.2)
33
+ builder (3.0.4)
34
+ diff-lcs (1.1.3)
35
+ erubis (2.7.0)
36
+ hike (1.2.1)
37
+ i18n (0.6.1)
38
+ journey (1.0.4)
39
+ json (1.7.5)
40
+ multi_json (1.5.0)
41
+ rack (1.4.1)
42
+ rack-cache (1.2)
43
+ rack (>= 0.4)
44
+ rack-ssl (1.3.2)
45
+ rack
46
+ rack-test (0.6.2)
47
+ rack (>= 1.0)
48
+ railties (3.2.9)
49
+ actionpack (= 3.2.9)
50
+ activesupport (= 3.2.9)
51
+ rack-ssl (~> 1.3.2)
52
+ rake (>= 0.8.7)
53
+ rdoc (~> 3.4)
54
+ thor (>= 0.14.6, < 2.0)
55
+ rake (10.0.2)
56
+ rdoc (3.12)
57
+ json (~> 1.4)
58
+ rspec (2.12.0)
59
+ rspec-core (~> 2.12.0)
60
+ rspec-expectations (~> 2.12.0)
61
+ rspec-mocks (~> 2.12.0)
62
+ rspec-core (2.12.1)
63
+ rspec-expectations (2.12.0)
64
+ diff-lcs (~> 1.1.3)
65
+ rspec-mocks (2.12.0)
66
+ sprockets (2.2.2)
67
+ hike (~> 1.2)
68
+ multi_json (~> 1.0)
69
+ rack (~> 1.0)
70
+ tilt (~> 1.1, != 1.3.0)
71
+ thor (0.16.0)
72
+ tilt (1.3.3)
73
+ tzinfo (0.3.35)
74
+
75
+ PLATFORMS
76
+ ruby
77
+
78
+ DEPENDENCIES
79
+ rate_limiter!
80
+ rspec
data/README.md ADDED
@@ -0,0 +1,65 @@
1
+ # rate_limiter
2
+
3
+ A gem that limits the rate at which ActiveRecord model instances can be created.
4
+
5
+ ## Rails Version
6
+
7
+ This gem has only been tested on Rails 3.2. There is no reason that I am aware of that would prevent it from working on all versions of Rails 3 (and Rails 4 when it is released).
8
+
9
+ ## Installation
10
+
11
+ Add the gem to your project's Gemfile:
12
+
13
+ gem 'rate_limiter'
14
+
15
+ ## Basic Usage
16
+
17
+ In the models you want to rate limit simply call the `rate_limit` method inside the model.
18
+
19
+ ```ruby
20
+ class ProductReview < ActiveRecord::Base
21
+ rate_limit
22
+ end
23
+ ```
24
+
25
+ By default this will rate limit creation of instances using the `ip_address` attribute with an interval of one minute. This is kind of a bold assumption (that may change in future versions) since there's a good chance you don't have an `ip_address` attribute on your model. If that's the case then you can do the following:
26
+
27
+ ```ruby
28
+ class ProductReview < ActiveRecord::Base
29
+ rate_limit :on => :username
30
+ end
31
+ ```
32
+
33
+ This will instead check for `ProductReview`s with a matching `username` instead.
34
+
35
+ Because you may want to increase or decrease the interval between creating instances of your model you can do this:
36
+
37
+ ```ruby
38
+ class ProductReview < ActiveRecord::Base
39
+ rate_limit :interval => 3.hours
40
+ end
41
+ ```
42
+
43
+ ## Contributing
44
+
45
+ If you feel like you can add something useful to rate_limiter then don't hesitate to contribute! To make sure your fix/feature has a high chance of being included, please do the following:
46
+
47
+ 1. Fork the repo.
48
+
49
+ 2. Run the tests. I will only take pull requests with passing tests, and it's great to know that you have a clean slate: `bundle && rake`
50
+
51
+ 3. Add a test for your change. Only adding tests for existing code, refactoring, and documentation changes require no new tests. If you are adding functionality or fixing a bug, you need a test!
52
+
53
+ 4. Make the test pass.
54
+
55
+ 5. Push to your fork and submit a pull request.
56
+
57
+ I can't guarantee that I will accept the change, but if I don't I will be sure to let you know why!
58
+
59
+ Some things that will increase the chance that your pull request is accepted, taken straight from the Ruby on Rails guide:
60
+
61
+ * Use Rails idioms and helpers
62
+ * Include tests that fail without your code, and pass with it
63
+ * Update the documentation, guides, or whatever is affected by your contribution
64
+
65
+ Yes, I am well aware of the irony of asking for tests when there are effectively none right now. This gem is a work in progress.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,24 @@
1
+ require 'singleton'
2
+
3
+ require 'rate_limiter/config'
4
+ require 'rate_limiter/model'
5
+
6
+ module RateLimiter
7
+ def self.timestamp_field= field_name
8
+ RateLimiter.config.timestamp_field = field_name
9
+ end
10
+
11
+ def self.timestamp_field
12
+ RateLimiter.config.timestamp_field
13
+ end
14
+
15
+ private
16
+
17
+ def self.config
18
+ @@config ||= RateLimiter::Config.instance
19
+ end
20
+ end
21
+
22
+ ActiveSupport.on_load(:active_record) do
23
+ include RateLimiter::Model
24
+ end
@@ -0,0 +1,10 @@
1
+ module RateLimiter
2
+ class Config
3
+ include Singleton
4
+ attr_accessor :timestamp_field
5
+
6
+ def initialize
7
+ @timestamp_field = :created_at
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,52 @@
1
+ module RateLimiter
2
+ module Model
3
+ def self.included(base)
4
+ base.send :extend, ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+ def rate_limit options = {}
9
+ send :include, InstanceMethods
10
+
11
+ class_attribute :rate_limit_on
12
+ self.rate_limit_on = options[:on] || :ip_address
13
+
14
+ class_attribute :rate_limit_interval
15
+ self.rate_limit_interval = options[:interval] || 1.minute
16
+
17
+ class_attribute :rate_limit_if_condition
18
+ self.rate_limit_if_condition = options[:if]
19
+
20
+ class_attribute :rate_limit_unless_condition
21
+ self.rate_limit_unless_condition = options[:unless]
22
+
23
+ self.before_create :check_rate_limit
24
+ end
25
+ end
26
+
27
+ module InstanceMethods
28
+ def check_rate_limit
29
+ if rate_limit?
30
+ klass = self.class
31
+
32
+ others = klass.where("#{klass.rate_limit_on} =? AND created_at >= ?", self.send(klass.rate_limit_on), Time.now - klass.rate_limit_interval)
33
+
34
+ if others.present?
35
+ # TODO: Come up with a better error message.
36
+ self.errors.add(:base, "You cannot create a new #{klass.name.downcase} yet.")
37
+
38
+ false
39
+ else
40
+ true
41
+ end
42
+ else
43
+ true
44
+ end
45
+ end
46
+
47
+ def rate_limit?
48
+ (rate_limit_if_condition.blank? || rate_limit_if_condition.call(self)) && !rate_limit_unless_condition.try(:call, self)
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,3 @@
1
+ module RateLimiter
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+ require 'rate_limiter/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'rate_limiter'
7
+ s.version = RateLimiter::VERSION
8
+ s.authors = ['Sean Eshbaugh']
9
+ s.email = ['seaneshbaugh@gmail.com']
10
+ s.homepage = 'https://github.com/seaneshbaugh/rate_limiter'
11
+ s.summary = 'Adds creation rate limiting to ActiveRecord models.'
12
+ s.description = 'Adds creation rate limiting to ActiveRecord models.'
13
+
14
+ s.rubyforge_project = 'rate_limiter'
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ['lib']
20
+
21
+ s.add_dependency 'railties', '~> 3.0'
22
+ s.add_dependency 'activerecord', '~> 3.0'
23
+
24
+ s.add_development_dependency 'rspec'
25
+ end
@@ -0,0 +1,10 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper.rb'
3
+
4
+ describe RateLimiter do
5
+ describe 'Sanity Test' do
6
+ it 'should be a Module' do
7
+ RateLimiter.should be_a(Module)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,6 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rails/railtie'
4
+ require 'active_record'
5
+
6
+ require 'rate_limiter'
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rate_limiter
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Sean Eshbaugh
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-12 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: railties
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '3.0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '3.0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: activerecord
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '3.0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '3.0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: Adds creation rate limiting to ActiveRecord models.
63
+ email:
64
+ - seaneshbaugh@gmail.com
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - .gitignore
70
+ - .rspec
71
+ - .rvmrc
72
+ - CHANGELOG.md
73
+ - Gemfile
74
+ - Gemfile.lock
75
+ - README.md
76
+ - Rakefile
77
+ - lib/rate_limiter.rb
78
+ - lib/rate_limiter/config.rb
79
+ - lib/rate_limiter/model.rb
80
+ - lib/rate_limiter/version.rb
81
+ - rate_limiter.gemspec
82
+ - spec/rate_limiter/rate_limiter_spec.rb
83
+ - spec/spec_helper.rb
84
+ homepage: https://github.com/seaneshbaugh/rate_limiter
85
+ licenses: []
86
+ post_install_message:
87
+ rdoc_options: []
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ! '>='
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ requirements: []
103
+ rubyforge_project: rate_limiter
104
+ rubygems_version: 1.8.24
105
+ signing_key:
106
+ specification_version: 3
107
+ summary: Adds creation rate limiting to ActiveRecord models.
108
+ test_files:
109
+ - spec/rate_limiter/rate_limiter_spec.rb
110
+ - spec/spec_helper.rb