double_entry 1.0.1 → 2.0.0.beta5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +497 -0
  3. data/README.md +107 -44
  4. data/double_entry.gemspec +22 -49
  5. data/lib/active_record/locking_extensions.rb +3 -3
  6. data/lib/active_record/locking_extensions/log_subscriber.rb +1 -1
  7. data/lib/double_entry.rb +29 -21
  8. data/lib/double_entry/account.rb +39 -46
  9. data/lib/double_entry/account_balance.rb +20 -3
  10. data/lib/double_entry/balance_calculator.rb +5 -5
  11. data/lib/double_entry/configurable.rb +1 -0
  12. data/lib/double_entry/configuration.rb +8 -2
  13. data/lib/double_entry/errors.rb +13 -13
  14. data/lib/double_entry/line.rb +7 -6
  15. data/lib/double_entry/locking.rb +5 -5
  16. data/lib/double_entry/transfer.rb +37 -30
  17. data/lib/double_entry/validation.rb +1 -0
  18. data/lib/double_entry/validation/account_fixer.rb +36 -0
  19. data/lib/double_entry/validation/line_check.rb +25 -43
  20. data/lib/double_entry/version.rb +1 -1
  21. data/lib/generators/double_entry/install/install_generator.rb +22 -1
  22. data/lib/generators/double_entry/install/templates/initializer.rb +20 -0
  23. data/lib/generators/double_entry/install/templates/migration.rb +45 -55
  24. metadata +35 -256
  25. data/.gitignore +0 -32
  26. data/.rspec +0 -2
  27. data/.travis.yml +0 -29
  28. data/.yardopts +0 -2
  29. data/Gemfile +0 -2
  30. data/Rakefile +0 -15
  31. data/lib/double_entry/reporting.rb +0 -181
  32. data/lib/double_entry/reporting/aggregate.rb +0 -110
  33. data/lib/double_entry/reporting/aggregate_array.rb +0 -76
  34. data/lib/double_entry/reporting/day_range.rb +0 -42
  35. data/lib/double_entry/reporting/hour_range.rb +0 -45
  36. data/lib/double_entry/reporting/line_aggregate.rb +0 -16
  37. data/lib/double_entry/reporting/line_aggregate_filter.rb +0 -79
  38. data/lib/double_entry/reporting/month_range.rb +0 -94
  39. data/lib/double_entry/reporting/time_range.rb +0 -59
  40. data/lib/double_entry/reporting/time_range_array.rb +0 -49
  41. data/lib/double_entry/reporting/week_range.rb +0 -107
  42. data/lib/double_entry/reporting/year_range.rb +0 -40
  43. data/script/jack_hammer +0 -210
  44. data/script/setup.sh +0 -8
  45. data/spec/active_record/locking_extensions_spec.rb +0 -110
  46. data/spec/double_entry/account_balance_spec.rb +0 -7
  47. data/spec/double_entry/account_spec.rb +0 -130
  48. data/spec/double_entry/balance_calculator_spec.rb +0 -88
  49. data/spec/double_entry/configuration_spec.rb +0 -50
  50. data/spec/double_entry/line_spec.rb +0 -80
  51. data/spec/double_entry/locking_spec.rb +0 -214
  52. data/spec/double_entry/performance/double_entry_performance_spec.rb +0 -32
  53. data/spec/double_entry/performance/reporting/aggregate_performance_spec.rb +0 -50
  54. data/spec/double_entry/reporting/aggregate_array_spec.rb +0 -123
  55. data/spec/double_entry/reporting/aggregate_spec.rb +0 -205
  56. data/spec/double_entry/reporting/line_aggregate_filter_spec.rb +0 -90
  57. data/spec/double_entry/reporting/line_aggregate_spec.rb +0 -39
  58. data/spec/double_entry/reporting/month_range_spec.rb +0 -139
  59. data/spec/double_entry/reporting/time_range_array_spec.rb +0 -169
  60. data/spec/double_entry/reporting/time_range_spec.rb +0 -45
  61. data/spec/double_entry/reporting/week_range_spec.rb +0 -103
  62. data/spec/double_entry/reporting_spec.rb +0 -181
  63. data/spec/double_entry/transfer_spec.rb +0 -93
  64. data/spec/double_entry/validation/line_check_spec.rb +0 -99
  65. data/spec/double_entry_spec.rb +0 -428
  66. data/spec/generators/double_entry/install/install_generator_spec.rb +0 -30
  67. data/spec/spec_helper.rb +0 -118
  68. data/spec/support/accounts.rb +0 -21
  69. data/spec/support/blueprints.rb +0 -43
  70. data/spec/support/database.example.yml +0 -21
  71. data/spec/support/database.travis.yml +0 -24
  72. data/spec/support/double_entry_spec_helper.rb +0 -27
  73. data/spec/support/gemfiles/Gemfile.rails-3.2.x +0 -8
  74. data/spec/support/gemfiles/Gemfile.rails-4.1.x +0 -6
  75. data/spec/support/gemfiles/Gemfile.rails-4.2.x +0 -5
  76. data/spec/support/gemfiles/Gemfile.rails-5.0.x +0 -5
  77. data/spec/support/performance_helper.rb +0 -26
  78. data/spec/support/reporting_configuration.rb +0 -6
  79. data/spec/support/schema.rb +0 -74
