Money-Rails Gem: Humanized_money in Models
Asked Answered
R

5

5

In my Donations Model, I have monetized the amount_cents column

I need the humanized version of the donation amount (Eg. 643.50) in the Model so I can generate and send a PDF receipt to the donor.

I've tried humanized_money(self.amount) and self.amount.humanized_money but get the error :

NoMethodError: undefined method `humanized_money' for #<Donation:0x007fa687ebb678>

How can I get this humanized form in the Models?

class Donation < ActiveRecord::Base
  belongs_to :donatable, polymorphic: true
  belongs_to :added_by_user, foreign_key: "added_by", class_name: "User"

  store_accessor :details, :method

  monetize :amount_cents

  def donations_this_week(branch_id)
    sum =  Donation.sum(:amount_cents).to_money
    return humanized_money(sum)
  end

  def receipt
    Receipts::Receipt.new(
        id: id,
        product: "GoRails",
        message: "This receipt is to acknowledge that we have received a donation with the below details from #{self.donatable.name}",
        company: {
            name: self.donatable.branch.organization.name,
            address: "#{self.donatable.branch.address_line_1}\n#{self.donatable.branch.address_line_2}\n#{self.donatable.branch.email}\n#{self.donatable.branch.legal_details}",
            email: self.donatable.branch.email,
            logo: self.donatable.branch.organization.logo.url(:medium),
        },
        line_items: [
            ["Date",           created_at.to_s],
            ["Donor Name", self.donatable.name],
            ["Amount",         humanized_money(self.amount)],
            ["Payment Method",     self.method],
        ]
    )
  end
end

Below is the database schema :

create_table "donations", force: :cascade do |t|
t.string   "donatable_type"
t.integer  "donatable_id"
t.integer  "amount_cents"
t.datetime "created_at",                  null: false
t.datetime "updated_at",                  null: false
t.datetime "date"
t.integer  "added_by"
t.jsonb    "details",        default: {}, null: false
Rennes answered 19/8, 2015 at 4:30 Comment(6)
You should post your Donation model, particularly the the part where you monetize the amount field. Right off, I can tell you the problem is that you're calling humanized_money on a Donation object. You need to call that method with a Money object as the parameter.Reverberator
post the code where you are calling humanize_money. I am guessing that maybe you are calling humanized_money on something that is not a money_objectSandstone
Attached the model! Thanks!Rennes
could you check the column type of amount in your database?Chatterton
Attached the database schema!Rennes
the helper calls a money method that can be called directly in the model without include the whole helper in the model https://mcmap.net/q/1899797/-money-rails-gem-humanized_money-in-modelsTierell
T
2

Do NOT need to include the helper in your model.

price_options = {
  :no_cents_if_whole => MoneyRails::Configuration.no_cents_if_whole.nil? ? true : MoneyRails::Configuration.no_cents_if_whole,
  :symbol => true
}
your_money_column.format(price_options)

source code on github

Tierell answered 14/3, 2018 at 18:57 Comment(0)
N
5

To do this without loading everything in ActionView::Base. You can just do

return ActionController::Base.helpers.humanized_money sum
Nystrom answered 8/1, 2016 at 20:1 Comment(0)
C
4

Including ActionView::Base will add a LOT of extra stuff to your model, do NOT do it this way.

Do this instead:

include MoneyRails::ActionViewExtension

This way you get all (5 at the time of this post) of the money view helper methods.

Comprehensible answered 16/9, 2017 at 0:40 Comment(1)
THIS! Even saw solutions that this ActionView::Base.new.humanized_money(10) Especially when you have a plain api and dont even use action view...Mccray
C
2
NoMethodError: undefined method `humanized_money' for #<Donation:0x007fa687ebb678>

From the error message its clear that you are calling the humanized_money helper method for a Donation object, NOT a Money object. That's why its failing.

If you monetized the amount_cents column properly already, then automagically, your amount column will be of Money type i.e. Money object which you can pass to the humanized_money helper method as parameter like this:

humanized_money amount

I would say, check the type of your amount and make sure its a Money object which it should be if you properly monetized amount_cents column of your Donation model. That's why it's not working in this case.

Update

Looks like humanized_money is defined in the action_view_extension of the money-rails gem and expected to work in views only. Not in model.

A possible solution to this problem would be to include ActionView::Base module in the Model, that would make the humanized_money method available inside the model. And then you can call humanized_money in your model like:

 include ActionView::Base
 humanized_money(sum)
Chatterton answered 19/8, 2015 at 4:51 Comment(6)
I'm pretty sure it is, when I run Donation.last.amount on the console, I get : => #<Money fractional:3400 currency:USD>Rennes
on which line its failing? return humanized_money(sum) OR ["Amount", humanized_money(self.amount)]?Chatterton
Okay, can you inspect this: puts Donation.sum(:amount_cents).to_money.inspect what do you see?Chatterton
(0.4ms) SELECT SUM("donations"."amount_cents") FROM "donations" #<Money fractional:33985700 currency:USD> => nilRennes
ok, so its a Money object. Then I don't see any reason for its failing :( Seems to be, it does not work in a Model class for some reason. Can you try it in your view? I am sure it will work.Chatterton
Let us continue this discussion in chat.Chatterton
T
2

Do NOT need to include the helper in your model.

price_options = {
  :no_cents_if_whole => MoneyRails::Configuration.no_cents_if_whole.nil? ? true : MoneyRails::Configuration.no_cents_if_whole,
  :symbol => true
}
your_money_column.format(price_options)

source code on github

Tierell answered 14/3, 2018 at 18:57 Comment(0)
S
0

KM Rakibul is right about the helper not being included in ActiveRecord but they are hooked to ActionView::Base so to include them use:

include ActionView::Base
Sandstone answered 19/8, 2015 at 5:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.