bitex_bot 0.0.3 → 0.0.4

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.
@@ -1,5 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'bitex_bot'
3
+ require "bitex_bot/settings"
4
+ BitexBot::Settings.load_default
4
5
 
6
+ require 'bitex_bot'
5
7
  BitexBot::Robot.run!
@@ -26,8 +26,7 @@ Gem::Specification.new do |spec|
26
26
  spec.add_dependency "activesupport"
27
27
  spec.add_dependency "sqlite3"
28
28
  spec.add_dependency "bitstamp"
29
- spec.add_dependency "bitex"
30
- spec.add_dependency "debugger"
29
+ spec.add_dependency "bitex", "0.0.8"
31
30
  spec.add_dependency "mail"
32
31
 
33
32
  spec.add_development_dependency "bundler", "~> 1.3"
@@ -37,5 +36,6 @@ Gem::Specification.new do |spec|
37
36
  spec.add_development_dependency "database_cleaner"
38
37
  spec.add_development_dependency "factory_girl"
39
38
  spec.add_development_dependency "timecop"
39
+ spec.add_development_dependency "debugger"
40
40
  spec.add_development_dependency "shoulda-matchers"
41
41
  end
@@ -8,7 +8,6 @@ require "bitex"
8
8
  require "bitstamp"
9
9
  require "bitex_bot/settings"
10
10
  require "bitex_bot/database"
11
- require "debugger"
12
11
  require "bitex_bot/models/opening_flow.rb"
13
12
  require "bitex_bot/models/closing_flow.rb"
14
13
  Dir[File.dirname(__FILE__) + '/bitex_bot/models/*.rb'].each {|file| require file }
@@ -1,3 +1,4 @@
1
+ require 'debugger'
1
2
  module BitexBot
2
3
  module Database
3
4
  #ActiveRecord::Base.logger = Logger.new(File.open('database.log', 'w'))
@@ -74,10 +74,6 @@ module BitexBot
74
74
  def self.get_remote_value_to_use(value_to_use_needed, safest_price)
75
75
  value_to_use_needed / safest_price
76
76
  end
77
-
78
- def self.order_is_executing?(order)
79
- order.status != :executing && order.remaining_amount == order.amount
80
- end
81
77
 
82
78
  def self.get_bitex_price(usd_to_spend, bitcoin_to_resell)
83
79
  (usd_to_spend / bitcoin_to_resell) * (1 - Settings.buying.profit / 100.0)
@@ -55,14 +55,21 @@ module BitexBot
55
55
 
56
56
  bitex_price = get_bitex_price(value_to_use, remote_value_to_use)
57
57
 
