catptcha 0.0.2 → 0.0.3
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.
- data/{README → README.markdown} +14 -5
- data/Rakefile +6 -19
- data/catptcha.gemspec +2 -1
- data/generators/catptcha_migration/templates/migration.rb +7 -2
- data/lib/catptcha/photo.rb +8 -0
- data/lib/catptcha/photo_group.rb +8 -46
- data/lib/catptcha/seed.rb +31 -2
- data/lib/catptcha.rb +12 -1
- data/lib/tasks/catptcha.rake +6 -0
- data/test/catptcha_seed_test.rb +24 -0
- data/test/catptcha_test.rb +21 -0
- data/test/photo_group_test.rb +27 -0
- data/test/test_helper.rb +28 -0
- metadata +29 -8
data/{README → README.markdown}
RENAMED
@@ -9,20 +9,29 @@ This is still experimental and incomplete. Don't use it.
|
|
9
9
|
|
10
10
|
## Installation
|
11
11
|
|
12
|
-
|
12
|
+
From within your Rails application:
|
13
13
|
|
14
|
-
|
14
|
+
Add the gem to your Gemfile and load the rake tasks.
|
15
|
+
|
16
|
+
echo "gem 'catptcha'" >> Gemfile
|
17
|
+
echo "load 'tasks/catptcha.rake'" >> Rakefile
|
15
18
|
|
16
19
|
Put your flickr keys in config/flickr.yml, see flickr.example.yml.
|
17
20
|
|
18
|
-
Generate the migration
|
21
|
+
Generate and run the migration.
|
19
22
|
|
20
|
-
|
23
|
+
ruby script/generate catptcha_migration add_catptcha_tables
|
24
|
+
rake db:migrate
|
21
25
|
|
22
|
-
Seed the images
|
26
|
+
Seed the images.
|
23
27
|
|
24
28
|
rake catptcha:seed
|
25
29
|
|
30
|
+
Run the tests.
|
31
|
+
|
32
|
+
rake db:test:prepare
|
33
|
+
rake catptcha:test
|
34
|
+
|
26
35
|
## Author
|
27
36
|
|
28
37
|
Copyright (c) 2012 ENTP, released under the MIT license
|
data/Rakefile
CHANGED
@@ -1,23 +1,10 @@
|
|
1
|
-
require 'rake'
|
2
|
-
require 'rake/testtask'
|
3
|
-
require 'rdoc/task'
|
4
1
|
|
5
|
-
desc 'Default:
|
6
|
-
task :default => :
|
2
|
+
desc 'Default: build the gem'
|
3
|
+
task :default => :gem
|
7
4
|
|
8
|
-
desc '
|
9
|
-
|
10
|
-
|
11
|
-
t.libs << 'test'
|
12
|
-
t.pattern = 'test/**/*_test.rb'
|
13
|
-
t.verbose = true
|
5
|
+
desc 'Build the gem'
|
6
|
+
task :gem do
|
7
|
+
sh 'gem build catptcha.gemspec'
|
14
8
|
end
|
15
9
|
|
16
|
-
|
17
|
-
RDoc::Task.new(:rdoc) do |rdoc|
|
18
|
-
rdoc.rdoc_dir = 'rdoc'
|
19
|
-
rdoc.title = 'Catptcha'
|
20
|
-
rdoc.options << '--line-numbers' << '--inline-source'
|
21
|
-
rdoc.rdoc_files.include('README')
|
22
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
23
|
-
end
|
10
|
+
|
data/catptcha.gemspec
CHANGED
@@ -4,12 +4,13 @@ require 'catptcha'
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "catptcha"
|
6
6
|
s.version = Catptcha::VERSION
|
7
|
-
s.summary = 'Visual
|
7
|
+
s.summary = 'Visual captcha plugin for Rails 2.3'
|
8
8
|
s.description = <<-EOD
|
9
9
|
Choose the kitten!
|
10
10
|
EOD
|
11
11
|
s.add_dependency "commonthread-flickr_fu", "0.3.0"
|
12
12
|
s.add_dependency "activerecord", "~>2.3"
|
13
|
+
s.add_development_dependency "rr"
|
13
14
|
s.authors = ['Zack Hobson']
|
14
15
|
s.files = `git ls-files`.split("\n")
|
15
16
|
s.test_files = `git ls-files -- test/*`.split("\n")
|
@@ -2,18 +2,23 @@ class <%= class_name %> < ActiveRecord::Migration
|
|
2
2
|
def self.up
|
3
3
|
create_table :catptcha_photos do |t|
|
4
4
|
t.belongs_to :photo_group
|
5
|
+
t.string :key
|
5
6
|
t.string :url
|
6
|
-
t.index :catptcha_group_id
|
7
7
|
end
|
8
|
+
add_index :catptcha_photos, :photo_group_id
|
9
|
+
add_index :catptcha_photos, :key, :unique => true
|
10
|
+
|
8
11
|
create_table :catptcha_photo_groups do |t|
|
9
12
|
t.string :name
|
10
13
|
t.string :flickr_group_id
|
11
14
|
t.timestamp :photos_updated_at
|
12
15
|
t.integer :photos_count
|
13
16
|
t.boolean :kittens
|
14
|
-
t.index :kittens
|
15
17
|
end
|
18
|
+
add_index :catptcha_photo_groups, :flickr_group_id, :unique => true
|
19
|
+
add_index :catptcha_photo_groups, :kittens
|
16
20
|
end
|
21
|
+
|
17
22
|
def self.down
|
18
23
|
drop_table :catptcha_photos
|
19
24
|
drop_table :catptcha_photo_groups
|
data/lib/catptcha/photo.rb
CHANGED
@@ -2,4 +2,12 @@
|
|
2
2
|
class Catptcha::Photo < ActiveRecord::Base
|
3
3
|
set_table_name "catptcha_photos"
|
4
4
|
belongs_to :photo_group, :counter_cache => :photos_count, :class_name => 'Catptcha::PhotoGroup'
|
5
|
+
|
6
|
+
before_validation_on_create :generate_key
|
7
|
+
validates_uniqueness_of :key, :on => :create
|
8
|
+
validates_presence_of :photo_group_id
|
9
|
+
|
10
|
+
def generate_key
|
11
|
+
self.key = Digest::SHA1.hexdigest(url)
|
12
|
+
end
|
5
13
|
end
|
data/lib/catptcha/photo_group.rb
CHANGED
@@ -4,62 +4,24 @@
|
|
4
4
|
class Catptcha::PhotoGroup < ActiveRecord::Base
|
5
5
|
set_table_name 'catptcha_photo_groups'
|
6
6
|
|
7
|
+
validates_presence_of :name, :flickr_group_id
|
7
8
|
validates_uniqueness_of :name
|
8
|
-
validates_uniqueness_of :flickr_group_id
|
9
9
|
|
10
10
|
has_many :photos, :class_name => 'Catptcha::Photo'
|
11
11
|
named_scope :kittens, :conditions => {:kittens => true}
|
12
12
|
named_scope :not_kittens, :conditions => {:kittens => false}
|
13
13
|
|
14
14
|
def self.photos_count
|
15
|
-
|
15
|
+
sum(:photos_count)
|
16
16
|
end
|
17
17
|
|
18
18
|
def self.random count
|
19
|
-
# TODO
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
conditions << results.map(&:id)
|
26
|
-
end
|
27
|
-
results << Photo.first(
|
28
|
-
:conditions => conditions,
|
29
|
-
:offset => rand(photos_count).to_i
|
30
|
-
)
|
31
|
-
end
|
32
|
-
results
|
33
|
-
end
|
34
|
-
|
35
|
-
def update_images flickr
|
36
|
-
get_photos(flickr) do |photo|
|
37
|
-
photos.create(:url => photo.url(:square))
|
38
|
-
end
|
39
|
-
update_attributes(:photos_updated_at => DateTime.now.utc)
|
40
|
-
end
|
41
|
-
|
42
|
-
# fetches up to 2000 photos
|
43
|
-
def get_photos flickr
|
44
|
-
params = {
|
45
|
-
:group_id => flickr_group_id, :safe_search => 1, :content_type => 1,
|
46
|
-
:per_page => 500, :page => 1
|
47
|
-
}
|
48
|
-
params[:min_upload_date] = photos_updated_at if photos_updated_at
|
49
|
-
|
50
|
-
total_pages = nil
|
51
|
-
loop do
|
52
|
-
result = flickr.photos.search(params)
|
53
|
-
result.each do |photo|
|
54
|
-
yield photo
|
55
|
-
end
|
56
|
-
if total_pages.nil?
|
57
|
-
total_pages = [result.pages, 4].min
|
58
|
-
else
|
59
|
-
params[:page] += 1
|
60
|
-
break if params[:page] > total_pages
|
61
|
-
end
|
62
|
-
end
|
19
|
+
# TODO generate an identity/key column that isn't easy to guess
|
20
|
+
Catptcha::Photo.all(
|
21
|
+
:conditions => ['photo_group_id in (?)', all.map(&:id)],
|
22
|
+
:offset => rand(photos_count-count).to_i,
|
23
|
+
:limit => count
|
24
|
+
)
|
63
25
|
end
|
64
26
|
|
65
27
|
end
|
data/lib/catptcha/seed.rb
CHANGED
@@ -14,7 +14,7 @@ module Catptcha::Seed
|
|
14
14
|
@flickr ||= Flickr.new(Rails.root.join("config/flickr.yml").to_s)
|
15
15
|
end
|
16
16
|
|
17
|
-
def update
|
17
|
+
def update silent=false
|
18
18
|
SEED_GROUP_KITTENS.each do |name, id|
|
19
19
|
Catptcha::PhotoGroup.create(:name => name.to_s, :flickr_group_id => id, :kittens => true)
|
20
20
|
end
|
@@ -22,8 +22,37 @@ module Catptcha::Seed
|
|
22
22
|
Catptcha::PhotoGroup.create(:name => name.to_s, :flickr_group_id => id, :kittens => false)
|
23
23
|
end
|
24
24
|
Catptcha::PhotoGroup.all.each do |group|
|
25
|
-
group.
|
25
|
+
puts "updating photos for `#{group.name}`..." unless silent
|
26
|
+
count = update_photos group
|
27
|
+
puts "...done, #{count} photos imported" unless silent
|
26
28
|
end
|
27
29
|
end
|
30
|
+
|
31
|
+
# fetches up to 2500 photos
|
32
|
+
def update_photos group
|
33
|
+
params = {
|
34
|
+
:group_id => group.flickr_group_id, :safe_search => 1, :content_type => 1,
|
35
|
+
:per_page => 500, :page => 1
|
36
|
+
}
|
37
|
+
params[:min_upload_date] = group.photos_updated_at if group.photos_updated_at
|
38
|
+
|
39
|
+
total_pages = nil
|
40
|
+
photo_count = 0
|
41
|
+
loop do
|
42
|
+
result = flickr.photos.search(params)
|
43
|
+
result.each do |photo|
|
44
|
+
group.photos.create(:url => photo.url(:square))
|
45
|
+
photo_count += 1
|
46
|
+
end
|
47
|
+
if total_pages.nil?
|
48
|
+
total_pages = [result.pages, 5].min
|
49
|
+
else
|
50
|
+
params[:page] += 1
|
51
|
+
end
|
52
|
+
break if params[:page] >= total_pages
|
53
|
+
end
|
54
|
+
group.update_attributes(:photos_updated_at => DateTime.now.utc)
|
55
|
+
photo_count
|
56
|
+
end
|
28
57
|
end
|
29
58
|
end
|
data/lib/catptcha.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module Catptcha
|
2
|
-
VERSION = '0.0.
|
2
|
+
VERSION = '0.0.3'
|
3
3
|
|
4
4
|
class << self
|
5
5
|
# Get a list of 3 kitten photos
|
@@ -11,9 +11,20 @@ module Catptcha
|
|
11
11
|
def not_kittens
|
12
12
|
PhotoGroup.not_kittens.random(6)
|
13
13
|
end
|
14
|
+
|
15
|
+
def check_guesses *ids
|
16
|
+
guesses = ids.flatten.compact
|
17
|
+
if guesses.size != 3
|
18
|
+
return false
|
19
|
+
end
|
20
|
+
3 == Photo.count(:include => 'photo_group', :conditions => [
|
21
|
+
'catptcha_photos.id in (?) and kittens = ?', guesses, true
|
22
|
+
])
|
23
|
+
end
|
14
24
|
end
|
15
25
|
|
16
26
|
autoload :Photo, 'catptcha/photo'
|
17
27
|
autoload :PhotoGroup, 'catptcha/photo_group'
|
18
28
|
autoload :Seed, 'catptcha/seed'
|
29
|
+
|
19
30
|
end
|
data/lib/tasks/catptcha.rake
CHANGED
@@ -3,5 +3,11 @@ namespace :catptcha do
|
|
3
3
|
task :seed => :environment do
|
4
4
|
Catptcha::Seed.update
|
5
5
|
end
|
6
|
+
|
7
|
+
desc 'run catptcha plugin tests'
|
8
|
+
Rake::TestTask.new do |t|
|
9
|
+
t.test_files = FileList[File.dirname(__FILE__)+'/../../test/**/*_test.rb']
|
10
|
+
t.verbose = true
|
11
|
+
end
|
6
12
|
end
|
7
13
|
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require File.dirname(__FILE__)+'/test_helper.rb'
|
2
|
+
|
3
|
+
class CatptchaSeedTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
Catptcha::PhotoGroup.delete_all
|
6
|
+
Catptcha::Photo.delete_all
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_seed_with_no_photos
|
10
|
+
stub(Catptcha::Seed).flickr { build_flickr_stub [] }
|
11
|
+
Catptcha::Seed.update :silent
|
12
|
+
assert_equal 3, Catptcha::PhotoGroup.count
|
13
|
+
assert_equal 0, Catptcha::Photo.count
|
14
|
+
# doesn't recreate groups
|
15
|
+
Catptcha::Seed.update :silent
|
16
|
+
assert_equal 3, Catptcha::PhotoGroup.count
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_seed_with_photos
|
20
|
+
stub(Catptcha::Seed).flickr { build_flickr_stub { [ build_flickr_photo_stub ] } }
|
21
|
+
Catptcha::Seed.update :silent
|
22
|
+
assert_equal 3, Catptcha::Photo.count
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require File.dirname(__FILE__)+'/test_helper.rb'
|
2
|
+
|
3
|
+
class CatptchaTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
Catptcha::Photo.delete_all
|
7
|
+
Catptcha::PhotoGroup.delete_all
|
8
|
+
kittens = Catptcha::PhotoGroup.create!(:name => 'kittens', :flickr_group_id => 'x', :kittens => true)
|
9
|
+
3.times {|i| kittens.photos.create!(:url => "http://#{i}") }
|
10
|
+
not_kittens = Catptcha::PhotoGroup.create!(:name => 'not_kittens', :flickr_group_id => 'y', :kittens => false)
|
11
|
+
6.times {|i| not_kittens.photos.create!(:url => "http://#{i+3}") }
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_kittens
|
15
|
+
assert Catptcha.check_guesses(Catptcha.kittens.map(&:id))
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_not_kittens
|
19
|
+
assert !Catptcha.check_guesses(Catptcha.not_kittens.map(&:id)[0,3])
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require File.dirname(__FILE__)+'/test_helper.rb'
|
2
|
+
|
3
|
+
class PhotoGroupTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
Catptcha::Photo.delete_all
|
7
|
+
Catptcha::PhotoGroup.delete_all
|
8
|
+
kittens = Catptcha::PhotoGroup.create!(:name => 'kittens', :flickr_group_id => 'x', :kittens => true)
|
9
|
+
3.times {|i| kittens.photos.create!(:url => "http://#{i}") }
|
10
|
+
kittens = Catptcha::PhotoGroup.create!(:name => 'more_kittens', :flickr_group_id => 'a', :kittens => true)
|
11
|
+
3.times {|i| kittens.photos.create!(:url => "http://#{i+3}") }
|
12
|
+
not_kittens = Catptcha::PhotoGroup.create!(:name => 'tacos', :flickr_group_id => 'y', :kittens => false)
|
13
|
+
6.times {|i| not_kittens.photos.create!(:url => "http://#{i+6}") }
|
14
|
+
not_kittens = Catptcha::PhotoGroup.create!(:name => 'yaks', :flickr_group_id => 'b', :kittens => false)
|
15
|
+
6.times {|i| not_kittens.photos.create!(:url => "http://#{i+12}") }
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_photo_count
|
19
|
+
assert_equal 6, Catptcha::PhotoGroup.kittens.photos_count
|
20
|
+
assert_equal 12, Catptcha::PhotoGroup.not_kittens.photos_count
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_random
|
24
|
+
assert_equal 3, Catptcha::PhotoGroup.kittens.random(3).size
|
25
|
+
assert_equal 6, Catptcha::PhotoGroup.not_kittens.random(6).size
|
26
|
+
end
|
27
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
ENV['RAILS_ENV'] = 'test'
|
2
|
+
require "./config/environment"
|
3
|
+
require 'test/unit'
|
4
|
+
require 'rr'
|
5
|
+
|
6
|
+
class Test::Unit::TestCase
|
7
|
+
include RR::Adapters::RRMethods
|
8
|
+
|
9
|
+
# Stub out a flickr photo with a unique url
|
10
|
+
def build_flickr_photo_stub
|
11
|
+
@index ||= 0
|
12
|
+
@index += 1
|
13
|
+
Object.new.tap do |photo|
|
14
|
+
stub(photo).url { "http://#{@index}" }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Stub out a flickr search query using the provided photos,
|
19
|
+
# for lazy evaluation pass the photos in a block instead
|
20
|
+
def build_flickr_stub value=nil
|
21
|
+
Object.new.tap do |flickr|
|
22
|
+
photos = Object.new
|
23
|
+
stub(flickr).photos { stub(photos).search {
|
24
|
+
(value || yield).tap {|result| stub(result).pages { 1 } }
|
25
|
+
}}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: catptcha
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 25
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 3
|
10
|
+
version: 0.0.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Zack Hobson
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-05-
|
18
|
+
date: 2012-05-17 00:00:00 -07:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -49,6 +49,20 @@ dependencies:
|
|
49
49
|
version: "2.3"
|
50
50
|
type: :runtime
|
51
51
|
version_requirements: *id002
|
52
|
+
- !ruby/object:Gem::Dependency
|
53
|
+
name: rr
|
54
|
+
prerelease: false
|
55
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
hash: 3
|
61
|
+
segments:
|
62
|
+
- 0
|
63
|
+
version: "0"
|
64
|
+
type: :development
|
65
|
+
version_requirements: *id003
|
52
66
|
description: " Choose the kitten!\n"
|
53
67
|
email:
|
54
68
|
executables: []
|
@@ -60,7 +74,7 @@ extra_rdoc_files: []
|
|
60
74
|
files:
|
61
75
|
- .gitignore
|
62
76
|
- MIT-LICENSE
|
63
|
-
- README
|
77
|
+
- README.markdown
|
64
78
|
- Rakefile
|
65
79
|
- catptcha.gemspec
|
66
80
|
- generators/catptcha_migration/catptcha_migration_generator.rb
|
@@ -72,6 +86,10 @@ files:
|
|
72
86
|
- lib/catptcha/seed.rb
|
73
87
|
- lib/tasks/catptcha.rake
|
74
88
|
- rails/init.rb
|
89
|
+
- test/catptcha_seed_test.rb
|
90
|
+
- test/catptcha_test.rb
|
91
|
+
- test/photo_group_test.rb
|
92
|
+
- test/test_helper.rb
|
75
93
|
- uninstall.rb
|
76
94
|
has_rdoc: true
|
77
95
|
homepage:
|
@@ -106,6 +124,9 @@ rubyforge_project:
|
|
106
124
|
rubygems_version: 1.6.2
|
107
125
|
signing_key:
|
108
126
|
specification_version: 3
|
109
|
-
summary: Visual
|
110
|
-
test_files:
|
111
|
-
|
127
|
+
summary: Visual captcha plugin for Rails 2.3
|
128
|
+
test_files:
|
129
|
+
- test/catptcha_seed_test.rb
|
130
|
+
- test/catptcha_test.rb
|
131
|
+
- test/photo_group_test.rb
|
132
|
+
- test/test_helper.rb
|