representable icon indicating copy to clipboard operation
representable copied to clipboard

Representation doesn't appear to recurse on Properties that are also representable

Open kipcole9 opened this issue 10 years ago • 5 comments

Using Roar/Representable 2.3, 2.4 and 3.0. Rails apps but would seem unrelated. Representable is serialising Properties when are themselves Representable. For example below an instance of User is assigned to the created_by attribute of a new Blog. There is already a UserRepresenter available but its not used and hence private information can easily leak.

I realise I can add a specific #getter for the relevant attributes but it would seem to make sense that Representable would use a Representer for Properties that have one?

2.2.2 :002 > b = Blog.new name: 'Blog', description: 'New Blog'
 => #<Blog id: nil, created_by: nil, updated_by: nil, owner_id: nil, group_id: nil, permissions: nil, tags: nil, created_at: nil, updated_at: nil, name: "Blog", slug: nil, description: "New Blog", language: nil, tsvector: nil, copyright_notice: nil, copyrighted_on: nil, mail_address: nil, layout_id: nil> 
2.2.2 :003 > u = User.last
  User Load (1.4ms)  SELECT  "users"."tableoid"::regclass as "type", "users".* FROM "users" ORDER BY created_at DESC LIMIT $1  [["LIMIT", 1]]
 => #<User id: "b9dc0139-e453-4c65-8c0c-6b46a13c3d6e", created_by: nil, updated_by: nil, owner_id: nil, group_id: nil, permissions: nil, tags: nil, created_at: "2015-12-20 11:20:04", updated_at: "2015-12-20 11:20:04", name: "System Admin", slug: "system-admin", description: nil, language: "simple", tsvector: "'admin':2A 'system':1A", honorific: nil, given_name: nil, family_name: nil, middle_names: nil, known_as: nil, suffix: nil, formal_address: nil, informal_address: nil, salutation: nil, born_on: nil, died_on: nil, gender_id: nil, name_order: nil, locale: nil, status: nil, login_name: "admin", api_key: "5aa7001622ea81ec1d5fb6674b074a71", password_digest: "$2a$10$4mIUUvt9YKHhuF5KM3A4NuvXXSVleau1Gln/qffci1z...", groups: nil, auth: nil> 
2.2.2 :004 > b.created_by = u
 => #<User id: "b9dc0139-e453-4c65-8c0c-6b46a13c3d6e", created_by: nil, updated_by: nil, owner_id: nil, group_id: nil, permissions: nil, tags: nil, created_at: "2015-12-20 11:20:04", updated_at: "2015-12-20 11:20:04", name: "System Admin", slug: "system-admin", description: nil, language: "simple", tsvector: "'admin':2A 'system':1A", honorific: nil, given_name: nil, family_name: nil, middle_names: nil, known_as: nil, suffix: nil, formal_address: nil, informal_address: nil, salutation: nil, born_on: nil, died_on: nil, gender_id: nil, name_order: nil, locale: nil, status: nil, login_name: "admin", api_key: "5aa7001622ea81ec1d5fb6674b074a71", password_digest: "$2a$10$4mIUUvt9YKHhuF5KM3A4NuvXXSVleau1Gln/qffci1z...", groups: nil, auth: nil> 
2.2.2 :005 > b
 => #<Blog id: nil, created_by: "b9dc0139-e453-4c65-8c0c-6b46a13c3d6e", updated_by: nil, owner_id: nil, group_id: nil, permissions: nil, tags: nil, created_at: nil, updated_at: nil, name: "Blog", slug: nil, description: "New Blog", language: nil, tsvector: nil, copyright_notice: nil, copyrighted_on: nil, mail_address: nil, layout_id: nil> 

# Representer will serialise the complete object assigned to created_by when there is a representer available for it:
2.2.2 :006 > b.extend(V1::BlogRepresenter).to_hash
 => {"@type"=>"blog", "tags"=>nil, "permissions"=>nil, "name"=>"Blog", "description"=>"New Blog", "language"=>nil, "copyright_notice"=>nil, "copyrighted_on"=>nil, "created_at"=>nil, "updated_at"=>nil, "created_by"=>#<User id: "b9dc0139-e453-4c65-8c0c-6b46a13c3d6e", created_by: nil, updated_by: nil, owner_id: nil, group_id: nil, permissions: nil, tags: nil, created_at: "2015-12-20 11:20:04", updated_at: "2015-12-20 11:20:04", name: "System Admin", slug: "system-admin", description: nil, language: "simple", tsvector: "'admin':2A 'system':1A", honorific: nil, given_name: nil, family_name: nil, middle_names: nil, known_as: nil, suffix: nil, formal_address: nil, informal_address: nil, salutation: nil, born_on: nil, died_on: nil, gender_id: nil, name_order: nil, locale: nil, status: nil, login_name: "admin", api_key: "5aa7001622ea81ec1d5fb6674b074a71", password_digest: "$2a$10$4mIUUvt9YKHhuF5KM3A4NuvXXSVleau1Gln/qffci1z...", groups: nil, auth: nil>, "updated_by"=>nil, "slug"=>nil, "id"=>nil, "mail_address"=>nil} 
2.2.2 :007 > 

kipcole9 avatar Dec 23 '15 09:12 kipcole9

I don't understand, please show me your BlogRepresenter.

I am guessing your users property is typed but doesn't have a representer assigned, otherwise Representable would never call to_hash on an object.

apotonick avatar Dec 23 '15 09:12 apotonick

Ah, ok, no, if you have an object assigned to a scalar property, it will simply call to_s which results in the document you posted.

apotonick avatar Dec 23 '15 09:12 apotonick

The rule in all my gems is: they don't guess anything. If you want the created_at to be represented as a user, you have to say

property :created_at, decorator: UserRepresenter

apotonick avatar Dec 23 '15 09:12 apotonick

Nick, got it! Thanks, been a loooooong day and that is, I think, the last piece of my puzzle (and all good running on roar master, thanks for the tip)

kipcole9 avatar Dec 23 '15 09:12 kipcole9

Time for a beer then!

BTW, for quicker support, join us here: https://gitter.im/trailblazer/chat

apotonick avatar Dec 23 '15 09:12 apotonick