{"action":"created","issue":{"url":"https://api.github.com/repos/FCO/Red/issues/122","repository_url":"https://api.github.com/repos/FCO/Red","labels_url":"https://api.github.com/repos/FCO/Red/issues/122/labels{/name}","comments_url":"https://api.github.com/repos/FCO/Red/issues/122/comments","events_url":"https://api.github.com/repos/FCO/Red/issues/122/events","html_url":"https://github.com/FCO/Red/issues/122","id":420575337,"node_id":"MDU6SXNzdWU0MjA1NzUzMzc=","number":122,"title":"Provide a ```.perl``` for model objects that only includes the columns, not relations and internals.","user":{"login":"jonathanstowe","id":736419,"node_id":"MDQ6VXNlcjczNjQxOQ==","avatar_url":"https://avatars3.githubusercontent.com/u/736419?v=4","gravatar_id":"","url":"https://api.github.com/users/jonathanstowe","html_url":"https://github.com/jonathanstowe","followers_url":"https://api.github.com/users/jonathanstowe/followers","following_url":"https://api.github.com/users/jonathanstowe/following{/other_user}","gists_url":"https://api.github.com/users/jonathanstowe/gists{/gist_id}","starred_url":"https://api.github.com/users/jonathanstowe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jonathanstowe/subscriptions","organizations_url":"https://api.github.com/users/jonathanstowe/orgs","repos_url":"https://api.github.com/users/jonathanstowe/repos","events_url":"https://api.github.com/users/jonathanstowe/events{/privacy}","received_events_url":"https://api.github.com/users/jonathanstowe/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":7,"created_at":"2019-03-13T15:47:16Z","updated_at":"2019-03-14T09:06:38Z","closed_at":"2019-03-14T09:06:38Z","author_association":"CONTRIBUTOR","body":"The default ```Mu.perl``` does something quite awful with the model objects, say :+1: \r\n\r\n```\r\nuse Red;\r\n\r\nmodel Foo { ... }\r\n\r\nmodel Zub {\r\n    has Int $.id is serial;\r\n    has Foo @.foos is relationship( { .zub-id });\r\n}\r\n\r\nmodel Foo  {\r\n    has Int $.id is serial;\r\n    has Str $.bar is column;\r\n    has Int $.zub-id is referencing( { Zub.id } );\r\n    has Zub $.zub is relationship( { .zub-id });\r\n}\r\n\r\nmy $*RED-DEBUG          = $_ with %*ENV<RED_DEBUG>;\r\nmy $*RED-DB             = database \"SQLite\", |(:database($_) with %*ENV<RED_DATABASE>);\r\n\r\nZub.^create-table;\r\nFoo.^create-table;\r\n\r\nmy $zub = Zub.^create;\r\nmy $one = $zub.foos.create( bar => \"one\" );\r\nmy $two = $zub.foos.create( bar => \"two\" );\r\n\r\nsay [ $one, $two ].perl;\r\n```\r\n\r\nMakes:\r\n\r\n```\r\n[Foo.new(id => 1, bar => \"one\", zub-id => 1, zub => Zub.new(id => 1, foos => Foo::ResultSeq.new(chain => Red::AST::Chained.new(filter => Red::AST::Eq.new(op => \"=\", returns => Bool, left => Red::Column.new(attr => foo.zub_id, attr-name => \"zub-id\", id => Bool::False, auto-increment => Bool::False, references => -> ;; $_? is raw { #`(Block|94023458453432) ... }, nullable => Bool::True, name => \"zub_id\", name-alias => \"zub_id\", type => Str, inflate => { ... }, deflate => { ... }, computation => Any, model-name => Str, column-name => Str, require => Str), right => Red::AST::Value.new(value => 1, column => Red::Column, type => Int), bind-left => Bool::False, bind-right => Bool::True), limit => Int, post => Callable, order => Array[Red::AST].new(), group => Array[Red::AST].new(), table-list => [], next => Red::AST::Chained), update => (my Red::AST %), comments => Array[Red::AST::Comment].new()))), Foo.new(id => 2, bar => \"two\", zub-id => 1, zub => Zub.new(id => 1, foos => Foo::ResultSeq.new(chain => Red::AST::Chained.new(filter => Red::AST::Eq.new(op => \"=\", returns => Bool, left => Red::Column.new(attr => foo.zub_id, attr-name => \"zub-id\", id => Bool::False, auto-increment => Bool::False, references => -> ;; $_? is raw { #`(Block|94023458453432) ... }, nullable => Bool::True, name => \"zub_id\", name-alias => \"zub_id\", type => Str, inflate => { ... }, deflate => { ... }, computation => Any, model-name => Str, column-name => Str, require => Str), right => Red::AST::Value.new(value => 1, column => Red::Column, type => Int), bind-left => Bool::False, bind-right => Bool::True), limit => Int, post => Callable, order => Array[Red::AST].new(), group => Array[Red::AST].new(), table-list => [], next => Red::AST::Chained), update => (my Red::AST %), comments => Array[Red::AST::Comment].new())))]\r\n```\r\n\r\nWhich is bad enough but this becomes serious when there is a circular relation between two objects, such as:\r\n\r\n```\r\nmodel Zub {\r\n    has Int $.id is serial;\r\n    has Int $.default-foo-id is referencing( { Foo.id } );\r\n    has Foo $.default-foo is relationship( { .default-foo-id });\r\n    has Foo @.foos is relationship( { .zub-id });\r\n}\r\n\r\nmodel Foo  {\r\n    has Int $.id is serial;\r\n    has Str $.bar is column;\r\n    has Int $.zub-id is referencing( { Zub.id } );\r\n    has Zub $.zub is relationship( { .zub-id });\r\n}\r\n```\r\n\r\nWhich becomes catastrophic with the ```.perl``` actually iterating eternally over the circult Foo->Zub->Foo  relationship.  I think this would be a problem with any circular data structures but this is quite a common pattern in DB applications.\r\n\r\nAlso limiting the ```.perl``` to just the columns and omitting the relationships would limit the size of the output where there is a large, complex schema.\r\n\r\nBTW I fix the problem that manifested in ```Tinky::DB``` by implementing a ```.perl``` in ```Tinky::DB::Workflow``` that broke the loop.\r\n\r\nI initially got confused by this as the problem was being seen in:\r\n\r\n```\r\nis-deeply $ticket-a.next-states, [ $state-stalled, $state-complete ], \"Next-states gives what expected\";\r\n```\r\n\r\nAnd it transpires that ```is-deeply``` fails back to comparing the ```.perl``` of  both sides.\r\n"},"comment":{"url":"https://api.github.com/repos/FCO/Red/issues/comments/472763157","html_url":"https://github.com/FCO/Red/issues/122#issuecomment-472763157","issue_url":"https://api.github.com/repos/FCO/Red/issues/122","id":472763157,"node_id":"MDEyOklzc3VlQ29tbWVudDQ3Mjc2MzE1Nw==","user":{"login":"jonathanstowe","id":736419,"node_id":"MDQ6VXNlcjczNjQxOQ==","avatar_url":"https://avatars3.githubusercontent.com/u/736419?v=4","gravatar_id":"","url":"https://api.github.com/users/jonathanstowe","html_url":"https://github.com/jonathanstowe","followers_url":"https://api.github.com/users/jonathanstowe/followers","following_url":"https://api.github.com/users/jonathanstowe/following{/other_user}","gists_url":"https://api.github.com/users/jonathanstowe/gists{/gist_id}","starred_url":"https://api.github.com/users/jonathanstowe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jonathanstowe/subscriptions","organizations_url":"https://api.github.com/users/jonathanstowe/orgs","repos_url":"https://api.github.com/users/jonathanstowe/repos","events_url":"https://api.github.com/users/jonathanstowe/events{/privacy}","received_events_url":"https://api.github.com/users/jonathanstowe/received_events","type":"User","site_admin":false},"created_at":"2019-03-14T09:06:38Z","updated_at":"2019-03-14T09:06:38Z","author_association":"CONTRIBUTOR","body":"Yep that is all good:\r\n\r\n```\r\n[Foo.new(id => 1, bar => \"one\", zub-id => 1), Foo.new(id => 2, bar => \"two\", zub-id => 1)]\r\n```\r\n\r\nI'd say that is good to be closed now."}}
{"actor":{"display_login":"jonathanstowe"}}