stocktrade-money-rails 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. data/CHANGELOG.md +60 -0
  2. data/LICENSE +22 -0
  3. data/README.md +359 -0
  4. data/Rakefile +60 -0
  5. data/lib/generators/money_rails/initializer_generator.rb +15 -0
  6. data/lib/generators/templates/money.rb +41 -0
  7. data/lib/money-rails.rb +12 -0
  8. data/lib/money-rails/active_model/validator.rb +37 -0
  9. data/lib/money-rails/active_record/monetizable.rb +138 -0
  10. data/lib/money-rails/configuration.rb +47 -0
  11. data/lib/money-rails/helpers/action_view_extension.rb +36 -0
  12. data/lib/money-rails/hooks.rb +30 -0
  13. data/lib/money-rails/mongoid/three.rb +42 -0
  14. data/lib/money-rails/mongoid/two.rb +25 -0
  15. data/lib/money-rails/railtie.rb +7 -0
  16. data/lib/money-rails/version.rb +3 -0
  17. data/money-rails.gemspec +30 -0
  18. data/spec/active_record/monetizable_spec.rb +308 -0
  19. data/spec/configuration_spec.rb +20 -0
  20. data/spec/dummy/README.rdoc +261 -0
  21. data/spec/dummy/Rakefile +7 -0
  22. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  23. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  24. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  25. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  26. data/spec/dummy/app/models/dummy_product.rb +10 -0
  27. data/spec/dummy/app/models/priceable.rb +7 -0
  28. data/spec/dummy/app/models/product.rb +26 -0
  29. data/spec/dummy/app/models/service.rb +8 -0
  30. data/spec/dummy/app/models/transaction.rb +13 -0
  31. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  32. data/spec/dummy/config.ru +4 -0
  33. data/spec/dummy/config/application.rb +61 -0
  34. data/spec/dummy/config/boot.rb +10 -0
  35. data/spec/dummy/config/database.yml +25 -0
  36. data/spec/dummy/config/environment.rb +5 -0
  37. data/spec/dummy/config/environments/development.rb +37 -0
  38. data/spec/dummy/config/environments/production.rb +67 -0
  39. data/spec/dummy/config/environments/test.rb +37 -0
  40. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  41. data/spec/dummy/config/initializers/inflections.rb +15 -0
  42. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  43. data/spec/dummy/config/initializers/money.rb +31 -0
  44. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  45. data/spec/dummy/config/initializers/session_store.rb +8 -0
  46. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  47. data/spec/dummy/config/locales/en.yml +5 -0
  48. data/spec/dummy/config/mongoid.yml +23 -0
  49. data/spec/dummy/config/routes.rb +3 -0
  50. data/spec/dummy/db/development.sqlite3 +0 -0
  51. data/spec/dummy/db/migrate/20120331190108_create_products.rb +10 -0
  52. data/spec/dummy/db/migrate/20120402080348_add_bonus_cents_to_product.rb +6 -0
  53. data/spec/dummy/db/migrate/20120524052716_create_services.rb +10 -0
  54. data/spec/dummy/db/migrate/20120528181002_create_transactions.rb +11 -0
  55. data/spec/dummy/db/migrate/20120528210103_create_dummy_products.rb +10 -0
  56. data/spec/dummy/db/migrate/20120607210247_add_column_that_allows_nil.rb +5 -0
  57. data/spec/dummy/db/migrate/20120712202655_add_sale_price_cents_to_product.rb +7 -0
  58. data/spec/dummy/db/schema.rb +49 -0
  59. data/spec/dummy/db/structure.sql +17 -0
  60. data/spec/dummy/db/test.sqlite3 +0 -0
  61. data/spec/dummy/public/404.html +26 -0
  62. data/spec/dummy/public/422.html +26 -0
  63. data/spec/dummy/public/500.html +25 -0
  64. data/spec/dummy/public/favicon.ico +0 -0
  65. data/spec/dummy/script/rails +6 -0
  66. data/spec/helpers/action_view_extension_spec.rb +38 -0
  67. data/spec/helpers/form_helper_spec.rb +19 -0
  68. data/spec/mongoid/three_spec.rb +31 -0
  69. data/spec/mongoid/two_spec.rb +25 -0
  70. data/spec/spec_helper.rb +19 -0
  71. data/spec/support/database_cleaner.rb +14 -0
  72. metadata +272 -0