58
- order = order_class.create!(:btc, value_to_use, bitex_price, true)
59
- if order_is_executing?(order)
58
+ begin
59
+ order = order_class.create!(:btc, value_to_use, bitex_price, true)
60
+ rescue StandardError => e
61
+ raise CannotCreateFlow.new(e.message)
62
+ end
63
+
64
+ if order.reason == :not_enough_funds
60
65
  raise CannotCreateFlow.new(
61
66
  "You need to have #{value_to_use} on bitex to place this
62
67
  #{order_class.name}.")
63
68
  end
69
+
64
70
  Robot.logger.info("Opening: Placed #{order_class.name} ##{order.id} " \
65
71
  "#{value_to_use} @ $#{bitex_price} (#{remote_value_to_use})")
72
+
66
73
  begin
67
74
  self.create!(price: bitex_price, value_to_use: value_to_use,
68
75
  suggested_closing_price: safest_price, status: 'executing', order_id: order.id)
@@ -94,7 +101,7 @@ module BitexBot
94
101
 
95
102
  def finalise!
96
103
  order = self.class.order_class.find(order_id)
97
- if order.nil?
104
+ if order.status == :cancelled
98
105
  Robot.logger.info(
99
106
  "Opening: #{self.class.order_class.name} ##{order_id} was too old.")
100
107
  self.status = 'finalised'
@@ -71,10 +71,6 @@ module BitexBot
71
71
  value_to_use_needed * safest_price
72
72
  end
73
73
 
74
- def self.order_is_executing?(order)
75
- order.status != :executing && order.remaining_quantity == order.quantity
76
- end
77
-
78
74
  def self.get_bitex_price(btc_to_sell, usd_to_spend_re_buying)
79
75
  (usd_to_spend_re_buying / btc_to_sell) * (1 + Settings.selling.profit / 100.0)
80
76
  end
@@ -1,13 +1,19 @@
1
1
  require 'settingslogic'
2
- require 'debugger'
2
+
3
3
  class BitexBot::Settings < Settingslogic
4
- path = ARGV[0] || File.expand_path('bitex_bot_settings.yml', Dir.pwd)
5
- unless FileTest.exists?(path)
6
- sample_path = File.expand_path('../../../settings.yml.sample', __FILE__)
7
- FileUtils.cp(sample_path, path)
8
- puts "No settings found, I've created a new one with sample "\
9
- "values at #{path}. Please go ahead and edit it before running this again."
10
- exit 1
4
+ def self.load_default
5
+ path = ARGV[0] || File.expand_path('bitex_bot_settings.yml', Dir.pwd)
6
+ unless FileTest.exists?(path)
7
+ sample_path = File.expand_path('../../../settings.yml.sample', __FILE__)
8
+ FileUtils.cp(sample_path, path)
9
+ puts "No settings found, I've created a new one with sample "\
10
+ "values at #{path}. Please go ahead and edit it before running this again."
11
+ exit 1
12
+ end
13
+ source path
14
+ end
15
+
16
+ def self.load_test
17
+ source File.expand_path('../../../settings.yml.sample', __FILE__)
11
18
  end
12
- source path
13
19
  end
@@ -1,3 +1,3 @@
1
1
  module BitexBot
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -61,11 +61,11 @@ describe BitexBot::BuyClosingFlow do
61
61
  stub_bitstamp_orders_into_transactions
62
62
  flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
63
63
  close = flow.close_positions.last
64
- close.amount.should == 624.1
64
+ close.amount.should == '624.1000000044'.to_d
65
65
  close.quantity.should == 2.01
66
66
  flow.should be_done
67
67
  flow.btc_profit.should == 0
68
- flow.usd_profit.should == 20.1
68
+ flow.usd_profit.should == '20.1000000044'.to_d
69
69
  end
70
70
 
71
71
  it "retries closing at a lower price every minute" do
@@ -97,7 +97,7 @@ describe BitexBot::BuyClosingFlow do
97
97
  flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
98
98
  end.to change{ BitexBot::CloseBuy.count }.by(1)
99
99
  flow.close_positions.first.tap do |close|
100
- close.amount.should == 312.05
100
+ close.amount.should == '312.0500000022'.to_d
101
101
  close.quantity.should == 1.005
102
102
  end
103
103
 
@@ -106,12 +106,12 @@ describe BitexBot::BuyClosingFlow do
106
106
  stub_bitstamp_orders_into_transactions
107
107
  flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
108
108
  flow.close_positions.last.tap do |close|
109
- close.amount.should == 312.0299
109
+ close.amount.should == '312.0299000022'.to_d
110
110
  close.quantity.should == 1.005
111
111
  end
112
112
  flow.should be_done
113
113
  flow.btc_profit.should == 0
114
- flow.usd_profit.should == 20.0799
114
+ flow.usd_profit.should == '20.0799000044001'.to_d
115
115
  end
116
116
 
117
117
  it "does not retry for an amount less than minimum_for_closing" do
@@ -126,7 +126,7 @@ describe BitexBot::BuyClosingFlow do
126
126
 
127
127
  flow.should be_done
128
128
  flow.btc_profit.should == 0.00201
129
- flow.usd_profit.should == 19.4759
129
+ flow.usd_profit.should == '19.4759000043956'.to_d
130
130
  end
131
131
 
132
132
  it "can lose USD if price had to be dropped dramatically" do
@@ -144,7 +144,7 @@ describe BitexBot::BuyClosingFlow do
144
144
 
145
145
  flow.reload.should be_done
146
146
  flow.btc_profit.should == 0
147
- flow.usd_profit.should == -16.08
147
+ flow.usd_profit.should == '-16.0799999956'.to_d
148
148
  end
149
149
  end
150
150
  end
@@ -14,7 +14,7 @@ describe BitexBot::BuyOpeningFlow do
14
14
 
15
15
  describe "when creating a buying flow" do
16
16
  it "spends 50 usd" do
17
- stub_bitex_bid_create
17
+ stub_bitex_orders
18
18
  BitexBot::Settings.stub(time_to_live: 3,
19
19
  buying: double(amount_to_spend_per_order: 50, profit: 0))
20
20
 
@@ -29,7 +29,7 @@ describe BitexBot::BuyOpeningFlow do
29
29
  end
30
30
 
31
31
  it "spends 100 usd" do
32
- stub_bitex_bid_create
32
+ stub_bitex_orders
33
33
  BitexBot::Settings.stub(time_to_live: 3,
34
34
  buying: double(amount_to_spend_per_order: 100, profit: 0))
35
35
 
@@ -43,7 +43,7 @@ describe BitexBot::BuyOpeningFlow do
43
43
  end
44
44
 
45
45
  it "lowers the price to pay on bitex to take a profit" do
46
- stub_bitex_bid_create
46
+ stub_bitex_orders
47
47
  BitexBot::Settings.stub(time_to_live: 3,
48
48
  buying: double(amount_to_spend_per_order: 100, profit: 50))
49
49
 
@@ -73,7 +73,7 @@ describe BitexBot::BuyOpeningFlow do
73
73
  end
74
74
 
75
75
  it "fails when there are not enough bitcoin to sell in the other exchange" do
76
- stub_bitex_bid_create
76
+ stub_bitex_orders
77
77
  BitexBot::Settings.stub(time_to_live: 3,
78
78
  buying: double(amount_to_spend_per_order: 100, profit: 0))
79
79
 
@@ -136,7 +136,7 @@ describe BitexBot::BuyOpeningFlow do
136
136
  end
137
137
 
138
138
  it 'cancels the associated bitex bid' do
139
- stub_bitex_bid_create
139
+ stub_bitex_orders
140
140
  BitexBot::Settings.stub(time_to_live: 3,
141
141
  buying: double(amount_to_spend_per_order: 50, profit: 0))
142
142
 
@@ -146,9 +146,6 @@ describe BitexBot::BuyOpeningFlow do
146
146
  flow.finalise!
147
147
  flow.should be_settling
148
148
  flow.finalise!
149
- flow.should be_settling
150
- Bitex::Order.stub(active: [])
151
- flow.finalise!
152
149
  flow.should be_finalised
153
150
  end
154
151
  end
@@ -19,8 +19,7 @@ describe BitexBot::Robot do
19
19
  )
