It's a Gem to convert ActiveRecord models' attributes and methods to human readable representations of these.
Add to your Gemfile:
gem "human_attributes"bundle installSuppose you have the following model:
# == Schema Information
#
# Table name: purchases
#
# id :integer not null, primary key
# paid :boolean
# commission :decimal(, )
# quantity :integer
# state :string
# expired_at :datetime
# amount :decimal(, )
# description :text
# created_at :datetime not null
# updated_at :datetime not null
#
class Purchase < ActiveRecord::Base
extend Enumerize
STATES = %i{pending canceled finished}
enumerize :state, in: STATES, default: :pending
def commission_amount
amount * commission / 100.0
end
endExecuting the humanize method, inside the class definition, will allow you to apply Formatters to Purchase's attributes and methods.
With...
purchase = Purchase.new
purchase.quantity = 20
purchase.commission = 5.3And having...
class Purchase < ActiveRecord::Base
humanize :quantity, percentage: true
humanize :commission, :commission_amount, currency: { unit: "R$", separator: ",", delimiter: "" }
endYou can do...
purchase.human_quantity #=> "20.000%"
purchase.human_commission #=> "R$5,30"
purchase.human_commission_amount #=> R$1 060 000,03The available numeric types are:currency, number, size, percentage, phone, delimiter and precision.
And the options to use with numeric types, are the same as in NumberHelper
With...
purchase = Purchase.new
purchase.expired_at = "04/06/1984 09:20:00"
purchase.created_at = "04/06/1984 09:20:00"
purchase.updated_at = "04/06/1984 09:20:00"And /your_app/config/locales/en.yml
en:
date:
formats:
default: "%Y-%m-%d"
short: "%b %d"And having...
class Purchase < ActiveRecord::Base
humanize :expired_at, date: { format: :short }
humanize :created_at, date: true
humanize :updated_at, date: { format: "%Y" }
endYou can do...
purchase.human_expired_at #=> "04 Jun"
purchase.human_created_at #=> "1984-06-04"
purchase.human_updated_at #=> "1984"With...
purchase = Purchase.new
purchase.expired_at = "04/06/1984 09:20:00"
purchase.created_at = "04/06/1984 09:20:00"
purchase.updated_at = "04/06/1984 09:20:00"And /your_app/config/locales/en.yml
en:
time:
formats:
default: "%a, %d %b %Y %H:%M:%S %z"
short: "%d %b %H:%M"And having...
class Purchase < ActiveRecord::Base
humanize :expired_at, datetime: { format: :short }
humanize :created_at, datetime: true
humanize :updated_at, datetime: { format: "%Y" }
endYou can do...
purchase.human_expired_at #=> "04 Jun 09:20"
purchase.human_created_at #=> "Mon, 04 Jun 1984 09:20:00 +0000"
purchase.human_updated_at #=> "1984"With...
purchase = Purchase.new
purchase.paid = trueAnd /your_app/config/locales/en.yml
en:
boolean:
positive: "Yes"
negative: "No"Having...
class Purchase < ActiveRecord::Base
humanize :paid, boolean: true
endYou can do...
purchase.human_paid #=> "Yes"
purchase.paid = false
purchase.human_paid #=> "No"Installing Enumerize gem with...
purchase = Purchase.new
purchase.state = :finishedAnd /your_app/config/locales/en.yml
en:
enumerize:
purchase:
state:
pending: "P."
finished: "F."
canceled: "C."Having...
class Purchase < ActiveRecord::Base
humanize :state, enumerize: true
endYou can do...
purchase.state = :finished
purchase.human_state #=> "F."Having...
class Purchase < ActiveRecord::Base
enum payment_method: [:credit, :debit, :cash, :bitcoin]
endYou can add
class Purchase < ActiveRecord::Base
enum payment_method: [:credit, :debit, :cash, :bitcoin]
humanize :payment_method, enum: true
endAnd /your_app/config/locales/en.yml
en:
activerecord:
attributes:
purchase:
payment_methods:
credit: "Credit Card"
debit: "Debit Card"
cash: "Cash"
bitcoin: "Bitcoin"And then you can do...
purchase = Purchase.new
purchase.payment_method = :debit
purchase.human_payment_method #=> "Debit Card"If you want to use the same enum translations for multiple models, use this locales structure:
/your_app/config/locales/en.yml
en:
enum:
default:
payment_methods:
credit: "Credit Card"
debit: "Debit Card"
cash: "Cash"
bitcoin: "Bitcoin"and then in other models will also work:
class Debt < ActiveRecord::Base
enum payment_method: [:credit, :debit, :cash, :bitcoin]
humanize :payment_method, enum: true
endpurchase = Purchase.new
purchase.payment_method = :debit
debt = Debt.new
debt.payment_method = :bitcoin
purchase.human_payment_method #=> "Debit Card"
debt.human_payment_method #=> "Bitcoin"With...
purchase = Purchase.create!And having...
class Purchase < ActiveRecord::Base
humanize :id, custom: { formatter: ->(purchase, value) { "Purchase: #{value}-#{purchase.id}" } }
endYou can do...
purchase.human_id #=> "Purchase: 1-1"The following options are available to use with all the formatters presented before.
With...
purchase = Purchase.new
purchase.amount = nilHaving...
class Purchase < ActiveRecord::Base
humanize :amount, currency: { default: 0 }
endYou can do...
purchase.human_amount #=> "$0"Useful when you want to define multiple formatters for the same attribute.
With...
purchase = Purchase.new
purchase.paid = true
purchase.amount = 20Having...
class Purchase < ActiveRecord::Base
humanize :paid, boolean: { suffix: "with_custom_suffix" }
humanize :amount, currency: { suffix: true }
endYou can do...
purchase.paid_with_custom_suffix #=> "Yes"
purchase.amount_to_currency #=> "$20" # default suffixWith...
purchase = Purchase.new
purchase.amount = 20Having...
class Purchase < ActiveRecord::Base
humanize :amount, currency: { suffix: true }, percentage: { suffix: true }
endYou can do...
purchase.amount_to_currency #=> ""
purchase.amount_to_percentage #=> ""Remember to use
:suffixoption to avoid name collisions
You can generate human representations for all the atributes of your ActiveRecord model like this:
class Purchase < ActiveRecord::Base
humanize_attributes
endThe humanize_attributes method will infer from the attribute's data type which formatter to choose.
With our Purchase model we will get:
purchase.human_id
purchase.human_paid
purchase.human_commission
purchase.human_quantity
purchase.human_expired_at
purchase.expired_at_to_short_date
purchase.expired_at_to_long_date
purchase.expired_at_to_short_datetime
purchase.expired_at_to_long_datetime
purchase.human_amount
purchase.human_created_at
purchase.created_at_to_short_date
purchase.created_at_to_long_date
purchase.created_at_to_short_datetime
purchase.created_at_to_long_datetime
purchase.human_updated_at
purchase.updated_at_to_short_date
purchase.updated_at_to_long_date
purchase.updated_at_to_short_datetime
purchase.updated_at_to_long_datetimeYou can pass to
humanize_attributesthe optiononly: [:attr1, :attr2]to humanize specific attributes. Theexceptoption works in similar way.
If you are thinking that the formatting functionality is a view related issue, you are right. Because of this, we made the integration with Draper gem. Using draper, you can move all your humanizers to your model's decorator.
With...
class Purchase < ActiveRecord::Base
extend Enumerize
STATES = %i{pending canceled finished}
enumerize :state, in: STATES, default: :pending
humanize :state, enumerize: true
humanize :commission, percentage: true
humanize :amount, currency: true
endYou can refactor your code like this:
class Purchase < ActiveRecord::Base
extend Enumerize
STATES = %i{pending canceled finished}
enumerize :state, in: STATES, default: :pending
end
class PurchaseDecorator < Draper::Decorator
delegate_all
humanize :state, enumerize: true
humanize :commission, percentage: true
humanize :amount, currency: true
endThen, you can use it, like this:
purchase.human_amount #=> NoMethodError: undefined method `human_amount'
purchase.decorate.human_amount #=> $2,000,000.95It's not mandatory to use draper as decorator. You can extend whatever you want including HumanAttributes::Extension. For example:
Draper::Decorator.send(:include, HumanAttributes::Extension)You can run, from your terminal, the following task to show defined human attributes for a particular ActiveRecord model.
$ rake human_attrs:show[your-model-name]
So, with...
class Purchase < ActiveRecord::Base
extend Enumerize
STATES = %i{pending canceled finished}
enumerize :state, in: STATES, default: :pending
humanize_attributes
humanize :state, enumerize: true
humanize :commission, percentage: true
humanize :amount, currency: true
endAnd running rake human_attrs:show[purchase], you will see the following output:
human_id => Purchase: #1
human_paid => Yes
human_commission => 1000.990%
human_quantity => 1
human_expired_at => Fri, 06 Apr 1984 09:00:00 +0000
expired_at_to_short_date => Apr 06
expired_at_to_long_date => Apr 06
expired_at_to_short_datetime => 06 Apr 09:00
expired_at_to_long_datetime => 06 Apr 09:00
human_amount => $2,000,000.95
human_created_at => Sat, 10 Dec 2016 21:18:15 +0000
created_at_to_short_date => Dec 10
created_at_to_long_date => Dec 10
created_at_to_short_datetime => 10 Dec 21:18
created_at_to_long_datetime => 10 Dec 21:18
human_updated_at => Sat, 10 Dec 2016 21:18:15 +0000
updated_at_to_short_date => Dec 10
updated_at_to_long_date => Dec 10
updated_at_to_short_datetime => 10 Dec 21:18
updated_at_to_long_datetime => 10 Dec 21:18
human_state => Pending
To run the specs you need to execute, in the root path of the gem, the following command:
bundle exec guardTo run all the specs of the gem, in the root path of the gem, the following command:
bundle exec rspecYou need to put all your tests in the /human_attributes/spec/dummy/spec/ directory.
On master/main branch...
- Change
VERSIONinlib/gemaker/version.rb. - Change
Unreleasedtitle to current version inCHANGELOG.md. - Run
bundle install. - Commit new release. For example:
Releasing v0.1.0. - Create tag. For example:
git tag v0.1.0. - Push tag. For example:
git push origin v0.1.0.
- Fork it
- Create your feature branch (
git checkout -b my-new-feature) - Commit your changes (
git commit -am 'Add some feature') - Push to the branch (
git push origin my-new-feature) - Create new Pull Request
Thank you contributors!
Human Attributes is maintained by platanus.
Human Attributes is © 2016 platanus, spa. It is free software and may be redistributed under the terms specified in the LICENSE file.