This project follows Semantic Versioning.
None of these changes should break anything for you, only speed things up, unless you're doing something very weird.
- Rewrite internals to improve runtime performance. No longer depend on
portrayal.attributes
, instead generating ruby code that references keywords literally (much more efficient). - All attr_readers and other methods such as
eql?
,==
,freeze
, etc are now included as a module, rather than class_eval'ed into your class. This lets you usesuper
when overriding them. - Class method
portrayal
now appears when you callextend Portrayal
, and not after the firstkeyword
declaration. (Instance methods are still added uponkeyword
.) - Remove
portrayal[]
shortcut that accessedportrayal.schema
(useportrayal.schema[]
directly instead). - Remove
portrayal.render_initialize
. - Add
portrayal.module
, which is the module included in your struct. - Add
portrayal.render_module_code
, which renders the code for the module. - Bring back class comparison to
==
(reverses a change in 0.3.0). Upon further research, it seems class comparison is always necessary. - Methods
==
,eql?
,hash
,initialize_dup
,initialize_clone
, andfreeze
now operate on @instance @variables, not reader method return values. - Methods
deconstruct
anddeconstruct_keys
now quietly exclude private/protected keywords.
- Add pattern matching support (
#deconstruct
and#deconstruct_keys
).
-
Fix default procs' behavior when overriding keywords in subclasses. Portrayal relies on an ordered ruby hash to initialize keywords in the correct order. However, if overriding the same keyword in a subclass (by declaring it again), it didn't move keyword to the bottom of the hash, so this would happen:
class Person extend Portrayal keyword :email, default: nil end class Employee < Person keyword :employee_id keyword :email, default: proc { "#{employee_id}@example.com" } end employee = Employee.new(employee_id: '1234') employee.email # => "@example.com"
The email is broken because it relies on having employee_id declared before email, but email was already declared first in the superclass. This change fixes situations like this by re-adding the keyword to the bottom of the hash on every re-declaration.
-
Breaking change: Remove
optional
setting. To update find alloptional: true
and change todefault: nil
instead. -
Breaking change: Move
self
of default procs toinitialize
context. Before this change, default procs used to be executed naively in class context. Now they can access other keyword readers and instance methods since theirself
is now coming frominitialize
. To update, look through your default procs and replace any reference to current class's methods such asmethod_name
withself.class.method_name
.
- Return keyword name from
keyword
, allowing usage such asprivate keyword :foo
. [commit]
- Add option
define
for overriding nested class name. [commit]
- Portrayal schema is deep-duped to subclasses. [commit]
- Fix the issue introduced in 0.3.0 where
==
andeql?
were always treating rhs as another portrayal class. [commit]
- No longer compare classes in
==
, useeql?
for that. [commit] - Define a protected writer for every keyword - useful when applying changes after
dup
/clone
. [commit] - Add definition of
#hash
to fix hash equality. Nowhash[object]
will match ifobject
is of the same class with the same keywords and values. [commit] - Make
#freeze
propagate to all keyword values. [commit] - Make
#dup
and#clone
propagate to all keyword values. [commit]
- It's now possible to specify non-lambda default values, like
default: "foo"
. There is now also a distinction between a proc and a lambda default. Procs arecall
-ed, while lambdas or any other types are returned as-is. In the majority of cases defaults are static values, and there is no need for the performance overhead of making all defaults into anonymous functions. [commit]
First version.