- Drop support for Virtus Coercion
- Fix deprecation warning with Nokogiri 1.13.0
- Upgrade
trailblazer-optionto0.1.1which supports passing an emptykeyword_arguments.
- Remove circular require
- Use Dry-types 1.0.0+ as coercion library
- Renamed Coercion to VirtusCoercion to support old codebases
- Replace
declarative-optionwithtrailblazer-option
- Add proper XML namespace support.
- [internal] Replace
XML::Binding#node_forwith functionXML::Node.
- Replace
Uber::Optionwith the newDeclarative::Option. This should result in a significant performance boost.
- Initialize
Config@wrapto avoid Ruby's warning. - Add
#renderand#parsealias methods to all format modules as a generic entry point. - In
GetValue, usepublic_sendnow.
- Loosen
uberdependency.
- Removed deprecations from 2.4.
- Removed
:parse_strategyin favor of:populator. - Removed
:bindingin favor of your own pipeline.
- No need to use Uber::Callable in Pipeline as this object is always invoked via
#call.
Full migration guide here: http://trailblazer.to/gems/representable/upgrading-guide.html#to-24
-
Breaking API change:
:parse_filterand:render_filterhave no deprecation as all the other, they receive one options. render_filter: val, doc, options -
Decoratoralways needs a format engine included, e.g.Representable::JSONto build bindings at compile-time. -
Removed
Representable::Apply. This is now done viaSchema. representer_class.representable_attrs is definitions -
Removed
:use_decoratoroption. Use a decorator instead. -
Added
Representable.deprecations = falseto disable slow and weird deprecation code. -
Removed
Binding#user_options. This is now available via->(options[:user_options]). -
Removed
Binding#as. -
Removed
Binding#parent_decorator.
- Removed
Binding@represented(which was never public anyway). UseBinding#represented. - Changed signature:
Binding#get(represented:). In now needs a hash{represented: ..}.
- Fix double definition of
Insert. - Deprecate
:binding.
- The preferred way of passing user options is now
to_hash(user_options: {}). - Supports nested options for nested representers.
SetisSetValue.GetisGetValue.CreateObjectno longer invokesAssignFragment. This is now part of the official parse pipeline.
- Use Declarative's
::build_definitioninterface instead of overwriting::property.
-
Remove dependency to Nokogiri and Multi_JSON. You have to add what you need to your
Gemfile/gemspecnow. -
to_*/from_*with options do no longer change the hash but work on copies. -
to_*/from_*now respectwrap: false. This will suppress the wrapping on the first level. -
Introduce
property "name", wrap: false. This allows reusing existing representers withrepresentation_wrapset as nested representers but suppressing the wrapping.class BandDecorator < Representable::Decorator include Representable::Hash self.representation_wrap = :bands # wrap set! property :name end class AlbumDecorator < Representable::Decorator include Representable::Hash self.representation_wrap = :albums # wrap set! property :band, decorator: BandDecorator, wrap: false # you can now set :wrap to false! end album.to_hash #=> {"albums" => {"band" => {"name"=>"Social Distortion"}}}
Thanks to @fighella for inspiring this feature when working on roarify.
-
from_hashno longer crashes with "NoMethodError: undefined method 'has_key?' for nil:NilClass" when an incoming nested object's value isnil. This was a problem with documents like{song: nil}wheresongis a nested property. Thanks to @mhuggins and @moxley for helping here.
- Introduce
Decorator::cloneto make sure cloning properly copies representable_attrs. in former versions, this would partially share definitions with subclasses when the decorator was aninheritable_attr.
- Bug fix: In 2.2.1 I accidentially removed a
supercall inRepresentable::inheritedwhich leads to wrong behavior when having Representable mixed into a class along with other classes overridinginherited. Thanks to @jrmhaig for an excellent bug report making it really easy to find the problem.
-
Options in
Definitionare now Cloneable. That means they will deep-clone when they contain values that areCloneable. This allows clean cloning of deeply nested configuration hashes, e.g. fordeserializer: {instance: ->{}}in combination with inheritance across representers.The former behavior was not to clone, which would allow sub-representers to bleed into the parent options, which is wrong. However, this fix shouldn't affect anyone but me.
-
Introduce
Representable::Cachedthat will keep the mapper, which in turn will keep the bindings, which in turn will keep their representer, in case they're nested. You have to include this feature manually and you can expect a 50% and more speed-up for rendering and parsing. Not to speak about the reduced memory footprint.class SongDecorator < Representable::Decorator include Representable::JSON feature Representable::Cached # .. end
-
Introduced
Decorator#update!to re-use a decorator instance between requests. This will inject the represented object, only.decorator = SongDecorator.new(song) decorator.to_json(..) decorator.update!(louder_song) decorator.to_json(..)
This is quite awesome.
- The
:extendoption only accepts one module.extend: [Module, Module]does no longer work and it actually didn't work in former versions of 2.x, anyway, it just included the first element of an array. - Remove
Binding#representer_module.
-
API change: features are now included into inline representers in the order they were specified. This used to be the other way round and is, of course, wrong, in case a sub-feature wants to override an existing method introduced by an earlier feature.
class Album < Representable::Decorator include Representable::Hash feature Title feature Date property :songs # will include R::Hash, Title, then Date.
As this is an edge-casey change, I decided not to minor-version bump.
- Adding
Object#to_object. This is even faster than using#from_objectfor simple transformations.
- Introducing
Representable::Objectthat allows mapping objects to objects. This is way faster than rendering a hash from the source and then writing the hash to the target object. - Fixed loading issues when requiring
representable/decorator, only.
-
Using
inherit: truenow works even if the parent property hasn't been defined before. It will simply create a new property. This used to crash withundefined methodmerge!' for nil:NilClass`.class SongRepresenter < Representable::Decorator property :title, inherit: true # this will create a brand-new :title property. end
- Allow lonely collection representers without configuration, with inline representer, only. This is for render-only collection representers and very handy.
- Now runs with MagLev.
- Like 2.1.2 (got yanked) because I thought it's buggy but it's not. What has changed is that
Serializer::Collection#serializeno longer doescollection.collectbutcollection.eachsince this allows filtering out unwanted elements.
- Added
:skip_renderoptions.
-
Added
Definition#delete!to remove options. -
Added
Representable::applydo iterate and change schemas. -
Added
Config#removeto remove properties. -
Added
Representable::Debugwhich just has to be included into your represented object.song.extend(SongRepresenter).extend(Representable::Debug).from_json("..") song.extend(SongRepresenter).extend(Representable::Debug).to_json("..")
It can also be included statically into your representer or decorator.
class SongRepresenter < Representable::Decorator include Representable::JSON include Representable::Debug property :title end
It is great.
- None, unless you messed around with internals like
Binding.
- Added
:skip_parseto skip deserialization of fragments. - It's now
Binding#read_fragment -> Populator -> Deserializer. Mostly, this got changed to allow better support for complex collection semantics when populating/deserializing as found in Object-HAL. - Likewise, it is
Binding#write_fragment -> Serializer, clearly separating format-specific and generic logic. - Make
Definition#inspectmore readable by filtering out some instance variables like@runtime_options. - Remove
Binding#write_fragment_for. This is#render_fragmentnow. - Almost 100% speedup for rendering and parsing by removing Ruby's delegation and
method_missing. - Bindings are now in the following naming format:
Representable::Hash::Binding[::Collection]. The file name isrepresentable/hash/binding. - Move
Definition#skipable_empty_value?andDefinition#default_fortoBindingas it is runtime-specific.
- Fix implicit rendering of JSON and XML collections where json/collection wasn't loaded properly, resulting in the native JSON's
#to_jsonto be called. - Fix
:find_or_instantiateparse strategy which wouldn't instantiate but raise an error. Thanks to @d4rky-pl.
- Fixed a bug where
Forwardablewasn't available (because we didn't require it :).
- Fixed a bug with
Config#[]which returned a default value that shouldn't be there.
- Made is simpler to define your own
Definitionclass by passing it toConfig.new(Definition)inRepresenter::build_config.
- Removed class methods
::from_json,::from_hash,::from_yamland::from_xml. Please build the instance yourself and use something alongSong.new.from_json. - Inline representers in
Decoratordo no longer inherit fromself. When defining an inline representer, they are always derived fromRepresentable::Decorator. The base class can be changed by overridingDecorator::default_inline_classin the decorator class that defines an inline representer block. If you need to inherit common methods to all inline decorators, include the module using::feature:Representer.feature(BetterProperty). - You can now define methods in inline representers! The block is now
module_evaled and notinstance_execed anymore. Same goes for Decorators, note that you need toexec_context: :decorator, though. Here, the block isclass_evaled. - Removed behaviour for
instance: lambda { |*| nil }which used to returnbinding.get. Simply do it yourself:instance: lambda { |fragment, options| options.binding.get }if you need this behaviour. If you use:instanceand it returnsnilit throws aDeserializeErrornow, which is way more understandable thanNoMethodError: undefined method 'title=' for {"title"=>"Perpetual"}:Hash. - Remove behaviour for
class: lambda { nil }which used to return the fragment. This now throws aDeserializeError. Do it yourself withclass: lambda { |fragment,*| fragment }. - Coercion now happens inside
:render_filterand:parse_filter(new!) and doesn't block:getterand:setteranymore. Also, we require virtus >=1.0 now. ::representation_wrap=in now properly inherited.- Including modules with representable
property .., inherit: trueinto aDecoratorcrashed. This works fine now.
- Added
::for_collectionto automatically generate a collection representer for singular one. Thanks to @timoschilling for inspiring this years ago. - Added
::representthat will detect collections and render the singular/collection with the respective representer. - Added
Callableoptions. - Added
:parse_filterand:render_filter.
- Added
Representable::featureto include a module and register it to be included into inline representers. - New signature:
inline_representer(base, features, name, options, &block). - Removed
::representer_engine, the module to include is just anotherregister_featurenow. Configno longer is a Hash, it's API is limited to a few methods like#<<,#[]etc. It still supports theEnumberableinterface.- Moved
Representable::ClassMethods::DeclarationstoRepresentable::Declarative. - Moved
Representable::ClassMethodstoRepresentable::Declarative. - Fixed: Inline decorators now work with
inherit: true. - Remove
:extendin combination with inline representer. The:extendoption is no longer considered. Include the module directly into the inline block. - Deprecated class methods
::from_jsonand friends. Use the instance version on an instance. - Use uber 0.0.7 so we can use
Uber::Callable. - Removed
Decorator::Coercion. - Removed
Definition#skipable_nil_value?.
- Binding now uses
#method_missinginstead of SimpleDelegator for a significant performance boost of many 100%s. Thanks to @0x4a616d6573 for figuring this.
- Make
representable/jsonwork without having to requirerepresentable/hash. Thanks to @acuppy!!!
- Fix
JSON::CollectionandJSON::Hash(lonely arrays and hashes), they can now use inline representers. Thanks to @jandudulski for reporting. - Added
:render_emptyoption to suppress rendering of empty collections. This will default to true in 2.0. - Remove Virtus deprecations.
- Add support for Rubinius.
Definition#defaultis public now, please don't use it anyway, it's a private concept.
- Add
:serializeand:deserializeoptions for overriding those steps.
:ifreceives block arguments just like any other dynamic options. Refer to Dynamic Options.- Remove defaults for collections. This fixes a major design flaw - when parsing a document a collection would be reset to
[]even if it is not present in the parsed document. - The number of arguments per block might have changed. Generally, if you're not interested in block arguments, use
Proc.neworlambda { |*| }. See Dynamic Options.
- The following options are dynamic now and can either be a static value, a lambda or an instance method symbol:
:as,:getter,:setter,:class,:instance,:reader,:writer,:extend,:prepare,:if. Please refer to the README to see their signatures. representation_wrapis dynamic, too, allowing you to change the wrap per instance.
- When unsure about the number of arguments passed into an option lambda, use
:pass_options. This passes all general options in a dedicatedOptionsobject that responds tobinding,decorator,representedanduser_options. It's always the last argument for the block. - Added
parse_strategy: :find_or_instantiate. More to come. - Added
parse_strategy: lambda { |fragment, i, options| }to implement your own deserialization. - Use
representable: falseto prevent callingto_*/from_*on a represented object even if the property istyped?(:extend,:classor:instanceset). - Introduced
:use_decoratoroption to force an inline representer to be implemented with a Decorator even in a module. This fixes a bug since we used the:decorateoption in earlier versions, which was already used for something else. - Autoload
Representable::Hash*andRepresentable::Decorator. - Added
Representable::Hash::AllowSymbolsto convert symbol keys to strings infrom_hash.
decorator_scope: trueis deprecated, useexec_context: :decoratorinstead.- Using
:extendin combination with an inline representer is deprecated. Include the module in the block. instance: lambda { true }is deprecated. Useparse_strategy: :sync.- Removed
Config#wrap. Only way to retrieve the evaluated wrap isConfig#wrap_for. class: lambda { nil }is deprecated. To return the fragment from parsing, useinstance: lambda { |fragment, *args| fragment }instead.
- Make
Definition < Hash, all options can/should now be accessed withDefinition#[]. - Make
Definition::newand#merge!the only entry points so that aDefinitionbecomes an almost immutual object. If you happened to modify a definition usingoptions[..]=this will break now. Usedefinition.merge!(..)to change it after creation. - Deprecated
#optionsas the definition itself is a hash (e.g.definition[:default]). - Removed
#sought_type,#default,#attribute,#content. #fromis replaced by#asand hardcore deprecated.#nameand#asare always strings.- A Definition is considered typed as soon as [
:extend|:class|:instance] is set. In earlier versions,property :song, class: Songwas considered typed, whereasproperty :song, class: lambda { Song }was static.
h2. 1.7.7
- Parsing an empty hash with a representer having a wrap does no longer throw an exception.
::nestednow works in modules, too! Nests are implemented as decorator representer, not as modules, so they don't pollute the represented object.- Introduce
:inheritto allow inheriting+overriding properties and inline representers (and properties in inline representers - it starts getting crazy!!!).
h2. 1.7.6
- Add
::nestedto nest blocks in the document whilst still using the same represented object. Use withDecoratoronly. - Fixing a bug (thanks @rsutphin) where inline decorators would inherit the properties from the outer decorator.
h2. 1.7.5
- propagate all options for ::property to ::inline_representer.
h2. 1.7.3
- Fix segfaulting with XML by passing the document to nested objects. Reported by @timoschilling and fixed by @canadaduane.
h2. 1.7.2
Representable#update_properties_fromis private now.- Added the
:contentoption in XML to map top-level node's content to a property.
h2. 1.7.1
- Introduce
Config#optionshash to store per-representer configuration. - The XML representer can now automatically remove namespaces when parsing. Use
XML::remove_namespaces!in your representer. This is a work-around until namespaces are properly implemented in representable.
h2. 1.7.0
- The actual serialization and deserialization (that is, calling
to_hashetc on the object) now happens in dedicated classes:ObjectDeserializerand friends. If you used to override stuff inBinding, I'm sorry. - A new option
parse_strategy: :sync. Instead of creating a new object using the:classoption when parsing, it uses the original object found in the represented instance. This works for property and collections. Configis now a hash. You may find a particular definition by usingConfig#[].- Properties are now overridden: when calling
property(:title)multiple times with the same name, this will override the formerDefinition. While this slightly changes the API, it allows overriding properties cleanly in sub-representers and saves you from manually finding and fiddling with the definitions.
h2. 1.6.1
- Using
instance: lambda { nil }will now treat the property as a representable object without trying to extend it. It simply callsto_*/from_*on the property. - You can use an inline representer and still have a
:extendwhich will be automatically included in the inline representer. This is handy if you want to "extend" a base representer with an inline block. Thanks to @pixelvitamina for requesting that. - Allow inline representers with
collection. Thanks to @rsutphin!
h2. 1.6.0
- You can define inline representers now if you don't wanna use multiple modules and files.
property :song, class: Song do
property :title
endThis supersedes the use for :extend or :decorator, which still works, of course.
- Coercion now happens in a dedicated coercion object. This means that in your models virtus no longer creates accessors for coerced properties and thus values get coerced when rendering or parsing a document, only. If you want the old behavior, include
Virtusinto your model class and do the coercion yourself. Decorator::Coercionis deprecated, just useinclude Representable::Coercion.- Introducing
Mapperwhich does most of the rendering/parsing process. Be careful, if you used to override private methods like#compile_fragmentthis no longer works, you have to override that inMappernow. - Fixed a bug where inheriting from Decorator wouldn't inherit properties correctly.
h2. 1.5.3
Representable#update_properties_fromnow always returnsrepresented, which isselfin a module representer and the decorated object in a decorator (only the latter changed).- Coercion in decorators should work now as expected.
- Fixed a require bug.
h2. 1.5.2
- Rename
:representer_execto:decorator_scopeand make it a documented (!) feature. - Accessors for properties defined with
decorator_scope: truewill now be invoked on the decorator, not on the represented instance anymore. This allows having decorators with helper methods. - Use
MultiJsoninstead ofJSONwhen parsing and rendering. - Make
Representable::Decorator::Coercionwork.
h2. 1.5.1
- Make lonely collections and hashes work with decorators.
h2. 1.5.0
- All lambdas now receive user options, too. Note that this might break your existing lambdas (especially with
:extendor:class) raising anArgumentError: wrong number of arguments (2 for 1). Fix this by declaring your block params correctly, e.g.lambda { |name, *|. Internally, this happens by running all lambdas through the newBinding#represented_exec_for.
h2. 1.4.2
- Fix the processing of
:setter, we called both the setter lambda and the setter method.
h2. 1.4.1
- Added
:representer_execto have lambdas be executed in decorator instance context.
h2. 1.4.0
- We now have two strategies for representing: the old extend approach and the brand-new decorator which leaves represented objects untouched. See "README":https://github.com/apotonick/representable#decorator-vs-extend for details.
- Internally, either extending or decorating in the Binding now happens through the representer class method
::prepare(i.e.Decorator::prepareorRepresentable::preparefor modules). That means any representer module or class must expose this class method.
h2. 1.3.5
- Added
:readerand:writerto allow overriding rendering/parsing of a property fragment and to give the user access to the entire document.
h2. 1.3.4
- Replacing
jsongem withmulti_jsonhoping not to cause trouble.
h2. 1.3.3
- Added new options:
:binding,:setterand:getter. - The
:ifoption now eventually receives passed in user options.
h2. 1.3.2
- Some minor internal changes. Added
Config#inheritto encasulate array push behavior.
h2. 1.3.1
- Bringing back
:as. For some strange reasons "we" lost that commit from @csexton!!!
h2. 1.3.0
- Remove @:exclude@ option.
- Moving all read/write logic to @Binding@. If you did override @#read_fragment@ and friends in your representer/models this won't work anymore.
- Options passed to @to_/from_@ are now passed to nested objects.
h2. 1.2.9
- When @:class@ returns @nil@ we no longer try to create a new instance but use the processed fragment itself.
- @:instance@ allows overriding the @ObjectBinding#create_object@ workflow by returning an instance from the lambda. This is particularly helpful when you need to inject additional data into the property object created in #deserialize.
- @:extend@ and @:class@ now also accept procs which allows having polymorphic properties and collections where representer and class can be chosen at runtime.
h2. 1.2.8
- Reverting all the bullshit from 1.2.7 making it even better. @Binding@s now wrap their @Definition@ instance adopting its API. Moved the binding_for_definition mechanics to the respecting @Binding@ subclass.
- Added :readable and :writeable to #property: while @:readable => true@ renders the property into the document @:writeable => true@ allows updating the property's value when consuming a representation. Both default to @true@.
h2. 1.2.7
- Moving @Format.binding_for_definition@ to @Format#{format}_binding_for_definition@, making it an instance method in its own "namespace". This allows mixing in multiple representer engines into a user's representer module.
h2. 1.2.6
- Extracted @HashRepresenter@ which operates on hash structures. This allows you to "parse" form data, e.g. as in Rails' @params@ hash. Internally, this is used by JSON and partly by YAML.
h2. 1.2.5
- Add support for YAML.
h2. 1.2.4
- ObjectBinding no longer tries to extend nil values when rendering and @:render_nil@ is set.
- In XML you can now use @:wrap@ to define an additional container tag around properties and collections.
h2. 1.2.3
- Using virtus for coercion now works in both classes and modules. Thanks to @solnic for a great collaboration. Open-source rocks!
h2. 1.2.2
- Added @XML::AttributeHash@ to store hash key-value pairs in attributes instead of dedicated tags.
- @JSON::Hash@, @XML::Hash@ and @XML::AttributeHash@ now respect @:exclude@ and @:include@ when parsing and rendering.
h2. 1.2.1
- Deprecated @:represent_nil@ favor of @:render_nil@.
- API change: if a property is missing in an incoming document and there is no default set it is completely ignored and not set in the represented object.
h2. 1.2.0
- Deprecated @:except@ in favor of @:exclude@.
- A property with @false@ value will now be included in the rendered representation. Same applies to parsing, @false@ values will now be included. That particularly means properties that used to be unset (i.e. @nil@) after parsing might be @false@ now.
- You can include @nil@ values now in your representations since @#property@ respects @:represent_nil => true@.
h2. 1.1.6
- Added @:if@ option to @property@.
h2. 1.1.5
- Definitions are now properly cloned when @Config@ is cloned.
h2. 1.1.4
- representable_attrs is now cloned when a representer module is included in an inheriting representer.
h2. 1.1.3
- Introduced
#compile_fragmentand friends to make it simpler overriding parsing and rendering steps.
h2. 1.1.2
- Allow
Module.hashto be called without arguments as this seems to be required in Padrino.
h2. 1.1.1
- When a representer module is extended we no longer set the
@representable_attrsivar directly but use a setter. This makes it work with mongoid and fixes trailblazer/roar#10.
h2. 1.1.0
- Added
JSON::Collectionto have plain list representations. AndJSON::Hashfor hashes. - Added the
hashclass method to XML and JSON to represent hashes. - Defining
:extendonly on a property now works for rendering. If you try parsing without a:classthere'll be an exception, though.
h2. 1.0.1
- Allow passing a list of modules to :extend, like @:extend => [Ingredient, IngredientRepresenter]@.
h2. 1.0.0
- 1.0.0 release! Party time!
h2. 0.13.1
- Removed property :@name from @XML@ in favor of @:attribute => true@.
h2. 0.13.0
- We no longer create accessors in @Representable.property@ - you have to do this yourself using @attr_accessors@.
h2. 0.12.0
- @:as@ is now @:class@.
h2. 0.11.0
- Representer modules can now be injected into objects using @#extend@.
- The @:extend@ option allows setting a representer module for a typed property. This will extend the contained object at runtime roughly following the DCI pattern.
- Renamed @#representable_property@ and @#representable_collection@ to @#property@ and @#collection@ as we don't have to fear namespace collisions in modules.
h2. 0.10.3
- Added @representable_property :default => ...@ option which is considered for both serialization and deserialization. The default is applied when the value is @nil@. Note that an empty string ain't @nil@.
- @representable_attrs@ are now pushed to instance level as soon as possible.
h2. 0.10.2
- Added @representable_property :accessors => false@ option to suppress adding accessors.
- @Representable.representation_wrap@ is no longer inherited.
- Representers can now be defined in modules. They inherit to including modules.
h2. 0.10.1
- The block in @to_@ and @from_@ now yields the symbolized property name. If you need the binding/definition you gotta get it yourself.
- Runs with Ruby 1.8 and 1.9.
h2. 0.10.0
- Wrapping can now be set through @Representable.representation_wrap=@. Possible values are:
- @false@: No wrapping. In XML context, this is undefined behaviour. Default in JSON.
- @String@: Wrap with provided string.
- @true@: compute wrapper from class name.
h2. 0.9.3
- Removed the @:as => [..]@ syntax in favor of @:array => true@.
h2. 0.9.2
- Arguments and block now successfully forwarded in @#from_*@.
h2. 0.9.1
- Extracted common serialization into @Representable#create_representation_with@ and deserialization into @#update_properties_from@.
- Both serialization and deserialization now accept a block to make them skip elements while iterating the property definitions.
h2. 0.9.0
h3. Changes
- Removed the :tag option in favor of :from. The Definition#from method is now authorative for all name mappings.
- Removed the active_support and i18n dependency.