Flattener
Allows to flat an object (ActiveRecord based) into one single level, so creating a form for the object becomes really simple. See usage for more details, or create an issue.
Installation
Add this line to your application's Gemfile:
gem 'flattener'
And then execute:
$ bundle
Or install it yourself as:
$ gem install flattener
Usage
Say you have something like this:
class Customer < ActiveRecord::Base
has_one :address
end
class Address < ActiveRecord::Base
# ... Attributes here
end
You could do something like this:
class Customer < ActiveRecord::Base
include Flattener
has_one :address
flat :address do
attribute :address_line_1
attribute :address_line_2
attribute :city
attribute :state
attribute :country
end
end
and use it like this:
customer = Customer.new address_line_1: "Av. Santa Fe 1234", country: "Argentina"
Pretty simple. It support all the basic AR methods, like valid?, save or create.
I know what you think. "I can do that with a simple delegate call". Indeed, but you can also do this:
class Payment < ActiveRecord::Base
include Flattener
has_one :payment_profile
flat :payment_profile do
attributes :credit_card, :expiration_date
flat :address, build: proc { proxy_payment_profile.build_address } do
attribute :address_line_1
attribute :address_line_2
end
end
end
And this way getting something really simple:
payment = Payment.new amount: "23.00", payment_profile_credit_card: "XXXXXXXXXX", expiration_date: "2011/12",
payment_profile_address_line_1: "Av. Mongo 1234"
payment.payment_profile_address_line_1 #=> "Av. Mongo 1234"
# and so on.
# supose you have a validation on Address#address_line_2
payment.valid? #=> false
payment.errors[:payment_profile_address_line_1] #=> ".... is required, blah..."
Prefix is optional, and changeable:
class Payment < ActiveRecord::Base
include Flattener
has_one :payment_profile
flat :payment_profile, prefix: "pp" do
attributes :credit_card, :expiration_date
end
end
payment = Payment.new
payment.pp_credit_card = "XXXX-XXXX-XXXX-XXXX"
payment.pp_credit_card # => "XXXX-XXXX-XXXX-XXXX"
You can use this also as a presenter (or something like that):
class PaymentBuilder < Flattener::Base
attr_accessor :payment_profile
flat :payment_profile,
prefix: "",
build: proc { self.payment_profile = PaymentProfile.new } do
attributes :credit_card, :expiration_date
end
end
payment = PaymentBuilder.new :credit_card => "XXXX-XXXX-XXXX-XXXX"
payment.credit_card # => "XXXX-XXXX-XXXX-XXXX"
You wonder why is this useful? May be you have something really complex on your app, but you want to expose it (to the view) in a simpler way, and only allowing some properties.
So what is this gem doing?
- It builds the flattened objects automatically, or the way you want (configuration option).
- It overwrites the AR methods in order to call the flattened methods before, so the right validation errors appear in place.
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Added some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request