20
20
  Bitex.api_key = "valid_key"
21
21
  Bitex::Profile.stub(get: {fee: 0.5})
22
- stub_bitex_bid_create
23
- stub_bitex_ask_create
22
+ stub_bitex_orders
24
23
  stub_bitstamp_sell
25
24
  stub_bitstamp_buy
26
25
  stub_bitstamp_balance
@@ -31,6 +30,7 @@ describe BitexBot::Robot do
31
30
  let(:bot){ BitexBot::Robot.new }
32
31
 
33
32
  it 'Starts out by creating opening flows that timeout' do
33
+ stub_bitex_orders
34
34
  bot.trade!
35
35
  stub_bitex_transactions
36
36
  buying = BitexBot::BuyOpeningFlow.last
@@ -42,7 +42,6 @@ describe BitexBot::Robot do
42
42
  buying.reload.should be_settling
43
43
  selling.reload.should be_settling
44
44
 
45
- Bitex::Order.stub(active: [])
46
45
  bot.trade!
47
46
  buying.reload.should be_finalised
48
47
  selling.reload.should be_finalised
@@ -59,10 +58,15 @@ describe BitexBot::Robot do
59
58
  bot.trade!
60
59
  BitexBot::BuyOpeningFlow.active.count.should == 2
61
60
 
61
+ # When transactions appear, all opening flows
62
+ # should get old and die.
63
+ # We stub our finder to make it so all orders
64
+ # have been successfully cancelled.
62
65
  stub_bitex_transactions