@@ -0,0 +1,60 @@
1
+ # Changelog
2
+
3
+ ## 0.7.0 (coming soon)
4
+ - Added custom validator for Money fields (GH-36)
5
+ TODO: decouple validator from active_record
6
+ - Added mongodb service test support for travis CI
7
+ - Fixed issue with current value assignment in text_field tags (GH-37)
8
+ - Fixed issue related to symbolized keys in Mongoid (GH-40)
9
+
10
+ ## 0.6.0
11
+ - Added basic support for Mongoid >= 3.0.
12
+ - Allow class methods to be monetized (ActiveRecord only - GH-34)
13
+
14
+ ## 0.5.0
15
+
16
+ - Refactored instance currency implementation. Now, instance currency
17
+ is permitted to override the field currency, if they are both non-nil
18
+ values. (GH-23)
19
+ - Replaced deprecated composed_of with a custom implementation for
20
+ activerecord. (GH-20)
21
+ - Refactored testing structure to support multiple ORMs/ODMS.
22
+ - Added Mongoid 2.x basic support. It uses serialization
23
+ (a differrent approach than activerecord for now). (GH-19)
24
+
25
+ ## 0.4.0
26
+
27
+ - Provide ActionView helpers integration.
28
+ - Map blank value assignments (for monetized fields) to nil.
29
+ - Allow nil values for monetized fields. (GH-15)
30
+ - Reworked support for ORM adaptation. (GH-16)
31
+
32
+ ## 0.3.1
33
+
34
+ - Fix bug with string assignment to monetized field. (GH-11)
35
+
36
+ ## 0.3.0
37
+
38
+ - Add support for model-wise currency.
39
+ - Fix conversion of monetized attribute value, whether a currency
40
+ table column exists or not.
41
+ - Add configuration options for currency exchange (config.add_rate,
42
+ config.default_bank)
43
+
44
+ ## 0.2.0
45
+
46
+ - Add new generator to install money.rb initializer
47
+ - Create a structure to enable better ORM/ODM integration
48
+ - Add configuration for numericality validation of monetized fields
49
+ - Add support for custom currency registration
50
+
51
+ ## 0.1.0
52
+
53
+ - Use better names for args :target_name, :field_currency,
54
+ :model_currency. From now on, :as, :with_currency and :with_model_currency should
55
+ be used instead of the old ones which are deprecated. (GH-6)
56
+
57
+ ## 0.0.1
58
+
59
+ - Hello World
60
+
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Andreas Loupasakis
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,359 @@
1
+ # RubyMoney - Money-Rails [![endorse](http://api.coderwall.com/alup/endorsecount.png)](http://coderwall.com/alup)
2
+
3
+ [![Build Status](https://secure.travis-ci.org/RubyMoney/money-rails.png?branch=master)](http://travis-ci.org/RubyMoney/money-rails)
4
+ [![Dependency Status](https://gemnasium.com/RubyMoney/money-rails.png)](https://gemnasium.com/RubyMoney/money-rails)
5
+ [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/RubyMoney/money-rails)
6
+
7
+ ## Introduction
8
+
9
+ This library provides integration of [money](http://github.com/Rubymoney/money) gem with Rails.
10
+
11
+ Use 'monetize' to specify which fields you want to be backed by
12
+ Money objects and helpers provided by the [money](http://github.com/Rubymoney/money)
13
+ gem.
14
+
15
+ Currently, this library is in active development mode, so if you would
16
+ like to have a new feature feel free to open a new issue
17
+ [here](https://github.com/RubyMoney/money-rails/issues). You are also
18
+ welcome to contribute to the project.
19
+
20
+ ## Installation
21
+
22
+ Add this line to your application's Gemfile:
23
+
24
+ gem 'money-rails'
25
+
26
+ And then execute:
27
+
28
+ $ bundle
29
+
30
+ Or install it yourself as:
31
+
32
+ $ gem install money-rails
33
+
34
+ You may also install money configuration initializer:
35
+
36
+ ```
37
+ $ rails g money_rails:initializer
38
+ ```
39
+
40
+ There, you can define the default currency value and set other
41
+ configuration parameters for the rails app.
42
+
43
+ ## Usage
44
+
45
+ ### ActiveRecord
46
+
47
+ For example, we create a Product model which has an integer price_cents column
48
+ and we want to handle it by using a Money object instead:
49
+
50
+ ```ruby
51
+ class Product < ActiveRecord::Base
52
+
53
+ monetize :price_cents
54
+
55
+ end
56
+ ```
57
+
58
+ Now each Product object will also have an attribute called ```price``` which
59
+ is a Money object and can be used for money comparisons, conversions etc.
60
+
61
+ In this case the name of the money attribute is created automagically by removing the
62
+ ```_cents``` suffix of the column name.
63
+
64
+ If you are using another db column name or you prefer another name for the
65
+ money attribute, then you can provide ```as``` argument with a string
66
+ value to the ```monetize``` macro:
67
+
68
+ ```ruby
69
+ monetize :discount_subunit, :as => "discount"
70
+ ```
71
+
72
+ Now the model objects will have a ```discount``` attribute which
73
+ is a Money object, wrapping the value of ```discount_subunit``` column to a
74
+ Money instance.
75
+
76
+ #### Allow nil values
77
+
78
+ If you want to allow the assignment of nil and/or blank values to a specific
79
+ monetized field, you can use the `:allow_nil` parameter like this:
80
+
81
+ ```
82
+ # in Product model
83
+ monetize :optional_price_cents, :allow_nil => true
84
+
85
+ # then blank assignments are permitted
86
+ product.optional_price = nil
87
+ product.save # returns without errors
88
+ product.optional_price # => nil
89
+ product.optional_price_cents # => nil
90
+ ```
91
+
92
+ ### Mongoid 2.x and 3.x
93
+
94
+ `Money` is available as a field type to supply during a field definition:
95
+
96
+ ```ruby
97
+ class Product
98
+ include Mongoid::Document
99
+
100
+ field :price, type: Money
101
+ end
102
+
103
+ obj = Product.new
104
+ # => #<Product _id: 4fe865699671383656000001, _type: nil, price: nil>
105
+
106
+ obj.price
107
+ # => nil
108
+
109
+ obj.price = Money.new(100, 'EUR')
110
+ # => #<Money cents:100 currency:EUR>
111
+
112
+ obj.price
113
+ #=> #<Money cents:100 currency:EUR>
114
+
115
+ obj.save
116
+ # => true
117
+
118
+ obj
119
+ # => #<Product _id: 4fe865699671383656000001, _type: nil, price: {:cents=>100, :currency_iso=>"EUR"}>
120
+
121
+ obj.price
122
+ #=> #<Money cents:100 currency:EUR>
123
+
124
+ ## You can access the money hash too :
125
+ obj[:price]
126
+ # => {:cents=>100, :currency_iso=>"EUR"}
127
+ ```
128
+
129
+ The usual options on `field` as `index`, `default`, ..., are available.
130
+
131
+ ### Method conversion
132
+
133
+ Method return values can be converted in the same way attributes are converted. For example:
134
+
135
+ ```ruby
136
+ class Transaction < ActiveRecord::Base
137
+
138
+ monetize :price_cents
139
+ monetize :tax_cents
140
+ monetize :total_cents
141
+ def total_cents
142
+ return price_cents + tax_cents
143
+ end
144
+
145
+ end
146
+ ```
147
+
148
+ Now each Transaction object has a method called `total` which returns a Money object.
149
+
150
+ ### Currencies
151
+
152
+ Money-rails supports a set of options to handle currencies for your
153
+ monetized fields. The default option for every conversion is to use
154
+ the global default currency of Money library, as given in the configuration
155
+ initializer of money-rails:
156
+
157
+ ```ruby
158
+ # config/initializers/money.rb
159
+ MoneyRails.configure do |config|
160
+
161
+ # set the default currency
162
+ config.default_currency = :usd
163
+
164
+ end
165
+ ```
166
+
167
+ In many cases this is not enough, so there are some other options to
168
+ satisfy your needs.
169
+
170
+ #### Model Currency
171
+
172
+ You can define a specific currency for an activerecord model (not for mongoid).
173
+ This currency is used for the creation and conversions of the Money objects
174
+ referring to every monetized attributes of the specific model.
175
+ This means it overrides the global default currency of Money library.
176
+ To attach a currency to a model use the ```register_currency``` macro:
177
+
178
+ ```ruby
179
+ # app/models/product.rb
180
+ class Product < ActiveRecord::Base
181
+
182
+ # Use EUR as model level currency
183
+ register_currency :eur
184
+
185
+ monetize :discount_subunit, :as => "discount"
186
+ monetize :bonus_cents
187
+
188
+ end
189
+ ```
190
+
191
+ Now ```product.discount``` and ```product.bonus``` will return a Money
192
+ object using EUR as currency, instead of the default USD.
193
+
194
+ #### Attribute Currency (:with_currency)
195
+
196
+ By using the key ```:with_currency``` with a currency symbol value in
197
+ the ```monetize``` macro call, you can define a currency in a more
198
+ granular way. This way you attach a currency only to the specific monetized
199
+ model attribute. It also allows to override both the model level
200
+ and the global default currency:
201
+
202
+ ```ruby
203
+ # app/models/product.rb
204
+ class Product < ActiveRecord::Base
205
+
206
+ # Use EUR as model level currency
207
+ register_currency :eur
208
+
209
+ monetize :discount_subunit, :as => "discount"
210
+ monetize :bonus_cents, :with_currency => :gbp
211
+
212
+ end
213
+ ```
214
+
215
+ In this case the ```product.bonus``` will return a Money object of GBP
216
+ currency, whereas ```product.discount.currency_as_string # => EUR ```
217
+
218
+ #### Instance Currencies
219
+
220
+ All the previous options do not require any extra model field to hold
221
+ currency values. If you need to provide differrent currency per model
222
+ instance, then you need to add a column with the name ```currency```
223
+ in your db table. Money-rails will discover this automatically,
224
+ and will use this knowledge to override the model level and global
225
+ default values. Non-nil instance currency values also override attribute
226
+ currency values, so they have the highest precedence.
227
+
228
+ ```ruby
229
+ class Transaction < ActiveRecord::Base
230
+
231
+ # This model has a separate currency column
232
+ attr_accessible :amount_cents, :currency, :tax_cents
233
+
234
+ # Use model level currency
235
+ register_currency :gbp
236
+
237
+ monetize :amount_cents
238
+ monetize :tax_cents
239
+
240
+ end
241
+
242
+ # Now instantiating with a specific currency overrides
243
+ # the model and global currencies
244
+ t = Transaction.new(:amount_cents => 2500, :currency => "CAD")
245
+ t.amount == Money.new(2500, "CAD") # true
246
+ ```
247
+
248
+ ### Configuration parameters
249
+
250
+ You can handle a bunch of configuration params through ```money.rb``` initializer:
251
+
252
+ ```
253
+ MoneyRails.configure do |config|
254
+
255
+ # To set the default currency
256
+ #
257
+ config.default_currency = :usd
258
+
259
+ # Add custom exchange rates
260
+ config.add_rate "USD", "CAD", 1.24515
261
+ config.add_rate "CAD", "USD", 0.803115
262
+
263
+ # To handle the inclusion of validations for monetized fields
264
+ # The default value is true
265
+ #
266
+ config.include_validations = true
267
+
268
+ # Register a custom currency
269
+ #
270
+ # config.register_currency = {
271
+ # :priority => 1,
272
+ # :iso_code => "EU4",
273
+ # :name => "Euro with subunit of 4 digits",
274
+ # :symbol => "€",
275
+ # :symbol_first => true,
276
+ # :subunit => "Subcent",
277
+ # :subunit_to_unit => 10000,
278
+ # :thousands_separator => ".",
279
+ # :decimal_mark => ","
280
+ # }
281
+ end
282
+ ```
283
+
284
+ * ```default_currecy```: Set the default (application wide) currency (USD is the default)
285
+ * ```include_validations```: Permit the inclusion of a ```validates_numericality_of```
286
+ validation for each monetized field (the default is true)
287
+ * ```register_currency```: Register one custom currency. This option can be
288
+ used more than once to set more custom currencies. The value should be
289
+ a hash of all the necessary key/value pairs (important keys: ```:priority```, ```:iso_code```,
290
+ ```:name```, ```:symbol```, ```:symbol_first```, ```:subunit```, ```:subunit_to_unit```,
291
+ ```:thousands_separator```, ```:decimal_mark```).
292
+ * ```add_rate```: Provide custom exchange rate for currencies in one direction
293
+ only! This rate is added to the attached bank object.
294
+ * ```default_bank```: The default bank object holding exchange rates etc.
295
+ (https://github.com/RubyMoney/money#currency-exchange)
296
+
297
+ ### Helpers
298
+
299
+ * the `currency_symbol` helper method
300
+
301
+ ```
302
+ <%= currency_symbol %>
303
+ ```
304
+ This will render a `span` dom element with the default currency symbol.
305
+
306
+ * the `humanized_money` helper method
307
+
308
+ ```
309
+ <%= humanized_money @money_object %>
310
+ ```
311
+ This will render a formatted money value without the currency symbol and
312
+ without the cents part if it contains only zeros (uses
313
+ `:no_cents_fi_whole flag`).
314
+
315
+ * humanize with symbol helper
316
+
317
+ ```
318
+ <%= humanized_money_with_symbol @money_object %>
319
+ ```
320
+ This will render a formatted money value including the currency symbol and
321
+ without the cents part if it contains only zeros.
322
+
323
+ * get the money value without the cents part
324
+
325
+ ```
326
+ <%= money_without_cents @money_object %>
327
+ ```
328
+ This will render a formatted money value without the currency symbol and
329
+ without the cents part.
330
+
331
+ * get the money value without the cents part and including the currency
332
+ symbol
333
+
334
+ ```
335
+ <%= money_without_cents_and_with_symbol @money_object %>
336
+ ```
337
+ This will render a formatted money value including the currency symbol and
338
+ without the cents part.
339
+
340
+ ## Supported ORMs/ODMs
341
+
342
+ * ActiveRecord (>= 3.x)
343
+ * Mongoid (2.x, 3.x)
344
+
345
+ ## Supported Ruby interpreters
346
+
347
+ * MRI Ruby >= 1.8.7
348
+
349
+ You can see a full list of the currently supported interpreters in [travis.yml](http://github.com/RubyMoney/money-rails/blob/master/.travis.yml)
350
+
351
+ ## Maintainers
352
+
353
+ * Andreas Loupasakis (https://github.com/alup)
354
+ * Shane Emmons (https://github.com/semmons99)
355
+ * Simone Carletti (https://github.com/weppos)
356
+
357
+ ## License
358
+
359
+ MIT License. Copyright 2012 RubyMoney.
@@ -0,0 +1,60 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+
6
+ begin
7
+ Bundler.setup(:default, :development)
8
+ rescue Bundler::BundlerError => e
9
+ $stderr.puts e.message
10
+ $stderr.puts "Run `bundle install` to install missing gems"
11
+ exit e.status_code
12
+ end
13
+
14
+ require 'rake'
15
+ require 'rspec/core/rake_task'
16
+
17
+ RSpec::Core::RakeTask.new
18
+
19
+ task :default => "spec:all"
20
+ task :test => :spec
21
+
22
+ namespace :spec do
23
+ desc "Run Tests against mongoid (version 3)"
24
+ task :mongoid3 do
25
+ sh "BUNDLE_GEMFILE='gemfiles/mongoid3.gemfile' bundle --quiet"
26
+ sh "BUNDLE_GEMFILE='gemfiles/mongoid3.gemfile' bundle exec rake -t spec"
27
+ end
28
+
29
+ desc "Run Tests against mongoid (version 2)"
30
+ task :mongoid2 do
31
+ sh "BUNDLE_GEMFILE='gemfiles/mongoid2.gemfile' bundle --quiet"
32
+ sh "BUNDLE_GEMFILE='gemfiles/mongoid2.gemfile' bundle exec rake -t spec"
33
+ end
34
+
35
+ desc "Run Tests against activerecord"
36
+ task :activerecord do
37
+ sh "bundle --quiet"
38
+ sh "bundle exec rake -t spec"
39
+ end
40
+
41
+ desc "Run Tests against all ORMs"
42
+ task :all do
43
+ # Mongoid 3
44
+ sh "BUNDLE_GEMFILE='gemfiles/mongoid3.gemfile' bundle --quiet"
45
+ sh "BUNDLE_GEMFILE='gemfiles/mongoid3.gemfile' bundle exec rake -t spec"
46
+
47
+ # Mongoid 2
48
+ sh "BUNDLE_GEMFILE='gemfiles/mongoid2.gemfile' bundle --quiet"
49
+ sh "BUNDLE_GEMFILE='gemfiles/mongoid2.gemfile' bundle exec rake -t spec"
50
+
51
+ # ActiveRecord
52
+ sh "bundle --quiet"
53
+ sh "bundle exec rake -t spec"
54
+ end
55
+ end
56
+
57
+ desc "Update AUTHORS file"
58
+ task :authors do
59
+ sh "git shortlog -s | awk '{ print $2 \" \" $3 }' > AUTHORS"
60
+ end