kosher 0.8.0 → 0.9.1
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/.travis.yml +3 -0
- data/Gemfile +2 -0
- data/README.md +4 -3
- data/Rakefile +6 -8
- data/data/venues.yml +28 -0
- data/kosher.gemspec +8 -14
- data/lib/kosher/invalid.rb +7 -0
- data/lib/kosher/offer.rb +16 -18
- data/lib/kosher/seller.rb +6 -20
- data/lib/kosher/shipping.rb +16 -10
- data/lib/kosher/unit.rb +28 -0
- data/lib/kosher/venue.rb +8 -4
- data/lib/kosher/version.rb +1 -1
- data/lib/kosher.rb +8 -29
- data/test/kosher_test.rb +62 -0
- metadata +58 -105
- data/lib/kosher/availability.rb +0 -22
- data/lib/kosher/condition.rb +0 -28
- data/lib/kosher/description.rb +0 -47
- data/lib/kosher/item.rb +0 -16
- data/lib/kosher/location.rb +0 -8
- data/lib/kosher/price.rb +0 -13
- data/lib/kosher/threshold.rb +0 -15
- data/spec/kosher/availability_spec.rb +0 -41
- data/spec/kosher/condition_spec.rb +0 -29
- data/spec/kosher/description_spec.rb +0 -79
- data/spec/kosher/item_spec.rb +0 -45
- data/spec/kosher/location_spec.rb +0 -5
- data/spec/kosher/offer_spec.rb +0 -178
- data/spec/kosher/price_spec.rb +0 -16
- data/spec/kosher/seller_spec.rb +0 -56
- data/spec/kosher/shipping_spec.rb +0 -41
- data/spec/kosher/venue_spec.rb +0 -5
- data/spec/kosher_spec.rb +0 -4
- data/spec/spec_helper.rb +0 -5
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/README.md
CHANGED
data/Rakefile
CHANGED
@@ -1,11 +1,9 @@
|
|
1
|
-
require 'bundler'
|
2
|
-
require '
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rake/testtask'
|
3
3
|
|
4
|
-
|
4
|
+
task :default => :test
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
Rake::TestTask.new do |test|
|
7
|
+
test.libs << 'test'
|
8
|
+
test.test_files = FileList['test/**/*_test.rb']
|
9
9
|
end
|
10
|
-
|
11
|
-
task :default => :spec
|
data/data/venues.yml
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
---
|
2
|
+
- id: 1
|
3
|
+
name: Amazon.com
|
4
|
+
country: us
|
5
|
+
- id: 2
|
6
|
+
name: Amazon.co.uk
|
7
|
+
country: uk
|
8
|
+
- id: 3
|
9
|
+
name: Amazon.de
|
10
|
+
country: de
|
11
|
+
- id: 4
|
12
|
+
name: Amazon.ca
|
13
|
+
country: ca
|
14
|
+
- id: 5
|
15
|
+
name: Amazon.fr
|
16
|
+
country: fr
|
17
|
+
- id: 6
|
18
|
+
name: Amazon.co.jp
|
19
|
+
country: jp
|
20
|
+
- id: 7
|
21
|
+
name: Amazon.co.jp
|
22
|
+
country: jp
|
23
|
+
- id: 8
|
24
|
+
name: Amazon.cn
|
25
|
+
country: cn
|
26
|
+
- id: 9
|
27
|
+
name: Barnesandnoble.com
|
28
|
+
country: us
|
data/kosher.gemspec
CHANGED
@@ -6,27 +6,21 @@ Gem::Specification.new do |s|
|
|
6
6
|
s.name = 'kosher'
|
7
7
|
s.version = Kosher::VERSION
|
8
8
|
s.platform = Gem::Platform::RUBY
|
9
|
-
s.authors = ['
|
9
|
+
s.authors = ['Hakan Ensari']
|
10
10
|
s.email = 'code@papercavalier.com'
|
11
|
-
s.homepage = 'https://
|
12
|
-
s.summary = %q{
|
13
|
-
s.description = %q{
|
11
|
+
s.homepage = 'https://github.com/hakanensari/kosher'
|
12
|
+
s.summary = %q{Online trade, abstracted}
|
13
|
+
s.description = %q{Online trade, abstracted}
|
14
14
|
|
15
|
-
|
16
|
-
'
|
17
|
-
|
18
|
-
|
19
|
-
end
|
20
|
-
|
21
|
-
{
|
22
|
-
'money' => '~> 3.7.1',
|
23
|
-
'structure' => '~> 0.8.0'
|
15
|
+
{
|
16
|
+
'activemodel' => '~> 3.0',
|
17
|
+
'money' => '~> 3.7',
|
18
|
+
'structure' => '~> 0.15'
|
24
19
|
}.each do |lib, version|
|
25
20
|
s.add_runtime_dependency lib, version
|
26
21
|
end
|
27
22
|
|
28
23
|
s.files = `git ls-files`.split("\n")
|
29
24
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
30
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
31
25
|
s.require_paths = ['lib']
|
32
26
|
end
|
data/lib/kosher/offer.rb
CHANGED
@@ -1,37 +1,35 @@
|
|
1
1
|
module Kosher
|
2
|
-
|
3
|
-
# An offer.
|
4
2
|
class Offer < Structure
|
3
|
+
include ActiveModel::Validations
|
5
4
|
include Comparable
|
6
5
|
|
7
|
-
key
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
key :id
|
7
|
+
one :seller
|
8
|
+
one :shipping
|
9
|
+
one :unit
|
10
|
+
key :venue_id, Integer
|
11
|
+
|
12
|
+
validates_presence_of :seller, :shipping, :unit, :venue
|
12
13
|
|
13
|
-
# Compares offer with another offer.
|
14
|
-
#
|
15
|
-
# A kosher offer is better than an unkosher offer. If both offers are
|
16
|
-
# kosher or unkosher, a lower-priced offer is better.
|
17
14
|
def <=>(other)
|
18
15
|
if kosher? != other.kosher?
|
19
16
|
kosher? ? -1 : 1
|
20
17
|
else
|
21
|
-
|
18
|
+
total <=> other.total
|
22
19
|
end
|
23
20
|
end
|
24
21
|
|
25
|
-
# Returns whether the offer is kosher.
|
26
|
-
#
|
27
|
-
# An offer is kosher if its item, seller, and shipping are kosher.
|
28
22
|
def kosher?
|
29
|
-
|
23
|
+
raise Invalid.new(self) unless valid?
|
24
|
+
seller.kosher? && shipping.kosher? && unit.kosher?
|
30
25
|
end
|
31
26
|
|
32
|
-
# The total price of an offer.
|
33
27
|
def price
|
34
|
-
|
28
|
+
unit.price + shipping.cost
|
29
|
+
end
|
30
|
+
|
31
|
+
def venue
|
32
|
+
Venue.find(venue_id)
|
35
33
|
end
|
36
34
|
end
|
37
35
|
end
|
data/lib/kosher/seller.rb
CHANGED
@@ -1,27 +1,13 @@
|
|
1
1
|
module Kosher
|
2
|
-
|
3
|
-
# The seller offering a book on a venue.
|
4
|
-
#
|
5
|
-
# A seller may have a location.
|
6
2
|
class Seller < Structure
|
7
|
-
|
8
|
-
|
9
|
-
key
|
10
|
-
key
|
11
|
-
key :rating, :type => Float
|
12
|
-
has_one :location
|
13
|
-
|
14
|
-
# Returns whether we blacklist the seller.
|
15
|
-
def blacklisted?
|
16
|
-
Kosher.seller_blacklist.include? id
|
17
|
-
end
|
3
|
+
key :id
|
4
|
+
key :kosher, Boolean, :default => true
|
5
|
+
key :name
|
6
|
+
key :rating, Float
|
18
7
|
|
19
|
-
# Returns whether the
|
20
|
-
#
|
21
|
-
# A seller is kosher as long as he is not blacklisted and his rating is
|
22
|
-
# unknown, 0.0, or above our minimum threshold.
|
8
|
+
# Returns whether the item is kosher.
|
23
9
|
def kosher?
|
24
|
-
|
10
|
+
kosher
|
25
11
|
end
|
26
12
|
end
|
27
13
|
end
|
data/lib/kosher/shipping.rb
CHANGED
@@ -1,19 +1,25 @@
|
|
1
1
|
module Kosher
|
2
|
-
# Shipping details of an offer.
|
3
|
-
#
|
4
|
-
# Shipping costs something (or nothing) and is subject to availability.
|
5
2
|
class Shipping < Structure
|
6
|
-
|
7
|
-
has_one :availability
|
3
|
+
include ActiveModel::Validations
|
8
4
|
|
9
|
-
|
10
|
-
|
11
|
-
|
5
|
+
key :available
|
6
|
+
key :cents, Integer
|
7
|
+
key :currency
|
8
|
+
key :kosher, Boolean, :default => true
|
9
|
+
|
10
|
+
validates_presence_of :currency, :available
|
11
|
+
validates_numericality_of :cents,
|
12
|
+
:greater_than => 0
|
13
|
+
|
14
|
+
# Shipping cost.
|
15
|
+
def cost
|
16
|
+
Money.new(cents, currency)
|
12
17
|
end
|
13
18
|
|
14
|
-
# Returns
|
19
|
+
# Returns whether the item is kosher.
|
15
20
|
def kosher?
|
16
|
-
|
21
|
+
raise Invalid.new(self) unless valid?
|
22
|
+
kosher
|
17
23
|
end
|
18
24
|
end
|
19
25
|
end
|
data/lib/kosher/unit.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
module Kosher
|
2
|
+
class Unit < Structure
|
3
|
+
include ActiveModel::Validations
|
4
|
+
|
5
|
+
key :cents, Integer
|
6
|
+
key :condition, Integer
|
7
|
+
key :currency
|
8
|
+
key :description
|
9
|
+
key :kosher, Boolean, :default => true
|
10
|
+
key :quantity, Integer, :default => 1
|
11
|
+
|
12
|
+
validates_inclusion_of :condition, :in => 1..6
|
13
|
+
validates_numericality_of :cents,
|
14
|
+
:greater_than => 0
|
15
|
+
validates_presence_of :currency
|
16
|
+
|
17
|
+
# Returns whether the item is kosher.
|
18
|
+
def kosher?
|
19
|
+
raise Invalid.new(self) unless valid?
|
20
|
+
kosher
|
21
|
+
end
|
22
|
+
|
23
|
+
# Item price.
|
24
|
+
def price
|
25
|
+
Money.new(cents, currency)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/kosher/venue.rb
CHANGED
@@ -1,9 +1,13 @@
|
|
1
1
|
module Kosher
|
2
|
-
|
3
|
-
# A Venue.
|
4
2
|
class Venue < Structure
|
5
|
-
|
3
|
+
include Static
|
4
|
+
|
5
|
+
set_data_path File.expand_path("../../../data/venues.yml", __FILE__)
|
6
|
+
|
7
|
+
# The name of the venue.
|
6
8
|
key :name
|
7
|
-
|
9
|
+
|
10
|
+
# The country the venue is based in.
|
11
|
+
key :country
|
8
12
|
end
|
9
13
|
end
|
data/lib/kosher/version.rb
CHANGED
data/lib/kosher.rb
CHANGED
@@ -1,34 +1,13 @@
|
|
1
|
-
|
2
|
-
# set of models.
|
3
|
-
|
1
|
+
require 'active_model'
|
4
2
|
require 'money'
|
5
3
|
require 'structure'
|
6
|
-
require 'structure/json'
|
7
|
-
|
8
|
-
# Require this module before all models.
|
9
|
-
require 'kosher/threshold'
|
10
|
-
|
11
|
-
# Require the models.
|
12
|
-
require 'kosher/availability'
|
13
|
-
require 'kosher/condition'
|
14
|
-
require 'kosher/description'
|
15
|
-
require 'kosher/item'
|
16
|
-
require 'kosher/location'
|
17
|
-
require 'kosher/offer'
|
18
|
-
require 'kosher/price'
|
19
|
-
require 'kosher/seller'
|
20
|
-
require 'kosher/shipping'
|
21
|
-
require 'kosher/venue'
|
22
4
|
|
23
5
|
module Kosher
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
Availability.threshold = 48
|
32
|
-
Condition.threshold = 4
|
33
|
-
Seller.threshold = 4.8
|
6
|
+
autoload :Invalid, 'kosher/invalid'
|
7
|
+
autoload :Item, 'kosher/item'
|
8
|
+
autoload :Offer, 'kosher/offer'
|
9
|
+
autoload :Seller, 'kosher/seller'
|
10
|
+
autoload :Shipping, 'kosher/shipping'
|
11
|
+
autoload :Unit, 'kosher/unit'
|
12
|
+
autoload :Venue, 'kosher/venue'
|
34
13
|
end
|
data/test/kosher_test.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'minitest/autorun'
|
3
|
+
|
4
|
+
require_relative '../lib/kosher'
|
5
|
+
|
6
|
+
class TestKosher < MiniTest::Unit::TestCase
|
7
|
+
def test_unit_price
|
8
|
+
unit = Kosher::Unit.new(:cents => '100',
|
9
|
+
:currency => 'JPY')
|
10
|
+
assert_equal '¥1.00', unit.price.format
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_shipping_cost
|
14
|
+
shipping = Kosher::Shipping.new(:cents => '100',
|
15
|
+
:currency => 'EUR')
|
16
|
+
assert_equal '1,00 €', shipping.cost.format
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_offer_price
|
20
|
+
shipping = Kosher::Shipping.new(:cents => 100,
|
21
|
+
:currency => 'USD')
|
22
|
+
unit = Kosher::Unit.new(:cents => 100,
|
23
|
+
:currency => 'USD')
|
24
|
+
offer = Kosher::Offer.new(:shipping => shipping,
|
25
|
+
:unit => unit)
|
26
|
+
assert_equal '$2.00', offer.price.format
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_venue
|
30
|
+
assert_equal 'Amazon.com', Kosher::Venue.find(1).name
|
31
|
+
assert_equal 'Amazon.co.uk', Kosher::Venue.find(2).name
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_venue_in_offer
|
35
|
+
offer = Kosher::Offer.new(:venue_id => 1)
|
36
|
+
assert_equal Kosher::Venue.find(1), offer.venue
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_validation
|
40
|
+
assert_raises(Kosher::Invalid) { Kosher::Unit.new.kosher? }
|
41
|
+
unit = Kosher::Unit.new(:condition => 1,
|
42
|
+
:cents => 100,
|
43
|
+
:currency => 'USD')
|
44
|
+
assert unit.kosher?
|
45
|
+
|
46
|
+
assert_raises(Kosher::Invalid) { Kosher::Shipping.new.kosher? }
|
47
|
+
shipping = Kosher::Shipping.new(:available => true,
|
48
|
+
:cents => 100,
|
49
|
+
:currency => 'USD')
|
50
|
+
assert shipping.kosher?
|
51
|
+
|
52
|
+
assert_raises(Kosher::Invalid) { Kosher::Offer.new.kosher? }
|
53
|
+
offer = Kosher::Offer.new(:unit => unit,
|
54
|
+
:shipping => shipping,
|
55
|
+
:seller => Kosher::Seller.new,
|
56
|
+
:venue_id => 1)
|
57
|
+
assert offer.kosher?
|
58
|
+
|
59
|
+
offer.venue_id = 0
|
60
|
+
assert_raises(Kosher::Invalid) { offer.kosher? }
|
61
|
+
end
|
62
|
+
end
|
metadata
CHANGED
@@ -1,148 +1,101 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: kosher
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
6
|
-
- 0
|
7
|
-
- 8
|
8
|
-
- 0
|
9
|
-
version: 0.8.0
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.1
|
5
|
+
prerelease:
|
10
6
|
platform: ruby
|
11
|
-
authors:
|
12
|
-
-
|
7
|
+
authors:
|
8
|
+
- Hakan Ensari
|
13
9
|
autorequire:
|
14
10
|
bindir: bin
|
15
11
|
cert_chain: []
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
name: rspec
|
22
|
-
prerelease: false
|
23
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
12
|
+
date: 2011-08-12 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activemodel
|
16
|
+
requirement: &70269322416700 !ruby/object:Gem::Requirement
|
24
17
|
none: false
|
25
|
-
requirements:
|
18
|
+
requirements:
|
26
19
|
- - ~>
|
27
|
-
- !ruby/object:Gem::Version
|
28
|
-
|
29
|
-
|
30
|
-
- 6
|
31
|
-
version: "2.6"
|
32
|
-
type: :development
|
33
|
-
version_requirements: *id001
|
34
|
-
- !ruby/object:Gem::Dependency
|
35
|
-
name: money
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '3.0'
|
22
|
+
type: :runtime
|
36
23
|
prerelease: false
|
37
|
-
|
24
|
+
version_requirements: *70269322416700
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: money
|
27
|
+
requirement: &70269322415880 !ruby/object:Gem::Requirement
|
38
28
|
none: false
|
39
|
-
requirements:
|
29
|
+
requirements:
|
40
30
|
- - ~>
|
41
|
-
- !ruby/object:Gem::Version
|
42
|
-
|
43
|
-
- 3
|
44
|
-
- 7
|
45
|
-
- 1
|
46
|
-
version: 3.7.1
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '3.7'
|
47
33
|
type: :runtime
|
48
|
-
version_requirements: *id002
|
49
|
-
- !ruby/object:Gem::Dependency
|
50
|
-
name: structure
|
51
34
|
prerelease: false
|
52
|
-
|
35
|
+
version_requirements: *70269322415880
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: structure
|
38
|
+
requirement: &70269322415060 !ruby/object:Gem::Requirement
|
53
39
|
none: false
|
54
|
-
requirements:
|
40
|
+
requirements:
|
55
41
|
- - ~>
|
56
|
-
- !ruby/object:Gem::Version
|
57
|
-
|
58
|
-
- 0
|
59
|
-
- 8
|
60
|
-
- 0
|
61
|
-
version: 0.8.0
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0.15'
|
62
44
|
type: :runtime
|
63
|
-
|
64
|
-
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70269322415060
|
47
|
+
description: Online trade, abstracted
|
65
48
|
email: code@papercavalier.com
|
66
49
|
executables: []
|
67
|
-
|
68
50
|
extensions: []
|
69
|
-
|
70
51
|
extra_rdoc_files: []
|
71
|
-
|
72
|
-
files:
|
52
|
+
files:
|
73
53
|
- .gitignore
|
54
|
+
- .travis.yml
|
74
55
|
- Gemfile
|
75
56
|
- LICENSE
|
76
57
|
- README.md
|
77
58
|
- Rakefile
|
59
|
+
- data/venues.yml
|
78
60
|
- kosher.gemspec
|
79
61
|
- lib/kosher.rb
|
80
|
-
- lib/kosher/
|
81
|
-
- lib/kosher/condition.rb
|
82
|
-
- lib/kosher/description.rb
|
83
|
-
- lib/kosher/item.rb
|
84
|
-
- lib/kosher/location.rb
|
62
|
+
- lib/kosher/invalid.rb
|
85
63
|
- lib/kosher/offer.rb
|
86
|
-
- lib/kosher/price.rb
|
87
64
|
- lib/kosher/seller.rb
|
88
65
|
- lib/kosher/shipping.rb
|
89
|
-
- lib/kosher/
|
66
|
+
- lib/kosher/unit.rb
|
90
67
|
- lib/kosher/venue.rb
|
91
68
|
- lib/kosher/version.rb
|
92
|
-
-
|
93
|
-
|
94
|
-
- spec/kosher/description_spec.rb
|
95
|
-
- spec/kosher/item_spec.rb
|
96
|
-
- spec/kosher/location_spec.rb
|
97
|
-
- spec/kosher/offer_spec.rb
|
98
|
-
- spec/kosher/price_spec.rb
|
99
|
-
- spec/kosher/seller_spec.rb
|
100
|
-
- spec/kosher/shipping_spec.rb
|
101
|
-
- spec/kosher/venue_spec.rb
|
102
|
-
- spec/kosher_spec.rb
|
103
|
-
- spec/spec_helper.rb
|
104
|
-
has_rdoc: true
|
105
|
-
homepage: https://rubygems.org/gems/kosher
|
69
|
+
- test/kosher_test.rb
|
70
|
+
homepage: https://github.com/hakanensari/kosher
|
106
71
|
licenses: []
|
107
|
-
|
108
72
|
post_install_message:
|
109
73
|
rdoc_options: []
|
110
|
-
|
111
|
-
require_paths:
|
74
|
+
require_paths:
|
112
75
|
- lib
|
113
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
114
77
|
none: false
|
115
|
-
requirements:
|
116
|
-
- -
|
117
|
-
- !ruby/object:Gem::Version
|
118
|
-
|
78
|
+
requirements:
|
79
|
+
- - ! '>='
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
segments:
|
119
83
|
- 0
|
120
|
-
|
121
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
hash: 908814609031354876
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
122
86
|
none: false
|
123
|
-
requirements:
|
124
|
-
- -
|
125
|
-
- !ruby/object:Gem::Version
|
126
|
-
|
87
|
+
requirements:
|
88
|
+
- - ! '>='
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
segments:
|
127
92
|
- 0
|
128
|
-
|
93
|
+
hash: 908814609031354876
|
129
94
|
requirements: []
|
130
|
-
|
131
95
|
rubyforge_project:
|
132
|
-
rubygems_version: 1.
|
96
|
+
rubygems_version: 1.8.6
|
133
97
|
signing_key:
|
134
98
|
specification_version: 3
|
135
|
-
summary:
|
136
|
-
test_files:
|
137
|
-
-
|
138
|
-
- spec/kosher/condition_spec.rb
|
139
|
-
- spec/kosher/description_spec.rb
|
140
|
-
- spec/kosher/item_spec.rb
|
141
|
-
- spec/kosher/location_spec.rb
|
142
|
-
- spec/kosher/offer_spec.rb
|
143
|
-
- spec/kosher/price_spec.rb
|
144
|
-
- spec/kosher/seller_spec.rb
|
145
|
-
- spec/kosher/shipping_spec.rb
|
146
|
-
- spec/kosher/venue_spec.rb
|
147
|
-
- spec/kosher_spec.rb
|
148
|
-
- spec/spec_helper.rb
|
99
|
+
summary: Online trade, abstracted
|
100
|
+
test_files:
|
101
|
+
- test/kosher_test.rb
|
data/lib/kosher/availability.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
module Kosher
|
2
|
-
|
3
|
-
# The availability of an offer.
|
4
|
-
#
|
5
|
-
# This represents within how many hours an offer is expected to ship out.
|
6
|
-
class Availability < Structure
|
7
|
-
include Threshold
|
8
|
-
|
9
|
-
key :hours, :type => Integer
|
10
|
-
|
11
|
-
# Returns whether the availability is kosher.
|
12
|
-
#
|
13
|
-
# An availability is kosher if the item ships within a maximum threshold of
|
14
|
-
# hours.
|
15
|
-
#
|
16
|
-
# If we do not know when an item will ship (e.g. Amazon's preorders), we
|
17
|
-
# should set hours to nil, which will render the availability unkosher.
|
18
|
-
def kosher?
|
19
|
-
!hours.nil? && hours <= threshold
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
data/lib/kosher/condition.rb
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
module Kosher
|
2
|
-
|
3
|
-
# The condition of a book.
|
4
|
-
#
|
5
|
-
# This condition is modeled on a numeric range starting from 1, which
|
6
|
-
# represents `new' offers.
|
7
|
-
class Condition < Structure
|
8
|
-
include Threshold
|
9
|
-
|
10
|
-
key :grade, :type => Integer
|
11
|
-
|
12
|
-
# Returns whether the condition is kosher.
|
13
|
-
#
|
14
|
-
# A condition is kosher if its grade is below a minimum threshold. We
|
15
|
-
# usually consider books that are good or better kosher.
|
16
|
-
def kosher?
|
17
|
-
grade <= threshold
|
18
|
-
end
|
19
|
-
|
20
|
-
def new?
|
21
|
-
grade == 1
|
22
|
-
end
|
23
|
-
|
24
|
-
def used?
|
25
|
-
!new?
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
data/lib/kosher/description.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
module Kosher
|
2
|
-
|
3
|
-
# The seller's description of the offer.
|
4
|
-
class Description < Structure
|
5
|
-
key :text, :default => ''
|
6
|
-
|
7
|
-
DAMAGED = "\\b(?:missing|torn|broken|split|discard|withdrawn|rent|stain|school|damaged|water)"
|
8
|
-
EXLIB = "(?:e?x|discarded|retired|former|has|have)[\\s._-]*lib"
|
9
|
-
MARKED = "(highlight|hilit|underlin)"
|
10
|
-
MISSING_VOL = "(vols?|volume) only"
|
11
|
-
REVIEW_COPY = "\\b(?:uncorrected|advanced?\\sreview|arc)\\b"
|
12
|
-
|
13
|
-
def damaged?
|
14
|
-
matches? DAMAGED
|
15
|
-
end
|
16
|
-
|
17
|
-
def ex_lib?
|
18
|
-
matches?(EXLIB) && !matches?(negation_of(EXLIB))
|
19
|
-
end
|
20
|
-
|
21
|
-
def kosher?
|
22
|
-
!damaged? && !ex_lib? && !marked? && !missing_volume? && !review_copy?
|
23
|
-
end
|
24
|
-
|
25
|
-
def marked?
|
26
|
-
matches?(MARKED) && !matches?(negation_of(MARKED))
|
27
|
-
end
|
28
|
-
|
29
|
-
def missing_volume?
|
30
|
-
matches? MISSING_VOL
|
31
|
-
end
|
32
|
-
|
33
|
-
def review_copy?
|
34
|
-
matches? REVIEW_COPY
|
35
|
-
end
|
36
|
-
|
37
|
-
private
|
38
|
-
|
39
|
-
def matches?(value)
|
40
|
-
!!text.match(Regexp.new(value, true))
|
41
|
-
end
|
42
|
-
|
43
|
-
def negation_of(value)
|
44
|
-
"(?:no|not an?)\\s+#{value}"
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
data/lib/kosher/item.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
module Kosher
|
2
|
-
|
3
|
-
# The actual item offered by a seller.
|
4
|
-
#
|
5
|
-
# An item has a price, quantity, condition, and description.
|
6
|
-
class Item < Structure
|
7
|
-
key :quantity, :type => Integer
|
8
|
-
has_one :price
|
9
|
-
has_one :condition
|
10
|
-
has_one :description
|
11
|
-
|
12
|
-
def kosher?
|
13
|
-
condition.kosher? && description.kosher?
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
data/lib/kosher/location.rb
DELETED
data/lib/kosher/price.rb
DELETED
data/lib/kosher/threshold.rb
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Kosher
|
4
|
-
describe Availability do
|
5
|
-
before do
|
6
|
-
@availability = Availability.new
|
7
|
-
end
|
8
|
-
|
9
|
-
describe "#kosher?" do
|
10
|
-
before do
|
11
|
-
Availability.threshold = 48
|
12
|
-
end
|
13
|
-
|
14
|
-
context "when available within threshold" do
|
15
|
-
before do
|
16
|
-
@availability.hours = 48
|
17
|
-
end
|
18
|
-
|
19
|
-
it "returns true" do
|
20
|
-
@availability.should be_kosher
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
context "when not available within threshold" do
|
25
|
-
before do
|
26
|
-
@availability.hours = 96
|
27
|
-
end
|
28
|
-
|
29
|
-
it "should return false" do
|
30
|
-
@availability.should_not be_kosher
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
context "when availability is not known" do
|
35
|
-
it "should return false" do
|
36
|
-
@availability.should_not be_kosher
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Kosher
|
4
|
-
describe Condition do
|
5
|
-
before do
|
6
|
-
@condition = Condition.new
|
7
|
-
end
|
8
|
-
|
9
|
-
describe "#kosher?" do
|
10
|
-
before do
|
11
|
-
Condition.threshold = 4
|
12
|
-
end
|
13
|
-
|
14
|
-
context "when grade within threshold" do
|
15
|
-
it "returns true" do
|
16
|
-
@condition.grade = 4
|
17
|
-
@condition.should be_kosher
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
context "when grade not within threshold" do
|
22
|
-
it "returns false" do
|
23
|
-
@condition.grade = 5
|
24
|
-
@condition.should_not be_kosher
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
@@ -1,79 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Kosher
|
4
|
-
describe Description do
|
5
|
-
before do
|
6
|
-
@description = Description.new
|
7
|
-
end
|
8
|
-
|
9
|
-
describe "#kosher?" do
|
10
|
-
it "validates a blank description" do
|
11
|
-
@description.text = ''
|
12
|
-
@description.should be_kosher
|
13
|
-
end
|
14
|
-
|
15
|
-
it "validates a non-blank description" do
|
16
|
-
@description.text = 'foo'
|
17
|
-
@description.should be_kosher
|
18
|
-
end
|
19
|
-
|
20
|
-
it "does not validate advance review copies" do
|
21
|
-
@description.text = 'Uncorrected review copy'
|
22
|
-
@description.should_not be_kosher
|
23
|
-
|
24
|
-
@description.text = 'arc'
|
25
|
-
@description.should_not be_kosher
|
26
|
-
|
27
|
-
@description.text = 'arc.'
|
28
|
-
@description.should_not be_kosher
|
29
|
-
|
30
|
-
@description.text = 'marc'
|
31
|
-
@description.should be_kosher
|
32
|
-
end
|
33
|
-
|
34
|
-
it "does not validate marked books" do
|
35
|
-
@description.text = 'Some highlighting'
|
36
|
-
@description.should_not be_kosher
|
37
|
-
|
38
|
-
@description.text = 'Underlining.'
|
39
|
-
@description.should_not be_kosher
|
40
|
-
|
41
|
-
@description.text = 'Good. Hiliting.'
|
42
|
-
@description.should_not be_kosher
|
43
|
-
|
44
|
-
@description.text = 'No highlighting.'
|
45
|
-
@description.should be_kosher
|
46
|
-
end
|
47
|
-
|
48
|
-
it "does not validate books with missing volumes" do
|
49
|
-
@description.text = 'First vol only.'
|
50
|
-
@description.should_not be_kosher
|
51
|
-
end
|
52
|
-
|
53
|
-
it "does not validate damaged or worn books" do
|
54
|
-
@description.text = 'Different'
|
55
|
-
@description.should be_kosher
|
56
|
-
|
57
|
-
@description.text = 'Rental'
|
58
|
-
@description.should_not be_kosher
|
59
|
-
|
60
|
-
@description.text = 'Torn pages'
|
61
|
-
@description.should_not be_kosher
|
62
|
-
end
|
63
|
-
|
64
|
-
it "does not validate withdrawn library copies" do
|
65
|
-
@description.text = 'xlib'
|
66
|
-
@description.should_not be_kosher
|
67
|
-
|
68
|
-
@description.text = 'ex-library'
|
69
|
-
@description.should_not be_kosher
|
70
|
-
|
71
|
-
@description.text = 'retired library copy'
|
72
|
-
@description.should_not be_kosher
|
73
|
-
|
74
|
-
@description.text = 'Not an ex-library'
|
75
|
-
@description.should be_kosher
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
data/spec/kosher/item_spec.rb
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Kosher
|
4
|
-
describe Item do
|
5
|
-
before do
|
6
|
-
@item = Item.new
|
7
|
-
@item.condition = Condition.new(:grade => 1)
|
8
|
-
end
|
9
|
-
|
10
|
-
describe "#kosher?" do
|
11
|
-
context "when condition is kosher" do
|
12
|
-
context "when description is kosher" do
|
13
|
-
before do
|
14
|
-
@item.description = Description.new
|
15
|
-
end
|
16
|
-
|
17
|
-
it "returns true" do
|
18
|
-
@item.should be_kosher
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
context "when description is not kosher" do
|
23
|
-
before do
|
24
|
-
@item.description = Description.new(
|
25
|
-
:text => 'Withdrawn library book')
|
26
|
-
end
|
27
|
-
|
28
|
-
it "returns false" do
|
29
|
-
@item.should_not be_kosher
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
context "when condition is not kosher" do
|
35
|
-
before do
|
36
|
-
@item.condition.grade = 5
|
37
|
-
end
|
38
|
-
|
39
|
-
it "returns false" do
|
40
|
-
@item.should_not be_kosher
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
data/spec/kosher/offer_spec.rb
DELETED
@@ -1,178 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Kosher
|
4
|
-
describe Offer do
|
5
|
-
before do
|
6
|
-
@offer = Offer.new
|
7
|
-
@offer.item = Item.new
|
8
|
-
@offer.seller = Seller.new
|
9
|
-
@offer.shipping = Shipping.new
|
10
|
-
end
|
11
|
-
|
12
|
-
describe "#kosher?" do
|
13
|
-
context "when item is kosher" do
|
14
|
-
before do
|
15
|
-
@offer.item.stub!(:kosher?).and_return(true)
|
16
|
-
end
|
17
|
-
|
18
|
-
context "when seller is kosher" do
|
19
|
-
before do
|
20
|
-
@offer.seller.stub!(:kosher?).and_return(true)
|
21
|
-
end
|
22
|
-
|
23
|
-
context "when shipping is kosher" do
|
24
|
-
before do
|
25
|
-
@offer.shipping.stub!(:kosher?).and_return(true)
|
26
|
-
end
|
27
|
-
|
28
|
-
it "returns true" do
|
29
|
-
@offer.should be_kosher
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
context "when shipping is not kosher" do
|
34
|
-
before do
|
35
|
-
@offer.shipping.stub!(:kosher?).and_return(false)
|
36
|
-
end
|
37
|
-
|
38
|
-
it "returns false" do
|
39
|
-
@offer.should_not be_kosher
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
context "when seller is not kosher" do
|
45
|
-
before do
|
46
|
-
@offer.seller.stub!(:kosher?).and_return(false)
|
47
|
-
end
|
48
|
-
|
49
|
-
it "returns false" do
|
50
|
-
@offer.should_not be_kosher
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
context "when item is not kosher" do
|
56
|
-
before do
|
57
|
-
@offer.item.stub!(:kosher?).and_return(false)
|
58
|
-
end
|
59
|
-
|
60
|
-
it "returns false" do
|
61
|
-
@offer.should_not be_kosher
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
describe "#price" do
|
67
|
-
it "sum of item price and shipping cost" do
|
68
|
-
@offer.item.price = Price.new(cents: 1000, currency: 'EUR')
|
69
|
-
@offer.shipping.cost = Price.new(cents: 399, currency: 'EUR')
|
70
|
-
|
71
|
-
@offer.price.cents.should eql 1399
|
72
|
-
@offer.price.currency.iso_code.should eql 'EUR'
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
describe "#<=>" do
|
77
|
-
before do
|
78
|
-
@another_offer = Offer.new
|
79
|
-
end
|
80
|
-
|
81
|
-
context "when kosher" do
|
82
|
-
before do
|
83
|
-
@offer.stub!(:kosher?).and_return(true)
|
84
|
-
end
|
85
|
-
|
86
|
-
it "is less than a non-kosher offer" do
|
87
|
-
@another_offer.stub!(:kosher?).and_return(false)
|
88
|
-
@offer.should < @another_offer
|
89
|
-
end
|
90
|
-
|
91
|
-
context "when the other offer is kosher as well" do
|
92
|
-
before do
|
93
|
-
@offer.stub!(:price).and_return(Money.new(100, 'EUR'))
|
94
|
-
@another_offer.stub!(:kosher?).and_return(true)
|
95
|
-
end
|
96
|
-
|
97
|
-
context "when it has a lower price" do
|
98
|
-
before do
|
99
|
-
@another_offer.stub!(:price).and_return(Money.new(150, 'EUR'))
|
100
|
-
end
|
101
|
-
|
102
|
-
it "is less than other offer" do
|
103
|
-
@offer.should < @another_offer
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
context "when the prices are equal" do
|
108
|
-
before do
|
109
|
-
@another_offer.stub!(:price).and_return(Money.new(100, 'EUR'))
|
110
|
-
end
|
111
|
-
|
112
|
-
it "is equal to the other offer" do
|
113
|
-
@offer.should <=> @another_offer
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
context "when it has a higher price" do
|
118
|
-
before do
|
119
|
-
@another_offer.stub!(:price).and_return(Money.new(50, 'EUR'))
|
120
|
-
end
|
121
|
-
|
122
|
-
it "is greater than the other offer" do
|
123
|
-
@offer.should > @another_offer
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
context "when not kosher" do
|
130
|
-
before do
|
131
|
-
@offer.stub!(:kosher?).and_return(false)
|
132
|
-
end
|
133
|
-
|
134
|
-
it "is greater than a kosher offer" do
|
135
|
-
@another_offer.stub!(:kosher?).and_return(true)
|
136
|
-
@offer.should > @another_offer
|
137
|
-
end
|
138
|
-
|
139
|
-
context "when the other offer is not kosher either" do
|
140
|
-
before do
|
141
|
-
@offer.stub!(:price).and_return(Money.new(100, 'EUR'))
|
142
|
-
@another_offer.stub!(:kosher?).and_return(false)
|
143
|
-
end
|
144
|
-
|
145
|
-
context "when it has a lower price" do
|
146
|
-
before do
|
147
|
-
@another_offer.stub!(:price).and_return(Money.new(150, 'EUR'))
|
148
|
-
end
|
149
|
-
|
150
|
-
it "is less than the other offer" do
|
151
|
-
@offer.should < @another_offer
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
context "when the prices are equal" do
|
156
|
-
before do
|
157
|
-
@another_offer.stub!(:price).and_return(Money.new(100, 'EUR'))
|
158
|
-
end
|
159
|
-
|
160
|
-
it "is equal to the other offer" do
|
161
|
-
@offer.should <=> @another_offer
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
context "when it has a higher price" do
|
166
|
-
before do
|
167
|
-
@another_offer.stub!(:price).and_return(Money.new(50, 'EUR'))
|
168
|
-
end
|
169
|
-
|
170
|
-
it "is greater than the other offer" do
|
171
|
-
@offer.should > @another_offer
|
172
|
-
end
|
173
|
-
end
|
174
|
-
end
|
175
|
-
end
|
176
|
-
end
|
177
|
-
end
|
178
|
-
end
|
data/spec/kosher/price_spec.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Kosher
|
4
|
-
describe Price do
|
5
|
-
describe "#to_money" do
|
6
|
-
it "returns a Money object" do
|
7
|
-
price = Price.new(:cents => 100, :currency => 'USD')
|
8
|
-
price.to_money.should be_a Money
|
9
|
-
end
|
10
|
-
|
11
|
-
it "raises a type error if cents is nil" do
|
12
|
-
expect { Price.new.to_money }.to raise_error TypeError
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
data/spec/kosher/seller_spec.rb
DELETED
@@ -1,56 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Kosher
|
4
|
-
describe Seller do
|
5
|
-
before do
|
6
|
-
@seller = Seller.new
|
7
|
-
end
|
8
|
-
|
9
|
-
describe "#blacklisted?" do
|
10
|
-
before do
|
11
|
-
Kosher.seller_blacklist << 'foo'
|
12
|
-
end
|
13
|
-
|
14
|
-
it "returns true if the seller is blacklisted" do
|
15
|
-
@seller.id = 'foo'
|
16
|
-
@seller.should be_blacklisted
|
17
|
-
end
|
18
|
-
|
19
|
-
it "returns false if the seller is not blacklisted" do
|
20
|
-
@seller.id = 'bar'
|
21
|
-
@seller.should_not be_blacklisted
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
describe "#kosher?" do
|
26
|
-
before do
|
27
|
-
Seller.threshold = 4.8
|
28
|
-
end
|
29
|
-
|
30
|
-
it "returns true if rating is 0.0" do
|
31
|
-
@seller.rating = 0.0
|
32
|
-
@seller.should be_kosher
|
33
|
-
end
|
34
|
-
|
35
|
-
it "returns true if rating is nil" do
|
36
|
-
@seller.should be_kosher
|
37
|
-
end
|
38
|
-
|
39
|
-
it "returns true if rating is within threshold" do
|
40
|
-
@seller.rating = 4.8
|
41
|
-
@seller.should be_kosher
|
42
|
-
end
|
43
|
-
|
44
|
-
it "returns false if rating is not within threshold" do
|
45
|
-
@seller.rating = 4.7
|
46
|
-
@seller.should_not be_kosher
|
47
|
-
end
|
48
|
-
|
49
|
-
it "returns false if seller is blacklisted" do
|
50
|
-
@seller.id = ['foo']
|
51
|
-
Kosher.seller_blacklist << @seller.id
|
52
|
-
@seller.should_not be_kosher
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Kosher
|
4
|
-
describe Shipping do
|
5
|
-
before do
|
6
|
-
@shipping = Shipping.new
|
7
|
-
end
|
8
|
-
|
9
|
-
describe "#free?" do
|
10
|
-
context "when shipping costs 0" do
|
11
|
-
it "returns true" do
|
12
|
-
@shipping.cost = Price.new(cents: 0)
|
13
|
-
@shipping.should be_free
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
context "when shipping is not free" do
|
18
|
-
it "returns false" do
|
19
|
-
@shipping.cost = Price.new(cents: 1)
|
20
|
-
@shipping.should_not be_free
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
describe "#kosher?" do
|
26
|
-
context "when available" do
|
27
|
-
it "returns true" do
|
28
|
-
@shipping.availability = Availability.new(:hours => 0)
|
29
|
-
@shipping.should be_kosher
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
context "when not available" do
|
34
|
-
it "returns false" do
|
35
|
-
@shipping.availability = Availability.new(:hours => 96)
|
36
|
-
@shipping.should_not be_kosher
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
data/spec/kosher/venue_spec.rb
DELETED
data/spec/kosher_spec.rb
DELETED