63
- Bitex::Order.stub(active: [])
66
+
64
67
  Timecop.travel 5.seconds.from_now
65
68
  bot.trade!
69
+ bot.trade!
66
70
  BitexBot::BuyOpeningFlow.active.count.should == 1
67
71
  Timecop.travel 5.seconds.from_now
68
72
  bot.trade!
@@ -72,13 +76,13 @@ describe BitexBot::Robot do
72
76
  it 'does not place new opening flows until all closing flows are done' do
73
77
  bot.trade!
74
78
  stub_bitex_transactions
75
- Bitex::Order.stub(active: [])
76
79
  expect do
77
80
  bot.trade!
78
81
  end.to change{ BitexBot::BuyClosingFlow.count }.by(1)
79
82
 
80
83
  Timecop.travel 15.seconds.from_now
81
84
  bot.trade!
85
+ bot.trade!
82
86
  bot.should be_active_closing_flows
83
87
  bot.should_not be_active_opening_flows
84
88
 
@@ -63,11 +63,11 @@ describe BitexBot::SellClosingFlow do
63
63
  stub_bitstamp_orders_into_transactions
64
64
  flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
65
65
  close = flow.close_positions.last
66
- close.amount.should == 583.9
66
+ close.amount.should == "583.9000000044".to_d
67
67
  close.quantity.should == 2.01
68
68
  flow.should be_done
69
69
  flow.btc_profit.should == 0
70
- flow.usd_profit.should == 20.1
70
+ flow.usd_profit.should == "20.0999999956".to_d
71
71
  end
72
72
 
73
73
  it "retries closing at a higher price every minute" do
@@ -99,7 +99,7 @@ describe BitexBot::SellClosingFlow do
99
99
  flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
100
100
  end.to change{ BitexBot::CloseSell.count }.by(1)
101
101
  flow.close_positions.first.tap do |close|
102
- close.amount.should == 291.95
102
+ close.amount.should == "291.9500000022".to_d
103
103
  close.quantity.should == 1.005
104
104
  end
105
105
 
@@ -108,12 +108,12 @@ describe BitexBot::SellClosingFlow do
108
108
  stub_bitstamp_orders_into_transactions
109
109
  flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
110
110
  flow.close_positions.last.tap do |close|
111
- close.amount.should == 291.95
112
- close.quantity.should == '1.004930813120933'.to_d
111
+ close.amount.should == "291.9499990955143".to_d
112
+ close.quantity.should == '1.00493081'.to_d
113
113
  end
114
114
  flow.should be_done
115
- flow.btc_profit.should == '-0.000069186879067'.to_d
116
- flow.usd_profit.should == 20.1
115
+ flow.btc_profit.should == '-0.00006919'.to_d
116
+ flow.usd_profit.should == '20.1000009022857'.to_d
117
117
  end
118
118
 
119
119
  it "does not retry for an amount less than minimum_for_closing" do
@@ -132,8 +132,8 @@ describe BitexBot::SellClosingFlow do
132
132
  end.not_to change{ BitexBot::CloseSell.count }
133
133
 
134
134
  flow.should be_done
135
- flow.btc_profit.should == '-0.015739962920125'.to_d
136
- flow.usd_profit.should == '20.6839'.to_d
135
+ flow.btc_profit.should == '-0.01573996629'.to_d
136
+ flow.usd_profit.should == '20.6839009813144'.to_d
137
137
  end
138
138
 
139
139
  it "can lose BTC if price had to be raised dramatically" do
@@ -150,11 +150,11 @@ describe BitexBot::SellClosingFlow do
150
150
  flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
151
151
 
152
152
  flow.reload.should be_done
153
- flow.btc_profit.should == "-0.117278093149271".to_d
154
- flow.usd_profit.should == "20.1".to_d
153
+ flow.btc_profit.should == "-0.11727809".to_d
154
+ flow.usd_profit.should == "20.0999990243145".to_d
155
155
  close = flow.close_positions.last
156
156
  (close.amount / close.quantity)
157
- .should == '308.497512437810935201007569945345172662'.to_d
157
+ .should == '308.497512439999968088286144476448735145'.to_d
158
158
  end
