{"action":"created","issue":{"url":"https://api.github.com/repos/jsonapi-suite/jsonapi_compliable/issues/113","repository_url":"https://api.github.com/repos/jsonapi-suite/jsonapi_compliable","labels_url":"https://api.github.com/repos/jsonapi-suite/jsonapi_compliable/issues/113/labels{/name}","comments_url":"https://api.github.com/repos/jsonapi-suite/jsonapi_compliable/issues/113/comments","events_url":"https://api.github.com/repos/jsonapi-suite/jsonapi_compliable/issues/113/events","html_url":"https://github.com/jsonapi-suite/jsonapi_compliable/pull/113","id":335469662,"node_id":"MDExOlB1bGxSZXF1ZXN0MTk3MTYwOTYz","number":113,"title":"Add type checking/coercion to filters and reads","user":{"login":"richmolj","id":55264,"node_id":"MDQ6VXNlcjU1MjY0","avatar_url":"https://avatars1.githubusercontent.com/u/55264?v=4","gravatar_id":"","url":"https://api.github.com/users/richmolj","html_url":"https://github.com/richmolj","followers_url":"https://api.github.com/users/richmolj/followers","following_url":"https://api.github.com/users/richmolj/following{/other_user}","gists_url":"https://api.github.com/users/richmolj/gists{/gist_id}","starred_url":"https://api.github.com/users/richmolj/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/richmolj/subscriptions","organizations_url":"https://api.github.com/users/richmolj/orgs","repos_url":"https://api.github.com/users/richmolj/repos","events_url":"https://api.github.com/users/richmolj/events{/privacy}","received_events_url":"https://api.github.com/users/richmolj/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2018-06-25T15:59:26Z","updated_at":"2018-06-25T16:00:02Z","closed_at":null,"author_association":"CONTRIBUTOR","pull_request":{"url":"https://api.github.com/repos/jsonapi-suite/jsonapi_compliable/pulls/113","html_url":"https://github.com/jsonapi-suite/jsonapi_compliable/pull/113","diff_url":"https://github.com/jsonapi-suite/jsonapi_compliable/pull/113.diff","patch_url":"https://github.com/jsonapi-suite/jsonapi_compliable/pull/113.patch"},"body":"This adds `dry-types` as a dependency to do runtime type-checking of\r\nserialized response and filters. It will first attempt to coerce the\r\nvalue, then raise an error if it cannot coerce or is still the wrong\r\ntime post-coercion.\r\n\r\nEach attribute 'type' is really 4 different types: what we want for\r\nreads, writes, filters, and tests. For example, filters should not\r\naccept `null` by default, but serialization *should* accept `null`.\r\nFor tests, we want to assert the final value of DateTime is an iso8601\r\nstring, but for serialization we just want DateTime.\r\n\r\nThe best way to see the behavior of individual types is\r\n`spec/serialization_spec.rb` and `spec/filtering_spec.rb`. The general\r\nlogic is \"lean towards strict, and coerce only as a 'nice to have'\".\r\n\r\nOne issue is that there isn't a common error class. `dry-types` itself\r\nwill sometimes raise `ConstraintError`, `ArgumentError`, or `TypeError`.\r\nWhile we could rescue these and raise a general exception, it would come\r\nat the cost of hiding *real* errors for custom types and add a level of\r\nindirection when debugging. So I have chosen to leave as-is for now.\r\n\r\n```ruby\r\n # Default types\r\nattribute :foo, :string\r\nattribute :foo, :integer\r\n # BigDecimal vs Float\r\n # Note json decimals must be strings to preserve precision!\r\nattribute :foo, :decimal\r\nattribute :foo, :float\r\nattribute :foo, :boolean\r\nattribute :foo, :date\r\nattribute :foo, :datetime\r\nattribute :foo, :hash\r\nattribute :foo, :array\r\n\r\n # All of these can be arrays\r\nattribute :foo, :array_of_strings\r\nattribute :foo, :array_of_floats\r\n```\r\n\r\nOverride types:\r\n\r\n```ruby\r\nJsonapiCompliable::Types[:integer] = {\r\n  read: MyType,\r\n  write: MyType,\r\n  params: MyType,\r\n  test: MyType\r\n}\r\n```\r\n\r\nProvide custom types:\r\n\r\n```ruby\r\nStatusType = Types::Strict::String.enum('draft', 'published', 'archived')\r\nJsonapiCompliable::Types[:status] = StatusType # use for all\r\n  # or\r\nJsonapiCompliable::Types[:status] = { read: StatusType, ... }\r\n```\r\n\r\n`dry-types` supports hash schemas as well for nested json attributes:\r\n\r\n```ruby\r\nmeta = Types::Hash.schema({\r\n  foo: Dry::Types['strict.string'],\r\n  bar: Dry::Types['strict.integer']\r\n})\r\nJsonapiCompliable::Types[:meta] = meta\r\n\r\nattribute :foo, :meta\r\n```"},"comment":{"url":"https://api.github.com/repos/jsonapi-suite/jsonapi_compliable/issues/comments/400004283","html_url":"https://github.com/jsonapi-suite/jsonapi_compliable/pull/113#issuecomment-400004283","issue_url":"https://api.github.com/repos/jsonapi-suite/jsonapi_compliable/issues/113","id":400004283,"node_id":"MDEyOklzc3VlQ29tbWVudDQwMDAwNDI4Mw==","user":{"login":"richmolj","id":55264,"node_id":"MDQ6VXNlcjU1MjY0","avatar_url":"https://avatars1.githubusercontent.com/u/55264?v=4","gravatar_id":"","url":"https://api.github.com/users/richmolj","html_url":"https://github.com/richmolj","followers_url":"https://api.github.com/users/richmolj/followers","following_url":"https://api.github.com/users/richmolj/following{/other_user}","gists_url":"https://api.github.com/users/richmolj/gists{/gist_id}","starred_url":"https://api.github.com/users/richmolj/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/richmolj/subscriptions","organizations_url":"https://api.github.com/users/richmolj/orgs","repos_url":"https://api.github.com/users/richmolj/repos","events_url":"https://api.github.com/users/richmolj/events{/privacy}","received_events_url":"https://api.github.com/users/richmolj/received_events","type":"User","site_admin":false},"created_at":"2018-06-25T16:00:02Z","updated_at":"2018-06-25T16:00:02Z","author_association":"CONTRIBUTOR","body":"@wadetandy on top of https://github.com/jsonapi-suite/jsonapi_compliable/pull/112"}}
{"actor":{"display_login":"richmolj"}}