data/README.md CHANGED
@@ -3,8 +3,8 @@
3
3
 
4
4
  [![License MIT](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://github.com/envato/double_entry/blob/master/LICENSE.md)
5
5
  [![Gem Version](https://badge.fury.io/rb/double_entry.svg)](http://badge.fury.io/rb/double_entry)
6
- [![Build Status](https://travis-ci.org/envato/double_entry.svg?branch=1-stable)](https://travis-ci.org/envato/double_entry)
7
- [![Code Climate](https://codeclimate.com/github/envato/double_entry.png)](https://codeclimate.com/github/envato/double_entry)
6
+ [![Build Status](https://travis-ci.org/envato/double_entry.svg?branch=master)](https://travis-ci.org/envato/double_entry)
7
+ [![Code Climate](https://codeclimate.com/github/envato/double_entry/badges/gpa.svg)](https://codeclimate.com/github/envato/double_entry)
8
8
 
9
9
  ![Show me the Money](http://24.media.tumblr.com/tumblr_m3bwbqNJIG1rrgbmqo1_500.gif)
10
10
 
@@ -22,15 +22,18 @@ DoubleEntry uses the [Money gem](https://github.com/RubyMoney/money) to encapsul
22
22
  DoubleEntry is tested against:
23
23
 
24
24
  Ruby
25
- * 2.1.x
26
- * 2.2.x
27
25
  * 2.3.x
26
+ * 2.4.x
27
+ * 2.5.x
28
+ * 2.6.x
29
+ * 2.7.x
28
30
 
29
31
  Rails
30
- * 3.2.x
31
- * 4.1.x
32
32
  * 4.2.x
33
33
  * 5.0.x
34
+ * 5.1.x
35
+ * 5.2.x
36
+ * 6.0.x
34
37
 
35
38
  Databases
36
39
  * MySQL
@@ -53,6 +56,8 @@ bundle
53
56
 
54
57
  Generate Rails schema migrations for the required tables:
55
58
 
59
+ > The default behavior is to store metadata in a json(b) column rather than a separate `double_entry_line_metadata` table. If you would like the old (1.x) behavior, you can add `--no-json-metadata`.
60
+
56
61
  ```sh
57
62
  rails generate double_entry:install
58
63
  ```
@@ -67,7 +72,7 @@ rake db:migrate
67
72
  ## Interface
68
73
 
69
74
  The entire API for recording financial transactions is available through a few
70
- methods in the **DoubleEntry** module. For full details on
75
+ methods in the [DoubleEntry](lib/double_entry.rb) module. For full details on
71
76
  what the API provides, please view the documentation on these methods.
72
77
 
73
78
  A configuration file should be used to define a set of accounts, and potential
@@ -88,12 +93,12 @@ than scoped accounts due to lock contention.
88
93
  To get a particular account:
89
94
 
90
95
  ```ruby
91
- account = DoubleEntry.account(:spending, :scope => user)
96
+ account = DoubleEntry.account(:spending, scope: user)
92
97
  ```
93
98
 
94
99
  (This actually returns an Account::Instance object.)
95
100
 
96
- See **DoubleEntry::Account** for more info.
101
+ See [DoubleEntry::Account](lib/double_entry/account.rb) for more info.
97
102
 
98
103
 
99
104
  ### Balances
@@ -114,15 +119,15 @@ To transfer money between accounts:
114
119
  ```ruby
115
120
  DoubleEntry.transfer(
116
121
  Money.new(20_00),
117
- :from => one_account,
118
- :to => another_account,
119
- :code => :a_business_code_for_this_type_of_transfer,
122
+ from: one_account,
123
+ to: another_account,
124
+ code: :a_business_code_for_this_type_of_transfer,
120
125
  )
121
126
  ```
122
127
 
123
128
  The possible transfers, and their codes, should be defined in the configuration.
124
129
 
125
- See **DoubleEntry::Transfer** for more info.
130
+ See [DoubleEntry::Transfer](lib/double_entry/transfer.rb) for more info.
126
131
 
127
132
  ### Metadata
128
133
 
@@ -131,10 +136,10 @@ You may associate arbitrary metadata with transfers, for example:
131
136
  ```ruby
132
137
  DoubleEntry.transfer(
133
138
  Money.new(20_00),
134
- :from => one_account,
135
- :to => another_account,
136
- :code => :a_business_code_for_this_type_of_transfer,
137
- :metadata => {:key1 => 'value 1', :key2 => 'value 2'},
139
+ from: one_account,
140
+ to: another_account,
141
+ code: :a_business_code_for_this_type_of_transfer,
142
+ metadata: {key1: ['value 1', 'value 2'], key2: 'value 3'},
138
143
  )
139
144
  ```
140
145
 
@@ -147,7 +152,7 @@ manually lock the accounts you're using:
147
152
  ```ruby
148
153
  DoubleEntry.lock_accounts(account_a, account_b) do
149
154
  # Perhaps transfer some money
150
- DoubleEntry.transfer(Money.new(20_00), :from => account_a, :to => account_b, :code => :purchase)
155
+ DoubleEntry.transfer(Money.new(20_00), from: account_a, to: account_b, code: :purchase)
151
156
  # Perform other tasks that should be commited atomically with the transfer of funds...
152
157
  end
153
158
  ```
@@ -155,8 +160,23 @@ end
155
160
  The lock_accounts call generates a database transaction, which must be the
156
161
  outermost transaction.
157
162
 
158
- See **DoubleEntry::Locking** for more info.
163
+ See [DoubleEntry::Locking](lib/double_entry/locking.rb) for more info.
164
+
165
+ ### Account Checker/Fixer
166
+
167
+ Although it's unlikely, DoubleEntry has tools for checking accounts to make sure they tie out, and optionally fixing them if there is a discrepancy. It's recommended to run this in a scheduled job, somewhere on the order of hourly to daily, depending on transaction volume. Keep in mind that this process locks accounts as it inspects their balances, so it will have an prevent new transactions from being written for a short time.
159
168
 
169
+ Here are examples that could go in your scheduled job, depending on your needs:
170
+
171
+ ```ruby
172
+ # Check all accounts & write the results to the double_entry_line_checks table
173
+ DoubleEntry::Validation::LineCheck.perform!
174
+
175
+ # Check & fix accounts (results will also be written to the table)
176
+ DoubleEntry::Validation::LineCheck.perform!(fixer: DoubleEntry::Validation::AccountFixer.new)
177
+ ```
178
+
179
+ See [DoubleEntry::Validation](lib/double_entry/validation) for more info.
160
180
 
161
181
  ## Implementation
162
182
 
@@ -168,13 +188,12 @@ Lines table entries also store the running balance for the account. To retrieve
168
188
  the current balance for an account, we find the most recent lines table entry
169
189
  for it.
170
190
 
171
- See **DoubleEntry::Line** for more info.
191
+ See [DoubleEntry::Line](lib/double_entry/line.rb) for more info.
172
192
 
173
193
  AccountBalance records cache the current balance for each Account, and are used
174
194
  to perform database level locking.
175
195
 
176
- Transfer metadata is stored as key/value pairs associated with both the source and destination lines of the transfer.
177
- See **DoubleEntry::LineMetadata** for more info.
196
+ Transfer metadata is stored in a json(b) column on both the source and destination lines of the transfer.
178
197
 
179
198
  ## Configuration
180
199
 
@@ -182,7 +201,7 @@ A configuration file should be used to define a set of accounts, optional scopes
182
201
  the accounts, and permitted transfers between those accounts.
183
202
 
184
203
  The configuration file should be kept in your application's load path. For example,
185
- *config/initializers/double_entry.rb*
204
+ *config/initializers/double_entry.rb*. By default, this file will be created when you run the installer, but you will need to fill out your accounts.
186
205
 
187
206
  For example, the following specifies two accounts, savings and checking.
188
207
  Each account is scoped by User (where User is an object with an ID), meaning
@@ -194,15 +213,21 @@ This configuration also specifies that money can be transferred between the two
194
213
  require 'double_entry'
195
214
 
196
215
  DoubleEntry.configure do |config|
216
+ # Use json(b) column in double_entry_lines table to store metadata instead of separate metadata table
217
+ config.json_metadata = true
218
+
197
219
  config.define_accounts do |accounts|
198
- user_scope = accounts.active_record_scope_identifier(User)
199
- accounts.define(:identifier => :savings, :scope_identifier => user_scope, :positive_only => true)
200
- accounts.define(:identifier => :checking, :scope_identifier => user_scope)
220
+ user_scope = ->(user) do
221
+ raise 'not a User' unless user.class.name == 'User'
222
+ user.id
223
+ end
224
+ accounts.define(identifier: :savings, scope_identifier: user_scope, positive_only: true)
225
+ accounts.define(identifier: :checking, scope_identifier: user_scope)
201
226
  end
202
227
 
203
228
  config.define_transfers do |transfers|
204
- transfers.define(:from => :checking, :to => :savings, :code => :deposit)
205
- transfers.define(:from => :savings, :to => :checking, :code => :withdraw)
229
+ transfers.define(from: :checking, to: :savings, code: :deposit)
230
+ transfers.define(from: :savings, to: :checking, code: :withdraw)
206
231
  end
207
232
  end
208
233
  ```
@@ -215,7 +240,7 @@ Transfers between accounts of different currencies are not allowed.
215
240
  ```ruby
216
241
  DoubleEntry.configure do |config|
217
242
  config.define_accounts do |accounts|
218
- accounts.define(:identifier => :savings, :scope_identifier => user_scope, :currency => :aud)
243
+ accounts.define(identifier: :savings, scope_identifier: user_scope, currency: 'AUD')
219
244
  end
220
245
  end
221
246
  ```
@@ -267,40 +292,78 @@ See the Github project [issues](https://github.com/envato/double_entry/issues).
267
292
 
268
293
  ## Development Environment Setup
269
294
 
295
+ We're using Docker to provide a convenient and consistent environment for
296
+ executing tests during development. This allows engineers to quickly set up
297
+ a productive development environment.
298
+
299
+ Note: Most development files are mounted in the Docker container. This
300
+ enables engineers to edit files in their favourite editor (on the host
301
+ OS) and have the changes immediately available in the Docker container
302
+ to be exercised.
303
+
304
+ One exception to this is the RSpec configuration. Changes to these files will
305
+ require a rebuild of the Docker image (step 2).
306
+
307
+ Prerequisites:
308
+
309
+ * Docker
310
+ * Docker Compose
311
+ * Git
312
+
270
313
  1. Clone this repo.
271
314
 
272
315
  ```sh
273
316
  git clone git@github.com:envato/double_entry.git && cd double_entry
274
317
  ```
275
318
 
276
- 2. Run the included setup script to install the gem dependencies.
319
+ 2. Build the Docker image we'll use to run tests
277
320
 
278
321
  ```sh
279
- ./script/setup.sh
322
+ docker-compose build --pull double_entry
280
323
  ```
281
324
 
282
- 3. Install MySQL, PostgreSQL and SQLite. We run tests against all three databases.
283
- 4. Create a database in MySQL.
325
+ 3. Startup a container and attach a terminal. This will also start up a
326
+ MySQL and Postgres database.
284
327
 
285
328
  ```sh
286
- mysql -u root -e 'create database double_entry_test;'
329
+ docker-compose run --rm double_entry ash
287
330
  ```
288
331
 
289
- 5. Create a database in PostgreSQL.
332
+ 4. Run the tests
290
333
 
291
334
  ```sh
292
- psql -c 'create database double_entry_test;' -U postgres
335
+ DB=mysql bundle exec rspec
336
+ DB=postgres bundle exec rspec
337
+ DB=sqlite bundle exec rspec
293
338
  ```
294
339
 
295
- 6. Specify how the tests should connect to the database
340
+ 5. When finished, exit the container terminal and shut down the databases.
296
341
 
297
342
  ```sh
298
- cp spec/support/{database.example.yml,database.yml}
299
- vim spec/support/database.yml
343
+ exit
344
+ docker-compose down
300
345
  ```
301
346
 
302
- 7. Run the tests
303
-
304
- ```sh
305
- bundle exec rake
306
- ```
347
+ ## Contributors
348
+
349
+ Many thanks to those who have contributed to both this gem, and the library upon which it was based, over the years:
350
+ * Anthony Sellitti - @asellitt
351
+ * Clinton Forbes - @clinton
352
+ * Eaden McKee - @eadz
353
+ * Giancarlo Salamanca - @salamagd
354
+ * Jiexin Huang - @jiexinhuang
355
+ * Keith Pitt - @keithpitt
356
+ * Kelsey Hannan - @KelseyDH
357
+ * Mark Turnley - @rabidcarrot
358
+ * Martin Jagusch - @MJIO
359
+ * Martin Spickermann - @spickermann
360
+ * Mary-Anne Cosgrove - @macosgrove
361
+ * Orien Madgwick - @orien
362
+ * Pete Yandall - @notahat
363
+ * Rizal Muthi - @rizalmuthi
364
+ * Ryan Allen - @ryan-allen
365
+ * Samuel Cochran - @sj26
366
+ * Stefan Wrobel - @swrobel
367
+ * Stephanie Staub - @stephnacios
368
+ * Trung Lê - @joneslee85
369
+ * Vahid Ta'eed - @vahid
data/double_entry.gemspec CHANGED
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
@@ -7,67 +7,40 @@ require 'double_entry/version'
7
7
  Gem::Specification.new do |gem|
8
8
  gem.name = 'double_entry'
9
9
  gem.version = DoubleEntry::VERSION
10
- gem.authors = ['Anthony Sellitti', 'Keith Pitt', 'Martin Jagusch', 'Martin Spickermann', 'Mark Turnley', 'Orien Madgwick', 'Pete Yandall', 'Stephanie Staub', 'Giancarlo Salamanca']
11
- gem.email = ['anthony.sellitti@envato.com', 'me@keithpitt.com', '_@mj.io', 'spickemann@gmail.com', 'mark@envato.com', '_@orien.io', 'pete@envato.com', 'staub.steph@gmail.com', 'giancarlo@salamanca.net.au']
10
+ gem.authors = ['Envato']
11
+ gem.email = ['rubygems@envato.com']
12
12
  gem.summary = 'Tools to build your double entry financial ledger'
13
13
  gem.homepage = 'https://github.com/envato/double_entry'
14
-
15
- gem.files = `git ls-files`.split($/)
16
- gem.executables = gem.files.grep(%r{bin/}).map { |f| File.basename(f) }
17
- gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.license = 'MIT'
15
+
16
+ gem.metadata = {
17
+ 'bug_tracker_uri' => 'https://github.com/envato/double_entry/issues',
18
+ 'changelog_uri' => "https://github.com/envato/double_entry/blob/v#{gem.version}/CHANGELOG.md",
19
+ 'documentation_uri' => "https://www.rubydoc.info/gems/double_entry/#{gem.version}",
20
+ 'source_code_uri' => "https://github.com/envato/double_entry/tree/v#{gem.version}",
21
+ }
22
+
23
+ gem.files = `git ls-files -z`.split("\x0").select do |f|
24
+ f.match(%r{^(?:double_entry.gemspec|README|LICENSE|CHANGELOG|lib/)})
25
+ end
18
26
  gem.require_paths = ['lib']
27
+ gem.required_ruby_version = '>= 2.3.0'
19
28
 
20
- gem.post_install_message = <<-'POSTINSTALLMESSAGE'
21
- Please note the following changes in DoubleEntry:
22
- - New table `double_entry_line_metadata` has been introduced and is *required* for
23
- aggregate reporting filtering to work. Existing applications must manually manage
24
- this change via a migration similar to the following:
25
-
26
- class CreateDoubleEntryLineMetadata < ActiveRecord::Migration
27
- def self.up
28
- create_table "#{DoubleEntry.table_name_prefix}line_metadata", :force => true do |t|
29
- t.integer "line_id", :null => false
30
- t.string "key", :limit => 48, :null => false
31
- t.string "value", :limit => 64, :null => false
32
- t.timestamps :null => false
33
- end
34
-
35
- add_index "#{DoubleEntry.table_name_prefix}line_metadata",
36
- ["line_id", "key", "value"],
37
- :name => "lines_meta_line_id_key_value_idx"
38
- end
39
-
40
- def self.down
41
- drop_table "#{DoubleEntry.table_name_prefix}line_metadata"
42
- end
43
- end
44
-
45
- Please ensure that you update your database accordingly.
46
- POSTINSTALLMESSAGE
47
-
48
- gem.add_dependency 'money', '>= 6.0.0'
49
29
  gem.add_dependency 'activerecord', '>= 3.2.0'
50
30
  gem.add_dependency 'activesupport', '>= 3.2.0'
31
+ gem.add_dependency 'money', '>= 6.0.0'
51
32
  gem.add_dependency 'railties', '>= 3.2.0'
52
33
 
53
- gem.add_development_dependency 'rake'
54
34
  gem.add_development_dependency 'mysql2'
55
35
  gem.add_development_dependency 'pg'
36
+ gem.add_development_dependency 'rake'
56
37
  gem.add_development_dependency 'sqlite3'
57
38
 
58
- gem.add_development_dependency 'rspec'
59
- gem.add_development_dependency 'rspec-its'
60
- gem.add_development_dependency 'rspec-instafail'
61
39
  gem.add_development_dependency 'database_cleaner'
40
+ gem.add_development_dependency 'factory_bot'
62
41
  gem.add_development_dependency 'generator_spec'
63
- gem.add_development_dependency 'machinist'
64
- gem.add_development_dependency 'timecop'
65
- gem.add_development_dependency 'test-unit'
66
-
67
- gem.add_development_dependency 'pry'
68
- gem.add_development_dependency 'pry-doc'
69
- gem.add_development_dependency 'pry-byebug' if RUBY_VERSION >= '2.0.0'
70
- gem.add_development_dependency 'pry-stack_explorer'
71
- gem.add_development_dependency 'awesome_print'
42
+ gem.add_development_dependency 'rspec'
43
+ gem.add_development_dependency 'rspec-its'
72
44
  gem.add_development_dependency 'ruby-prof'
45
+ gem.add_development_dependency 'timecop'
73
46
  end
@@ -18,7 +18,7 @@ module ActiveRecord
18
18
  yield
19
19
  rescue ActiveRecord::StatementInvalid => exception
20
20
  if exception.message =~ /deadlock/i || exception.message =~ /database is locked/i
21
- ActiveSupport::Notifications.publish('deadlock_restart.active_record', :exception => exception)
21
+ ActiveSupport::Notifications.publish('deadlock_restart.double_entry', exception: exception)
22
22
 
23
23
  raise ActiveRecord::RestartTransaction
24
24
  else
@@ -46,7 +46,7 @@ module ActiveRecord
46
46
  yield
47
47
  rescue ActiveRecord::StatementInvalid, ActiveRecord::RecordNotUnique => exception
48
48
  if exception.message =~ /duplicate/i || exception.message =~ /ConstraintException/
49
- ActiveSupport::Notifications.publish('duplicate_ignore.active_record', :exception => exception)
49
+ ActiveSupport::Notifications.publish('duplicate_ignore.double_entry', exception: exception)
50
50
 
51
51
  # Just ignore it...someone else has already created the record.
52
52
  else
@@ -63,7 +63,7 @@ module ActiveRecord
63
63
  if exception.message =~ /deadlock/i || exception.message =~ /database is locked/i
64
64
  # Somebody else is in the midst of creating the record. We'd better
65
65
  # retry, so we ensure they're done before we move on.
66
- ActiveSupport::Notifications.publish('deadlock_retry.active_record', :exception => exception)
66
+ ActiveSupport::Notifications.publish('deadlock_retry.double_entry', exception: exception)
67
67
 
68
68
  retry
69
69
  else
@@ -26,4 +26,4 @@ module ActiveRecord
26
26
  end
27
27
  end
28
28
 
29
- ActiveRecord::LockingExtensions::LogSubscriber.attach_to :active_record
29
+ ActiveRecord::LockingExtensions::LogSubscriber.attach_to :double_entry
data/lib/double_entry.rb CHANGED
@@ -4,6 +4,7 @@ require 'active_record/locking_extensions'
4
4
  require 'active_record/locking_extensions/log_subscriber'
5
5
  require 'active_support/all'
6
6
  require 'money'
7
+ require 'rails/railtie'
7
8
 
8
9
  require 'double_entry/version'
9
10
  require 'double_entry/errors'
@@ -14,9 +15,6 @@ require 'double_entry/account_balance'
14
15
  require 'double_entry/balance_calculator'
15
16
  require 'double_entry/locking'
16
17
  require 'double_entry/transfer'
17
- require 'double_entry/line'
18
- require 'double_entry/line_metadata'
19
- require 'double_entry/reporting'
20
18
  require 'double_entry/validation'
21
19
 
22
20
  # Keep track of all the monies!
@@ -24,6 +22,16 @@ require 'double_entry/validation'
24
22
  # This module provides the public interfaces for everything to do with
25
23
  # transferring money around the system.
26
24
  module DoubleEntry
25
+ class Railtie < ::Rails::Railtie
26
+ # So we can access user config from initializer in their app
27
+ config.after_initialize do
28
+ unless DoubleEntry.config.json_metadata
29
+ require 'double_entry/line_metadata'
30
+ end
31
+ require 'double_entry/line'
32
+ end
33
+ end
34
+
27
35
  class << self
28
36
  # Get the particular account instance with the provided identifier and
29
37
  # scope.
@@ -58,9 +66,9 @@ module DoubleEntry
58
66
  # savings_account = DoubleEntry.account(:savings, scope: user)
59
67
  # DoubleEntry.transfer(
60
68
  # 20.dollars,
61
- # :from => checking_account,
62
- # :to => savings_account,
63
- # :code => :save,
69
+ # from: checking_account,
70
+ # to: savings_account,
71
+ # code: :save,
64
72
  # )
65
73
  # @param [Money] amount The quantity of money to transfer from one account
66
74
  # to the other.
@@ -83,35 +91,35 @@ module DoubleEntry
83
91
  # Get the current or historic balance of an account.
84
92
  #
85
93
  # @example Obtain the current balance of my checking account
86
- # checking_account = DoubleEntry.account(:checking, :scope => user)
94
+ # checking_account = DoubleEntry.account(:checking, scope: user)
87
95
  # DoubleEntry.balance(checking_account)
88
96
  # @example Obtain the current balance of my checking account (without account or user model)
89
- # DoubleEntry.balance(:checking, :scope => user_id)
97
+ # DoubleEntry.balance(:checking, scope: user_id)
90
98
  # @example Obtain a historic balance of my checking account
91
- # checking_account = DoubleEntry.account(:checking, :scope => user)
92
- # DoubleEntry.balance(checking_account, :at => Time.new(2012, 1, 1))
99
+ # checking_account = DoubleEntry.account(:checking, scope: user)
100
+ # DoubleEntry.balance(checking_account, at: Time.new(2012, 1, 1))
93
101
  # @example Obtain the net balance of my checking account during may
94
- # checking_account = DoubleEntry.account(:checking, :scope => user)
102
+ # checking_account = DoubleEntry.account(:checking, scope: user)
95
103
  # DoubleEntry.balance(
96
104
  # checking_account,
97
- # :from => Time.new(2012, 5, 1, 0, 0, 0),
98
- # :to => Time.new(2012, 5, 31, 23, 59, 59),
105
+ # from: Time.new(2012, 5, 1, 0, 0, 0),
106
+ # to: Time.new(2012, 5, 31, 23, 59, 59),
99
107
  # )
100
108
  # @example Obtain the balance of salary deposits made to my checking account during may
101
- # checking_account = DoubleEntry.account(:checking, :scope => user)
109
+ # checking_account = DoubleEntry.account(:checking, scope: user)
102
110
  # DoubleEntry.balance(
103
111
  # checking_account,
104
- # :code => :salary,
105
- # :from => Time.new(2012, 5, 1, 0, 0, 0),
106
- # :to => Time.new(2012, 5, 31, 23, 59, 59),
112
+ # code: :salary,
113
+ # from: Time.new(2012, 5, 1, 0, 0, 0),
114
+ # to: Time.new(2012, 5, 31, 23, 59, 59),
107
115
  # )
108
116
  # @example Obtain the balance of salary & lottery deposits made to my checking account during may
109
- # checking_account = DoubleEntry.account(:checking, :scope => user)
117
+ # checking_account = DoubleEntry.account(:checking, scope: user)
110
118
  # DoubleEntry.balance(
111
119
  # checking_account,
112
- # :codes => [ :salary, :lottery ],
113
- # :from => Time.new(2012, 5, 1, 0, 0, 0),
114
- # :to => Time.new(2012, 5, 31, 23, 59, 59),
120
+ # codes: [ :salary, :lottery ],
121
+ # from: Time.new(2012, 5, 1, 0, 0, 0),
122
+ # to: Time.new(2012, 5, 31, 23, 59, 59),
115
123
  # )
116
124
  # @param [DoubleEntry::Account:Instance, Symbol] account Find the balance
117
125
  # for this account