159
159
  end
160
160
  end
@@ -14,7 +14,7 @@ describe BitexBot::SellOpeningFlow do
14
14
 
15
15
  describe "when creating a selling flow" do
16
16
  it "sells 2 bitcoin" do
17
- stub_bitex_ask_create
17
+ stub_bitex_orders
18
18
  BitexBot::Settings.stub(time_to_live: 3,
19
19
  selling: double(quantity_to_sell_per_order: 2, profit: 0))
20
20
 
@@ -29,7 +29,7 @@ describe BitexBot::SellOpeningFlow do
29
29
  end
30
30
 
31
31
  it "sells 4 bitcoin" do
32
- stub_bitex_ask_create
32
+ stub_bitex_orders
33
33
  BitexBot::Settings.stub(time_to_live: 3,
34
34
  selling: double(quantity_to_sell_per_order: 4, profit: 0))
35
35
 
@@ -44,7 +44,7 @@ describe BitexBot::SellOpeningFlow do
44
44
  end
45
45
 
46
46
  it "raises the price to charge on bitex to take a profit" do
47
- stub_bitex_ask_create
47
+ stub_bitex_orders
48
48
  BitexBot::Settings.stub(time_to_live: 3,
49
49
  selling: double(quantity_to_sell_per_order: 4, profit: 50))
50
50
 
@@ -75,7 +75,7 @@ describe BitexBot::SellOpeningFlow do
75
75
  end
76
76
 
77
77
  it "fails when there are not enough USD to re-buy in the other exchange" do
78
- stub_bitex_bid_create
78
+ stub_bitex_orders
79
79
  BitexBot::Settings.stub(time_to_live: 3,
80
80
  selling: double(quantity_to_sell_per_order: 4, profit: 50))
81
81
 
@@ -138,7 +138,7 @@ describe BitexBot::SellOpeningFlow do
138
138
  end
139
139
 
140
140
  it 'cancels the associated bitex bid' do
141
- stub_bitex_ask_create
141
+ stub_bitex_orders
142
142
  BitexBot::Settings.stub(time_to_live: 3,
143
143
  selling: double(quantity_to_sell_per_order: 4, profit: 50))
144
144
 
@@ -148,9 +148,6 @@ describe BitexBot::SellOpeningFlow do
148
148
  flow.finalise!
149
149
  flow.should be_settling
150
150
  flow.finalise!
151
- flow.should be_settling
152
- Bitex::Order.stub(active: [])
153
- flow.finalise!
154
151
  flow.should be_finalised
155
152
  end
156
153
  end
@@ -1,6 +1,8 @@
1
1
  require 'bundler/setup'
2
2
  Bundler.setup
3
3
 
4
+ require "bitex_bot/settings"
5
+ BitexBot::Settings.load_test
4
6
  require 'bitex_bot'
5
7
  require 'factory_girl'
6
8
  require 'database_cleaner'
@@ -1,14 +1,22 @@
1
1
  module BitexStubs
2
- def ensure_bitex_orders_stub
3
- begin
4
- Bitex::Order.active
5
- rescue Exception => e
6
- Bitex::Order.stub(active: [])
2
+ mattr_accessor(:bids){ {} }
3
+ mattr_accessor(:asks){ {} }
4
+ mattr_accessor(:active_bids){ {} }
5
+ mattr_accessor(:active_asks){ {} }
6
+
7
+ def stub_bitex_orders
8
+ Bitex::Order.stub(:all) do
9
+ BitexStubs.active_bids + BitexStubs.active_asks
10
+ end
11
+
12
+ Bitex::Bid.stub(:find) do |id|
13
+ BitexStubs.bids[id]
14
+ end
15
+
16
+ Bitex::Ask.stub(:find) do |id|
17
+ BitexStubs.asks[id]
7
18
  end
8
- end
9
19
 
10
- def stub_bitex_bid_create
11
- ensure_bitex_orders_stub
12
20
  Bitex::Bid.stub(:create!) do |specie, to_spend, price|
13
21
  bid = Bitex::Bid.new
14
22
  bid.id = 12345
