Define Poro
Plain Old Ruby Object class builder from provided attribute list and block.
WARNING
Sadly assignment does not handle constants scope well:
RegisterUser = DefinePoro::As.new(:user, :params) do
USER_TYPE = 1
# logic for registering user
end
puts USER_TYPE #> 1 WHAT! constant is bound to outer context
puts RegisterUser::USER_TYPE #> NameError: uninitialized constant RegisterUser::XX
Conclusion - please use old plain ruby objects with initializer and attr_reader, fancy things are not always the best ones.
History
Rationale
I have been using Struct.new to dynamically create ruby objects that base their identity on functionality and not on values.
RegisterUser = Struct.new(:user, :params) do
# logic for registering user
end
Then I looked what a Struct is: http://en.wikipedia.org/wiki/Struct_%28C_programming_language%29
From ruby side http://www.ruby-doc.org/core-2.2.0/Struct.html
So it is an object that acts like container for data. It implements Enumerable
.
But RegisterUser
is not a data container, neither enumerable. So what is it?
I would say PORO (plain old ruby object).
It should be described as:
RegisterUser
attr_reader :user, :params
def initialize(user, params)
@user, @params = user, params
end
# logic for registering user
end
Ruby guys are lazy so we would like to type something shorter - that's provided by DefinePoro:
RegisterUser = DefinePoro::As.new(:user, :params) do
# logic for registering user
end
The DefinePoro::As
implementation is easy and performant ruby code.
Should you use it?
Yes - if you are lazy to type initializers.
No - if you think that dynamic class definition could be harmful. And I believe that in some cases it could.
SURELY NOT - sadly assignment does not handle constants scope well.
Installation
Add this line to your application's Gemfile:
gem 'define-poro'
And then execute:
$ bundle
Or install it yourself as:
$ gem install define-poro
Usage
Instead of
RegisterUser
attr_reader :user, :params
def initialize(user, params)
@user, @params = user, params
end
# logic for registering user
end
Define you class via
RegisterUser = DefinePoro::As.new(:user, :params) do
# logic for registering user
end
Contributing
- Fork it ( https://github.com/astrauka/define-poro/fork )
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Ensure that you have written specs (rspec)
- Push to the branch (
git push origin my-new-feature
) - Create a new Pull Request
Changelog
0.1.0
- renamed DefinePoro::Define
to DefinePoro::As