Comments (8)
I just commented on the PR. @elShiaLabeouf Just do it
from representable.
Nothing is impossible haha
from representable.
Hey @elShiaLabeouf, thanks for your kind words! It means a lot to us knowing our tools are helpful to people!
What I am wondering is, what is the matter with the original implementation? What exactly wasn't working for you? We might have missed something, I don't remember ever anyone using the object transformation, so I'm happy you took over!
from representable.
Thanks for a quick response! To explain with a few more details:
What I'm trying to achieve
Let's say I have a Rails model Animal
that describes a table animals(id, name, age)
. And I have AnimalRepresenter
:
class AnimalRepresenter < Representable::Decorator
include Representable::Hash
property :name, getter: ->(represented:, **) { represented.name.upcase }
property :age,
property :is_favorite, getter: ->(options:, **) { options[:current_user].favorite_animals_ids.include?(id) }
end
Normally and habitually I'd represent an AR record like this:
represented = AnimalRepresenter.new(animal).to_hash(current_user: current_user)
and it works. I get a decorated object - a hash - with a new represented["is_favorite"]
field and the id value is excluded.
But I wish represented
was not a hash but an object with properties accessible via method calls: represented.is_favorite
What I tried
I tried to change include Representable::Hash
to include Representable::Object
, because their source code seemed similar to me, although the docs didn't mention this feature. But with this code:
require 'representable/object'
class AnimalRepresenter < Representable::Decorator
include Representable::Object
property :name, getter: ->(represented:, **) { represented.name.upcase }
property :age,
property :is_favorite, getter: ->(options:, **) { options[:current_user].favorite_animals_ids.include?(id) }
end
I'm getting an error in the moment of registering the class:
representable/lib/representable/cached.rb:7:in `block in build_definition': undefined local variable or method `format_engine' for AnimalRepresenter:Class (NameError)
binding_builder = format_engine::Binding
^^^^^^^^^^^^^
I dug the Internet and the Zulip chat to find an example, but unsuccessfully. I decided to fork the repo and make an attempt to implement the feature. Thankfully, the structure of the gem is flexible and easy to extend. So I added a few changes inspired by the hash implementation and added some tests.
Then I noticed the code in test/examples/object.rb
, ran it but it resulted with the same error I had got earlier (undefined format_engine). Then I found test/object_test.rb
and figured out that the code for my initial task should look something like that:
require 'representable/object'
module AnimalRepresenter
include Representable::Object
property :name, getter: ->(represented:, **) { represented.name.upcase }
property :age,
property :is_favorite, getter: ->(options:, **) { options[:current_user].favorite_animals_ids.include?(id) }
end
and with usage like this: AnimalRepresenterModule.prepare(animal).to_object(current_user: current_user)
.
The getter:
options didn't work, so I had to strictly follow the style from the spec: instance: ->(options) { options[:fragment].name.upcase!; options[:fragment] }
. To be honest, it looks greek to me.
What I achieved
With the changes from my PR, the line from my initial goal now works: represented = AnimalRepresenter.new(animal).to_object(current_user: current_user)
.
I get a decorated AR record of a Struct form with custom properties and current user context. The format of the method chain is unified with to_hash
and to_json
, which is well-documented in the docs. I also paid close attention to the memory usage by caching the Struct class on a representer class level. Plus implemented for_collection
and wrap:
option.
A brief example of the output from my console:
3.1.0 :009 > animal_array = [Animal.new('Shepard',22,'s'),Animal.new('Pickle',12,'c'),Animal.new('Rodgers',55,'e')]
=>
[#<Animal:0x00007feaab58a6b8 @age=22, @name="Shepard", @species="s">,
...
3.1.0 :010 > array_repr = AnimalRepresenter.for_collection.new(animal_array).to_object(wrap: "wrapper")
=> #<struct wrapper=[#<struct wrapper=#<struct name="SHEPARD", age=22>>, #<struct wrapper=#<struct name="PICKLE", age=12>>, #<struct wrapper=#<struct name="RODGERS", age=55...
from representable.
@elShiaLabeouf IMO, the to_object
method is intended to fill up an object of the same instance and not any other due to it's nature i.e. decorate given object as something else but with a same class.
In your case where you want to access keys of an output hash as a method, could you pass it to OpenStruct for simple method access or Mash if you want nested method access ?
from representable.
@yogeshjain999 Hm, I kind of had the same in mind what @elShiaLabeouf is asking for. If I remember correctly, the object strategy was meant for nested objects. The OpenStruct
approach would only work for one level. To me it sounds like a reasonable approach to make to_object
work.
from representable.
In your case where you want to access keys of an output hash as a method, could you pass it to OpenStruct for simple method access or Mash if you want nested method access ?
Hi @yogeshjain999 ! That's, for sure, one of workarounds to my needs. But if I did so, I presume, the usage of memory would be inefficient since I'd create a hash first and only then convert it to OpenStruct or Hashie resulting in 2x time and resources needed.
Meanwhile, with my approach we directly create a Struct with no middle-man. In fact, Struct is a structure with high performance - 3 to 50 times faster than OpenStruct (benchmark1, benchmark2). So I believe the feature is worth the hustle :)
from representable.
@apotonick thank you for having an understanding of the subject! I'd be happy to see it in master
!
I have changed the test according to you suggestion. Is there anything else needed to have it merged?
from representable.
Related Issues (20)
- Using the :skip_parse option with JSON::Hash values produces Pipeline::Stop HOT 1
- XML Encoding? HOT 3
- Populator docs or examples? HOT 4
- XML namespaces
- Options hash passed to setter has incorrect value for collection properties
- Collection parsing raises an error if the value is nil HOT 4
- Document nested inherit: true
- Parsing null values results in property being set despite `reader` property present
- parsing array of arrays
- Bug in dependency package declarative-option update HOT 1
- Nested keys within hash are getting mutated HOT 5
- Custom writer: method is not invoked or not invoked correctly HOT 2
- Can't activate multi_json on (>= 1.14.1), already activated multi_json-1.11.3 HOT 3
- Representable doesn't work as expected on truffleruby-21.3.0 HOT 1
- Nokogiri deprecation warning
- `nested` tries to assign to non-existent property when parsing nil body HOT 7
- Combining nested include/exclude with regular include/exclude HOT 1
- Representable 4: problem when parsing looks at one field but wants to create two
- Representable 4: how to collect/write data when parsing?
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from representable.