@@ -18,17 +26,16 @@ module BitexStubs
18
26
  bid.remaining_amount = to_spend
19
27
  bid.status = :executing
20
28
  bid.specie = specie
21
- bid.stub(cancel!: true) do
22
- bid.status = :cancelling
29
+ bid.stub(:cancel!) do
30
+ bid.status = :cancelled
31
+ BitexStubs.active_bids.delete(bid.id)
23
32
  bid
24
33
  end
25
- Bitex::Order.stub(active: Bitex::Order.active + [bid])
34
+ BitexStubs.bids[bid.id] = bid
35
+ BitexStubs.active_bids[bid.id] = bid
26
36
  bid
27
37
  end
28
- end
29
38
 
30
- def stub_bitex_ask_create
31
- ensure_bitex_orders_stub
32
39
  Bitex::Ask.stub(:create!) do |specie, to_sell, price|
33
40
  ask = Bitex::Ask.new
34
41
  ask.id = 12345
@@ -38,16 +45,17 @@ module BitexStubs
38
45
  ask.remaining_quantity = to_sell
39
46
  ask.status = :executing
40
47
  ask.specie = specie
41
- ask.stub(cancel!: true) do
42
- ask.status = :cancelling
48
+ ask.stub(:cancel!) do
49
+ ask.status = :cancelled
50
+ BitexStubs.active_asks.delete(ask.id)
43
51
  ask
44
52
  end
45
- Bitex::Order.stub(active: Bitex::Order.active + [ask])
53
+ BitexStubs.asks[ask.id] = ask
54
+ BitexStubs.active_asks[ask.id] = ask
46
55
  ask
47
56
  end
48
57
  end
49
58
 
50
-
51
59
  def stub_bitex_transactions(*extra_transactions)
52
60
  Bitex::Transaction.stub(all: extra_transactions + [
53
61
  build(:bitex_buy),
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bitex_bot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2014-07-18 00:00:00.000000000 Z
13
+ date: 2014-07-31 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: settingslogic
@@ -97,33 +97,17 @@ dependencies:
97
97
  requirement: !ruby/object:Gem::Requirement
98
98
  none: false
99
99
  requirements:
100
- - - ! '>='
101
- - !ruby/object:Gem::Version
102
- version: '0'
103
- type: :runtime
104
- prerelease: false
105
- version_requirements: !ruby/object:Gem::Requirement
106
- none: false
107
- requirements:
108
- - - ! '>='
100
+ - - '='
109
101
  - !ruby/object:Gem::Version
110
- version: '0'
111
- - !ruby/object:Gem::Dependency
112
- name: debugger
113
- requirement: !ruby/object:Gem::Requirement
114
- none: false
115
- requirements:
116
- - - ! '>='
117
- - !ruby/object:Gem::Version
118
- version: '0'
102
+ version: 0.0.8
119
103
  type: :runtime
120
104
  prerelease: false
121
105
  version_requirements: !ruby/object:Gem::Requirement
122
106
  none: false
123
107
  requirements:
124
- - - ! '>='
108
+ - - '='
125
109
  - !ruby/object:Gem::Version
126
- version: '0'
110
+ version: 0.0.8
127
111
  - !ruby/object:Gem::Dependency
128
112
  name: mail
129
113
  requirement: !ruby/object:Gem::Requirement
@@ -252,6 +236,22 @@ dependencies:
252
236
  - - ! '>='
253
237
  - !ruby/object:Gem::Version
254
238
  version: '0'
239
+ - !ruby/object:Gem::Dependency
240
+ name: debugger
241
+ requirement: !ruby/object:Gem::Requirement
242
+ none: false
243
+ requirements:
244
+ - - ! '>='
245
+ - !ruby/object:Gem::Version
246
+ version: '0'
247
+ type: :development
248
+ prerelease: false
249
+ version_requirements: !ruby/object:Gem::Requirement
250
+ none: false
251
+ requirements:
252
+ - - ! '>='
253
+ - !ruby/object:Gem::Version
254
+ version: '0'
255
255
  - !ruby/object:Gem::Dependency
256
256
  name: shoulda-matchers
257
257
  requirement: !ruby/object:Gem::Requirement