{"action":"created","comment":{"url":"https://api.github.com/repos/hanami/controller/pulls/comments/73405578","id":73405578,"diff_hunk":"@@ -0,0 +1,99 @@\n+module Hanami\n+  module Action\n+    module Exposable\n+      # Guard for Exposures API.\n+      # Prevents exposure of reserved words\n+      #\n+      # @since x.x.x\n+      #\n+      # @see Hanami::Action::Exposable::Guard::ClassMethods#expose\n+      # @see Hanami::Action::Exposable::Guard::ClassMethods#reserved_word?\n+      module Guard\n+        # Override Ruby's hook for modules.\n+        # It prepends a guard for the exposures logic\n+        #\n+        # @param base [Class] the target action\n+        #\n+        # @since x.x.x\n+        # @api private\n+        #\n+        # @see http://www.ruby-doc.org/core-2.1.2/Module.html#method-i-included\n+        def self.included(base)\n+          class << base\n+            prepend ClassMethods\n+          end\n+        end\n+\n+        # Exposure of reserved words\n+        #\n+        # @since x.x.x\n+        class IllegalExposeError < ::StandardError\n+        end\n+\n+        # Exposures API Guard class methods\n+        #\n+        # @since x.x.x\n+        # @api private\n+        module ClassMethods\n+          # Prevents exposure if names contain a reserved word.\n+          #\n+          # @param names [Array<Symbol>] the name(s) of the attribute(s) to be\n+          #   exposed\n+          #\n+          # @return [void]\n+          #\n+          # @since x.x.x\n+          def expose(*names)\n+            detect_reserved_words!(names)\n+\n+            super\n+          end\n+\n+          private\n+\n+          # Raises error if given names  contain a reserved word.\n+          #\n+          # @param names [Array<Symbol>] a list of names to be checked.\n+          #\n+          # @return [void]\n+          #\n+          # @raise [IllegalExposeError] if names contain one or more of reserved\n+          #   words\n+          #\n+          # @since x.x.x\n+          # @api private\n+          def detect_reserved_words!(names)\n+            names.each do |name|\n+              if reserved_word?(name)\n+                error_text = \"#{name} is a reserved word. It cannot be exposured\"\n+                raise IllegalExposeError, error_text","path":"lib/hanami/action/exposable/guard.rb","position":69,"original_position":69,"commit_id":"cb8886e8c347db224b34014059ebf87b721e19c6","original_commit_id":"cb8886e8c347db224b34014059ebf87b721e19c6","user":{"login":"cllns","id":632942,"avatar_url":"https://avatars.githubusercontent.com/u/632942?v=3","gravatar_id":"","url":"https://api.github.com/users/cllns","html_url":"https://github.com/cllns","followers_url":"https://api.github.com/users/cllns/followers","following_url":"https://api.github.com/users/cllns/following{/other_user}","gists_url":"https://api.github.com/users/cllns/gists{/gist_id}","starred_url":"https://api.github.com/users/cllns/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cllns/subscriptions","organizations_url":"https://api.github.com/users/cllns/orgs","repos_url":"https://api.github.com/users/cllns/repos","events_url":"https://api.github.com/users/cllns/events{/privacy}","received_events_url":"https://api.github.com/users/cllns/received_events","type":"User","site_admin":false},"body":"We don't need to define `error_text` here. You can break it across two lines after the comma to keep it under 80 characters\r\n```\r\n  raise IllegalExposeError, \r\n    \"...\"\r\n```","created_at":"2016-08-03T19:37:46Z","updated_at":"2016-08-03T19:37:46Z","html_url":"https://github.com/hanami/controller/pull/174#discussion_r73405578","pull_request_url":"https://api.github.com/repos/hanami/controller/pulls/174","_links":{"self":{"href":"https://api.github.com/repos/hanami/controller/pulls/comments/73405578"},"html":{"href":"https://github.com/hanami/controller/pull/174#discussion_r73405578"},"pull_request":{"href":"https://api.github.com/repos/hanami/controller/pulls/174"}}},"pull_request":{"url":"https://api.github.com/repos/hanami/controller/pulls/174","id":79951108,"html_url":"https://github.com/hanami/controller/pull/174","diff_url":"https://github.com/hanami/controller/pull/174.diff","patch_url":"https://github.com/hanami/controller/pull/174.patch","issue_url":"https://api.github.com/repos/hanami/controller/issues/174","number":174,"state":"open","locked":false,"title":"Raise error on reserved word exposure.","user":{"login":"akhramov","id":5289700,"avatar_url":"https://avatars.githubusercontent.com/u/5289700?v=3","gravatar_id":"","url":"https://api.github.com/users/akhramov","html_url":"https://github.com/akhramov","followers_url":"https://api.github.com/users/akhramov/followers","following_url":"https://api.github.com/users/akhramov/following{/other_user}","gists_url":"https://api.github.com/users/akhramov/gists{/gist_id}","starred_url":"https://api.github.com/users/akhramov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/akhramov/subscriptions","organizations_url":"https://api.github.com/users/akhramov/orgs","repos_url":"https://api.github.com/users/akhramov/repos","events_url":"https://api.github.com/users/akhramov/events{/privacy}","received_events_url":"https://api.github.com/users/akhramov/received_events","type":"User","site_admin":false},"body":"Closes #158\r\n(following text is extracted from [comment](https://github.com/hanami/controller/issues/158#issuecomment-234843765))\r\n\r\nI think we can go with guard module. The idea behind is dead simple:\r\n* Create a module implementing `#expose` method, which raises an exception if given list of words contains one or more reserved word. Otherwise it calls super.\r\n* Prepend this module to an action.\r\n* Introduce an alias method for `#expose` (`#expose!` or `#_expose`) for internal usage. This alias won't be watched by the guard so no exceptions are raised.\r\n","created_at":"2016-08-03T18:01:39Z","updated_at":"2016-08-03T19:37:46Z","closed_at":null,"merged_at":null,"merge_commit_sha":"d48f3501a0c54121c64ff301cc2eee8cf413b953","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/hanami/controller/pulls/174/commits","review_comments_url":"https://api.github.com/repos/hanami/controller/pulls/174/comments","review_comment_url":"https://api.github.com/repos/hanami/controller/pulls/comments{/number}","comments_url":"https://api.github.com/repos/hanami/controller/issues/174/comments","statuses_url":"https://api.github.com/repos/hanami/controller/statuses/cb8886e8c347db224b34014059ebf87b721e19c6","head":{"label":"akhramov:feature/158-raise-exception-for-reserved-words","ref":"feature/158-raise-exception-for-reserved-words","sha":"cb8886e8c347db224b34014059ebf87b721e19c6","user":{"login":"akhramov","id":5289700,"avatar_url":"https://avatars.githubusercontent.com/u/5289700?v=3","gravatar_id":"","url":"https://api.github.com/users/akhramov","html_url":"https://github.com/akhramov","followers_url":"https://api.github.com/users/akhramov/followers","following_url":"https://api.github.com/users/akhramov/following{/other_user}","gists_url":"https://api.github.com/users/akhramov/gists{/gist_id}","starred_url":"https://api.github.com/users/akhramov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/akhramov/subscriptions","organizations_url":"https://api.github.com/users/akhramov/orgs","repos_url":"https://api.github.com/users/akhramov/repos","events_url":"https://api.github.com/users/akhramov/events{/privacy}","received_events_url":"https://api.github.com/users/akhramov/received_events","type":"User","site_admin":false},"repo":{"id":63533081,"name":"controller","full_name":"akhramov/controller","owner":{"login":"akhramov","id":5289700,"avatar_url":"https://avatars.githubusercontent.com/u/5289700?v=3","gravatar_id":"","url":"https://api.github.com/users/akhramov","html_url":"https://github.com/akhramov","followers_url":"https://api.github.com/users/akhramov/followers","following_url":"https://api.github.com/users/akhramov/following{/other_user}","gists_url":"https://api.github.com/users/akhramov/gists{/gist_id}","starred_url":"https://api.github.com/users/akhramov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/akhramov/subscriptions","organizations_url":"https://api.github.com/users/akhramov/orgs","repos_url":"https://api.github.com/users/akhramov/repos","events_url":"https://api.github.com/users/akhramov/events{/privacy}","received_events_url":"https://api.github.com/users/akhramov/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/akhramov/controller","description":"Complete, fast and testable actions for Rack and Hanami","fork":true,"url":"https://api.github.com/repos/akhramov/controller","forks_url":"https://api.github.com/repos/akhramov/controller/forks","keys_url":"https://api.github.com/repos/akhramov/controller/keys{/key_id}","collaborators_url":"https://api.github.com/repos/akhramov/controller/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/akhramov/controller/teams","hooks_url":"https://api.github.com/repos/akhramov/controller/hooks","issue_events_url":"https://api.github.com/repos/akhramov/controller/issues/events{/number}","events_url":"https://api.github.com/repos/akhramov/controller/events","assignees_url":"https://api.github.com/repos/akhramov/controller/assignees{/user}","branches_url":"https://api.github.com/repos/akhramov/controller/branches{/branch}","tags_url":"https://api.github.com/repos/akhramov/controller/tags","blobs_url":"https://api.github.com/repos/akhramov/controller/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/akhramov/controller/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/akhramov/controller/git/refs{/sha}","trees_url":"https://api.github.com/repos/akhramov/controller/git/trees{/sha}","statuses_url":"https://api.github.com/repos/akhramov/controller/statuses/{sha}","languages_url":"https://api.github.com/repos/akhramov/controller/languages","stargazers_url":"https://api.github.com/repos/akhramov/controller/stargazers","contributors_url":"https://api.github.com/repos/akhramov/controller/contributors","subscribers_url":"https://api.github.com/repos/akhramov/controller/subscribers","subscription_url":"https://api.github.com/repos/akhramov/controller/subscription","commits_url":"https://api.github.com/repos/akhramov/controller/commits{/sha}","git_commits_url":"https://api.github.com/repos/akhramov/controller/git/commits{/sha}","comments_url":"https://api.github.com/repos/akhramov/controller/comments{/number}","issue_comment_url":"https://api.github.com/repos/akhramov/controller/issues/comments{/number}","contents_url":"https://api.github.com/repos/akhramov/controller/contents/{+path}","compare_url":"https://api.github.com/repos/akhramov/controller/compare/{base}...{head}","merges_url":"https://api.github.com/repos/akhramov/controller/merges","archive_url":"https://api.github.com/repos/akhramov/controller/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/akhramov/controller/downloads","issues_url":"https://api.github.com/repos/akhramov/controller/issues{/number}","pulls_url":"https://api.github.com/repos/akhramov/controller/pulls{/number}","milestones_url":"https://api.github.com/repos/akhramov/controller/milestones{/number}","notifications_url":"https://api.github.com/repos/akhramov/controller/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/akhramov/controller/labels{/name}","releases_url":"https://api.github.com/repos/akhramov/controller/releases{/id}","deployments_url":"https://api.github.com/repos/akhramov/controller/deployments","created_at":"2016-07-17T13:24:05Z","updated_at":"2016-07-17T13:24:06Z","pushed_at":"2016-07-24T16:06:32Z","git_url":"git://github.com/akhramov/controller.git","ssh_url":"git@github.com:akhramov/controller.git","clone_url":"https://github.com/akhramov/controller.git","svn_url":"https://github.com/akhramov/controller","homepage":"","size":855,"stargazers_count":0,"watchers_count":0,"language":"Ruby","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"hanami:master","ref":"master","sha":"1a3bef405fdb41e89c0d06f848d33e64554658f0","user":{"login":"hanami","id":3210273,"avatar_url":"https://avatars.githubusercontent.com/u/3210273?v=3","gravatar_id":"","url":"https://api.github.com/users/hanami","html_url":"https://github.com/hanami","followers_url":"https://api.github.com/users/hanami/followers","following_url":"https://api.github.com/users/hanami/following{/other_user}","gists_url":"https://api.github.com/users/hanami/gists{/gist_id}","starred_url":"https://api.github.com/users/hanami/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hanami/subscriptions","organizations_url":"https://api.github.com/users/hanami/orgs","repos_url":"https://api.github.com/users/hanami/repos","events_url":"https://api.github.com/users/hanami/events{/privacy}","received_events_url":"https://api.github.com/users/hanami/received_events","type":"Organization","site_admin":false},"repo":{"id":10932604,"name":"controller","full_name":"hanami/controller","owner":{"login":"hanami","id":3210273,"avatar_url":"https://avatars.githubusercontent.com/u/3210273?v=3","gravatar_id":"","url":"https://api.github.com/users/hanami","html_url":"https://github.com/hanami","followers_url":"https://api.github.com/users/hanami/followers","following_url":"https://api.github.com/users/hanami/following{/other_user}","gists_url":"https://api.github.com/users/hanami/gists{/gist_id}","starred_url":"https://api.github.com/users/hanami/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hanami/subscriptions","organizations_url":"https://api.github.com/users/hanami/orgs","repos_url":"https://api.github.com/users/hanami/repos","events_url":"https://api.github.com/users/hanami/events{/privacy}","received_events_url":"https://api.github.com/users/hanami/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/hanami/controller","description":"Complete, fast and testable actions for Rack and Hanami","fork":false,"url":"https://api.github.com/repos/hanami/controller","forks_url":"https://api.github.com/repos/hanami/controller/forks","keys_url":"https://api.github.com/repos/hanami/controller/keys{/key_id}","collaborators_url":"https://api.github.com/repos/hanami/controller/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/hanami/controller/teams","hooks_url":"https://api.github.com/repos/hanami/controller/hooks","issue_events_url":"https://api.github.com/repos/hanami/controller/issues/events{/number}","events_url":"https://api.github.com/repos/hanami/controller/events","assignees_url":"https://api.github.com/repos/hanami/controller/assignees{/user}","branches_url":"https://api.github.com/repos/hanami/controller/branches{/branch}","tags_url":"https://api.github.com/repos/hanami/controller/tags","blobs_url":"https://api.github.com/repos/hanami/controller/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/hanami/controller/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/hanami/controller/git/refs{/sha}","trees_url":"https://api.github.com/repos/hanami/controller/git/trees{/sha}","statuses_url":"https://api.github.com/repos/hanami/controller/statuses/{sha}","languages_url":"https://api.github.com/repos/hanami/controller/languages","stargazers_url":"https://api.github.com/repos/hanami/controller/stargazers","contributors_url":"https://api.github.com/repos/hanami/controller/contributors","subscribers_url":"https://api.github.com/repos/hanami/controller/subscribers","subscription_url":"https://api.github.com/repos/hanami/controller/subscription","commits_url":"https://api.github.com/repos/hanami/controller/commits{/sha}","git_commits_url":"https://api.github.com/repos/hanami/controller/git/commits{/sha}","comments_url":"https://api.github.com/repos/hanami/controller/comments{/number}","issue_comment_url":"https://api.github.com/repos/hanami/controller/issues/comments{/number}","contents_url":"https://api.github.com/repos/hanami/controller/contents/{+path}","compare_url":"https://api.github.com/repos/hanami/controller/compare/{base}...{head}","merges_url":"https://api.github.com/repos/hanami/controller/merges","archive_url":"https://api.github.com/repos/hanami/controller/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/hanami/controller/downloads","issues_url":"https://api.github.com/repos/hanami/controller/issues{/number}","pulls_url":"https://api.github.com/repos/hanami/controller/pulls{/number}","milestones_url":"https://api.github.com/repos/hanami/controller/milestones{/number}","notifications_url":"https://api.github.com/repos/hanami/controller/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/hanami/controller/labels{/name}","releases_url":"https://api.github.com/repos/hanami/controller/releases{/id}","deployments_url":"https://api.github.com/repos/hanami/controller/deployments","created_at":"2013-06-25T08:20:55Z","updated_at":"2016-08-02T16:39:21Z","pushed_at":"2016-08-03T18:01:39Z","git_url":"git://github.com/hanami/controller.git","ssh_url":"git@github.com:hanami/controller.git","clone_url":"https://github.com/hanami/controller.git","svn_url":"https://github.com/hanami/controller","homepage":"","size":904,"stargazers_count":169,"watchers_count":169,"language":"Ruby","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":81,"mirror_url":null,"open_issues_count":13,"forks":81,"open_issues":13,"watchers":169,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/hanami/controller/pulls/174"},"html":{"href":"https://github.com/hanami/controller/pull/174"},"issue":{"href":"https://api.github.com/repos/hanami/controller/issues/174"},"comments":{"href":"https://api.github.com/repos/hanami/controller/issues/174/comments"},"review_comments":{"href":"https://api.github.com/repos/hanami/controller/pulls/174/comments"},"review_comment":{"href":"https://api.github.com/repos/hanami/controller/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/hanami/controller/pulls/174/commits"},"statuses":{"href":"https://api.github.com/repos/hanami/controller/statuses/cb8886e8c347db224b34014059ebf87b721e19c6"}}}}
{"actor":{"display_login":"cllns"}}