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.
@@ -9,20 +9,29 @@ This is still experimental and incomplete. Don't use it.
9
9
 
10
10
  ## Installation
11
11
 
12
- Add the gem to your Gemfile and optionally require the rake task.
12
+ From within your Rails application:
13
13
 
14
- load 'tasks/catptcha.rake'
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
- ./script/generate catptcha_migration add_catptcha_tables
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: run unit tests.'
6
- task :default => :test
2
+ desc 'Default: build the gem'
3
+ task :default => :gem
7
4
 
8
- desc 'Test the catptcha plugin.'
9
- Rake::TestTask.new(:test) do |t|
10
- t.libs << 'lib'
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
- desc 'Generate documentation for the catptcha plugin.'
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 catptcha plugin for Rails 2.3'
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
@@ -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
@@ -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
- all.inject(0) {|a,g| a += (g.photos_count || 0) }
15
+ sum(:photos_count)
16
16
  end
17
17
 
18
18
  def self.random count
19
- # TODO use a single query
20
- results = []
21
- count.times do
22
- conditions = ['photo_group_id in (?)', all.map(&:id)]
23
- if results.any?
24
- conditions.first << ' and catptcha_photos.id not in (?)'
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.update_images flickr
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'
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
@@ -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
@@ -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: 27
4
+ hash: 25
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 2
10
- version: 0.0.2
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-16 00:00:00 -07:00
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 catptcha plugin for Rails 2.3
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