{"action":"created","comment":{"url":"https://api.github.com/repos/rspec/rspec-expectations/pulls/comments/23657184","id":23657184,"diff_hunk":"@@ -375,6 +379,155 @@ def expect_block\n             EOS\n           end\n         end\n+\n+        context \"when the first matcher is diffable\" do\n+          subject { include(\"foo\").and be_a(String) }\n+\n+          it 'is diffable' do\n+            expect(subject).to be_diffable\n+          end\n+\n+          context \"when only first matcher fails\" do\n+            it 'fails with a message containing a diff for first matcher' do\n+              expected_failure = dedent(<<-EOS)\n+                |Diff for (include \"foo\"):\n+                |@@ -1,2 +1,3 @@\n+                |-foo\n+                |+baz\n+                |+bar\n+              EOS\n+\n+              expect {\n+                expect(dedent(<<-EOS)).to subject\n+                  |baz\n+                  |bar\n+                EOS\n+              }.to fail_matching(expected_failure)\n+            end\n+          end\n+\n+          context \"when only second matcher fails\" do\n+            subject { include(\"baz\").and be_a(Fixnum) }\n+\n+            it 'fails with a message not containing a diff for first matcher' do\n+              expect {\n+                expect(dedent(<<-EOS)).to subject\n+                  |baz\n+                  |bar\n+                EOS\n+              }.to fail_matching(a_string_excluding \"Diff\")\n+            end\n+          end\n+\n+          context \"when both matcher fail\" do\n+            subject { include(\"foo\").and eq(35) }\n+\n+            it \"fails with a message containing a diff with first matcher\" do\n+              expected_failure = dedent(<<-EOS)\n+              |   expected \"baz\\\\nbar\" to include \"foo\"\n+              |\n+              |...and:\n+              |\n+              |   expected: 35\n+              |        got: \"baz\\\\nbar\"\n+              |\n+              |   (compared using ==)\n+              |\n+              |Diff for (include \"foo\"):\n+              |@@ -1,2 +1,3 @@\n+              |-foo\n+              |+baz\n+              |+bar\n+            EOS","path":"spec/rspec/matchers/built_in/compound_spec.rb","position":74,"original_position":74,"commit_id":"d659ec528109997fb3c59c9a52ddfe145d3ed95d","original_commit_id":"d659ec528109997fb3c59c9a52ddfe145d3ed95d","user":{"login":"myronmarston","id":49391,"avatar_url":"https://avatars.githubusercontent.com/u/49391?v=3","gravatar_id":"","url":"https://api.github.com/users/myronmarston","html_url":"https://github.com/myronmarston","followers_url":"https://api.github.com/users/myronmarston/followers","following_url":"https://api.github.com/users/myronmarston/following{/other_user}","gists_url":"https://api.github.com/users/myronmarston/gists{/gist_id}","starred_url":"https://api.github.com/users/myronmarston/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/myronmarston/subscriptions","organizations_url":"https://api.github.com/users/myronmarston/orgs","repos_url":"https://api.github.com/users/myronmarston/repos","events_url":"https://api.github.com/users/myronmarston/events{/privacy}","received_events_url":"https://api.github.com/users/myronmarston/received_events","type":"User","site_admin":false},"body":"I think this heredoc should be indented 2 spaces to be consistent.","created_at":"2015-01-28T00:38:39Z","updated_at":"2015-01-28T00:38:39Z","html_url":"https://github.com/rspec/rspec-expectations/pull/713#discussion_r23657184","pull_request_url":"https://api.github.com/repos/rspec/rspec-expectations/pulls/713","_links":{"self":{"href":"https://api.github.com/repos/rspec/rspec-expectations/pulls/comments/23657184"},"html":{"href":"https://github.com/rspec/rspec-expectations/pull/713#discussion_r23657184"},"pull_request":{"href":"https://api.github.com/repos/rspec/rspec-expectations/pulls/713"}}},"pull_request":{"url":"https://api.github.com/repos/rspec/rspec-expectations/pulls/713","id":27262053,"html_url":"https://github.com/rspec/rspec-expectations/pull/713","diff_url":"https://github.com/rspec/rspec-expectations/pull/713.diff","patch_url":"https://github.com/rspec/rspec-expectations/pull/713.patch","issue_url":"https://api.github.com/repos/rspec/rspec-expectations/issues/713","number":713,"state":"open","locked":false,"title":"Compound matcher diff","user":{"login":"waterlink","id":609046,"avatar_url":"https://avatars.githubusercontent.com/u/609046?v=3","gravatar_id":"","url":"https://api.github.com/users/waterlink","html_url":"https://github.com/waterlink","followers_url":"https://api.github.com/users/waterlink/followers","following_url":"https://api.github.com/users/waterlink/following{/other_user}","gists_url":"https://api.github.com/users/waterlink/gists{/gist_id}","starred_url":"https://api.github.com/users/waterlink/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/waterlink/subscriptions","organizations_url":"https://api.github.com/users/waterlink/orgs","repos_url":"https://api.github.com/users/waterlink/repos","events_url":"https://api.github.com/users/waterlink/events{/privacy}","received_events_url":"https://api.github.com/users/waterlink/received_events","type":"User","site_admin":false},"body":"related to #712 \r\n\r\nThis is work in progress but some input required.\r\n\r\nSo I tried first to approach it by using special return value from `#expected` - an instance of class `ExpectedForMultipleDiffs`, but it became a mess very fast.\r\nThen I tried to actually return more general `Expected` value and shifted responsibility of generating diffs to it.\r\nBut then it puzzled me, all the logic about composing `failure_message`-s of matchers is hidden inside of `CompoundMatcher`'s private methods, particularly in method `#failure_message`, and since diffs need to be injected inside of this `failure_message` at multiple places, I thought about actually having a special value for `failure_message` - `FailureMessage`\r\n\r\nSo the final idea is:\r\n- have a class `LazyFailureMessage` and shift responsibility of generating diffs to it\r\n- `lift` (or `coerce`) all `failure_message` values to it and give it a differ factory and let it return proper `failure_message` with diffs inside\r\n- allow some matchers (`Compound` and `All`) to make evaluation of `failure_message` lazy, allowing it to wait for differ to pass it around to child matchers\r\n\r\nYou can look at the commits, they currently non-squashed and show failed attempts to tackle it.\r\n\r\nBasically this variant of design works surprisingly well, but still it could be hard to understand, so I need some input and/or ideas. I thought, for example, about actually shifting responsibility of generating of `failure_message` for compound matchers somewhere outside of it - it could work out well too.\r\n\r\nIf this kind of design is ok to go, then I will just clean it up a bit and put some docs strings there.\r\n\r\n/cc @myronmarston @JonRowe ","created_at":"2015-01-13T10:46:20Z","updated_at":"2015-01-28T00:38:39Z","closed_at":null,"merged_at":null,"merge_commit_sha":"74568b192a193462bd6bb0decec5d710fcc400ec","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/rspec/rspec-expectations/pulls/713/commits","review_comments_url":"https://api.github.com/repos/rspec/rspec-expectations/pulls/713/comments","review_comment_url":"https://api.github.com/repos/rspec/rspec-expectations/pulls/comments/{number}","comments_url":"https://api.github.com/repos/rspec/rspec-expectations/issues/713/comments","statuses_url":"https://api.github.com/repos/rspec/rspec-expectations/statuses/d659ec528109997fb3c59c9a52ddfe145d3ed95d","head":{"label":"waterlink:compound_matcher_diff","ref":"compound_matcher_diff","sha":"d659ec528109997fb3c59c9a52ddfe145d3ed95d","user":{"login":"waterlink","id":609046,"avatar_url":"https://avatars.githubusercontent.com/u/609046?v=3","gravatar_id":"","url":"https://api.github.com/users/waterlink","html_url":"https://github.com/waterlink","followers_url":"https://api.github.com/users/waterlink/followers","following_url":"https://api.github.com/users/waterlink/following{/other_user}","gists_url":"https://api.github.com/users/waterlink/gists{/gist_id}","starred_url":"https://api.github.com/users/waterlink/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/waterlink/subscriptions","organizations_url":"https://api.github.com/users/waterlink/orgs","repos_url":"https://api.github.com/users/waterlink/repos","events_url":"https://api.github.com/users/waterlink/events{/privacy}","received_events_url":"https://api.github.com/users/waterlink/received_events","type":"User","site_admin":false},"repo":{"id":25056645,"name":"rspec-expectations","full_name":"waterlink/rspec-expectations","owner":{"login":"waterlink","id":609046,"avatar_url":"https://avatars.githubusercontent.com/u/609046?v=3","gravatar_id":"","url":"https://api.github.com/users/waterlink","html_url":"https://github.com/waterlink","followers_url":"https://api.github.com/users/waterlink/followers","following_url":"https://api.github.com/users/waterlink/following{/other_user}","gists_url":"https://api.github.com/users/waterlink/gists{/gist_id}","starred_url":"https://api.github.com/users/waterlink/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/waterlink/subscriptions","organizations_url":"https://api.github.com/users/waterlink/orgs","repos_url":"https://api.github.com/users/waterlink/repos","events_url":"https://api.github.com/users/waterlink/events{/privacy}","received_events_url":"https://api.github.com/users/waterlink/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/waterlink/rspec-expectations","description":"Provides a simple, readable API to express expected outcomes of a code example","fork":true,"url":"https://api.github.com/repos/waterlink/rspec-expectations","forks_url":"https://api.github.com/repos/waterlink/rspec-expectations/forks","keys_url":"https://api.github.com/repos/waterlink/rspec-expectations/keys{/key_id}","collaborators_url":"https://api.github.com/repos/waterlink/rspec-expectations/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/waterlink/rspec-expectations/teams","hooks_url":"https://api.github.com/repos/waterlink/rspec-expectations/hooks","issue_events_url":"https://api.github.com/repos/waterlink/rspec-expectations/issues/events{/number}","events_url":"https://api.github.com/repos/waterlink/rspec-expectations/events","assignees_url":"https://api.github.com/repos/waterlink/rspec-expectations/assignees{/user}","branches_url":"https://api.github.com/repos/waterlink/rspec-expectations/branches{/branch}","tags_url":"https://api.github.com/repos/waterlink/rspec-expectations/tags","blobs_url":"https://api.github.com/repos/waterlink/rspec-expectations/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/waterlink/rspec-expectations/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/waterlink/rspec-expectations/git/refs{/sha}","trees_url":"https://api.github.com/repos/waterlink/rspec-expectations/git/trees{/sha}","statuses_url":"https://api.github.com/repos/waterlink/rspec-expectations/statuses/{sha}","languages_url":"https://api.github.com/repos/waterlink/rspec-expectations/languages","stargazers_url":"https://api.github.com/repos/waterlink/rspec-expectations/stargazers","contributors_url":"https://api.github.com/repos/waterlink/rspec-expectations/contributors","subscribers_url":"https://api.github.com/repos/waterlink/rspec-expectations/subscribers","subscription_url":"https://api.github.com/repos/waterlink/rspec-expectations/subscription","commits_url":"https://api.github.com/repos/waterlink/rspec-expectations/commits{/sha}","git_commits_url":"https://api.github.com/repos/waterlink/rspec-expectations/git/commits{/sha}","comments_url":"https://api.github.com/repos/waterlink/rspec-expectations/comments{/number}","issue_comment_url":"https://api.github.com/repos/waterlink/rspec-expectations/issues/comments/{number}","contents_url":"https://api.github.com/repos/waterlink/rspec-expectations/contents/{+path}","compare_url":"https://api.github.com/repos/waterlink/rspec-expectations/compare/{base}...{head}","merges_url":"https://api.github.com/repos/waterlink/rspec-expectations/merges","archive_url":"https://api.github.com/repos/waterlink/rspec-expectations/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/waterlink/rspec-expectations/downloads","issues_url":"https://api.github.com/repos/waterlink/rspec-expectations/issues{/number}","pulls_url":"https://api.github.com/repos/waterlink/rspec-expectations/pulls{/number}","milestones_url":"https://api.github.com/repos/waterlink/rspec-expectations/milestones{/number}","notifications_url":"https://api.github.com/repos/waterlink/rspec-expectations/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/waterlink/rspec-expectations/labels{/name}","releases_url":"https://api.github.com/repos/waterlink/rspec-expectations/releases{/id}","created_at":"2014-10-10T23:17:26Z","updated_at":"2015-01-12T11:31:26Z","pushed_at":"2015-01-28T00:30:32Z","git_url":"git://github.com/waterlink/rspec-expectations.git","ssh_url":"git@github.com:waterlink/rspec-expectations.git","clone_url":"https://github.com/waterlink/rspec-expectations.git","svn_url":"https://github.com/waterlink/rspec-expectations","homepage":"http://relishapp.com/rspec/rspec-expectations","size":3507,"stargazers_count":0,"watchers_count":0,"language":"Ruby","has_issues":false,"has_downloads":false,"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":"rspec:master","ref":"master","sha":"45ff9faa26ea912d6b13d4044e5691b894d9fcc5","user":{"login":"rspec","id":22388,"avatar_url":"https://avatars.githubusercontent.com/u/22388?v=3","gravatar_id":"","url":"https://api.github.com/users/rspec","html_url":"https://github.com/rspec","followers_url":"https://api.github.com/users/rspec/followers","following_url":"https://api.github.com/users/rspec/following{/other_user}","gists_url":"https://api.github.com/users/rspec/gists{/gist_id}","starred_url":"https://api.github.com/users/rspec/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rspec/subscriptions","organizations_url":"https://api.github.com/users/rspec/orgs","repos_url":"https://api.github.com/users/rspec/repos","events_url":"https://api.github.com/users/rspec/events{/privacy}","received_events_url":"https://api.github.com/users/rspec/received_events","type":"Organization","site_admin":false},"repo":{"id":238986,"name":"rspec-expectations","full_name":"rspec/rspec-expectations","owner":{"login":"rspec","id":22388,"avatar_url":"https://avatars.githubusercontent.com/u/22388?v=3","gravatar_id":"","url":"https://api.github.com/users/rspec","html_url":"https://github.com/rspec","followers_url":"https://api.github.com/users/rspec/followers","following_url":"https://api.github.com/users/rspec/following{/other_user}","gists_url":"https://api.github.com/users/rspec/gists{/gist_id}","starred_url":"https://api.github.com/users/rspec/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rspec/subscriptions","organizations_url":"https://api.github.com/users/rspec/orgs","repos_url":"https://api.github.com/users/rspec/repos","events_url":"https://api.github.com/users/rspec/events{/privacy}","received_events_url":"https://api.github.com/users/rspec/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/rspec/rspec-expectations","description":"Provides a readable API to express expected outcomes of a code example","fork":false,"url":"https://api.github.com/repos/rspec/rspec-expectations","forks_url":"https://api.github.com/repos/rspec/rspec-expectations/forks","keys_url":"https://api.github.com/repos/rspec/rspec-expectations/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rspec/rspec-expectations/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rspec/rspec-expectations/teams","hooks_url":"https://api.github.com/repos/rspec/rspec-expectations/hooks","issue_events_url":"https://api.github.com/repos/rspec/rspec-expectations/issues/events{/number}","events_url":"https://api.github.com/repos/rspec/rspec-expectations/events","assignees_url":"https://api.github.com/repos/rspec/rspec-expectations/assignees{/user}","branches_url":"https://api.github.com/repos/rspec/rspec-expectations/branches{/branch}","tags_url":"https://api.github.com/repos/rspec/rspec-expectations/tags","blobs_url":"https://api.github.com/repos/rspec/rspec-expectations/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rspec/rspec-expectations/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rspec/rspec-expectations/git/refs{/sha}","trees_url":"https://api.github.com/repos/rspec/rspec-expectations/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rspec/rspec-expectations/statuses/{sha}","languages_url":"https://api.github.com/repos/rspec/rspec-expectations/languages","stargazers_url":"https://api.github.com/repos/rspec/rspec-expectations/stargazers","contributors_url":"https://api.github.com/repos/rspec/rspec-expectations/contributors","subscribers_url":"https://api.github.com/repos/rspec/rspec-expectations/subscribers","subscription_url":"https://api.github.com/repos/rspec/rspec-expectations/subscription","commits_url":"https://api.github.com/repos/rspec/rspec-expectations/commits{/sha}","git_commits_url":"https://api.github.com/repos/rspec/rspec-expectations/git/commits{/sha}","comments_url":"https://api.github.com/repos/rspec/rspec-expectations/comments{/number}","issue_comment_url":"https://api.github.com/repos/rspec/rspec-expectations/issues/comments/{number}","contents_url":"https://api.github.com/repos/rspec/rspec-expectations/contents/{+path}","compare_url":"https://api.github.com/repos/rspec/rspec-expectations/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rspec/rspec-expectations/merges","archive_url":"https://api.github.com/repos/rspec/rspec-expectations/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rspec/rspec-expectations/downloads","issues_url":"https://api.github.com/repos/rspec/rspec-expectations/issues{/number}","pulls_url":"https://api.github.com/repos/rspec/rspec-expectations/pulls{/number}","milestones_url":"https://api.github.com/repos/rspec/rspec-expectations/milestones{/number}","notifications_url":"https://api.github.com/repos/rspec/rspec-expectations/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rspec/rspec-expectations/labels{/name}","releases_url":"https://api.github.com/repos/rspec/rspec-expectations/releases{/id}","created_at":"2009-06-29T15:58:17Z","updated_at":"2015-01-27T23:55:42Z","pushed_at":"2015-01-22T22:51:08Z","git_url":"git://github.com/rspec/rspec-expectations.git","ssh_url":"git@github.com:rspec/rspec-expectations.git","clone_url":"https://github.com/rspec/rspec-expectations.git","svn_url":"https://github.com/rspec/rspec-expectations","homepage":"http://relishapp.com/rspec/rspec-expectations","size":7925,"stargazers_count":581,"watchers_count":581,"language":"Ruby","has_issues":true,"has_downloads":false,"has_wiki":false,"has_pages":false,"forks_count":194,"mirror_url":null,"open_issues_count":23,"forks":194,"open_issues":23,"watchers":581,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/rspec/rspec-expectations/pulls/713"},"html":{"href":"https://github.com/rspec/rspec-expectations/pull/713"},"issue":{"href":"https://api.github.com/repos/rspec/rspec-expectations/issues/713"},"comments":{"href":"https://api.github.com/repos/rspec/rspec-expectations/issues/713/comments"},"review_comments":{"href":"https://api.github.com/repos/rspec/rspec-expectations/pulls/713/comments"},"review_comment":{"href":"https://api.github.com/repos/rspec/rspec-expectations/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/rspec/rspec-expectations/pulls/713/commits"},"statuses":{"href":"https://api.github.com/repos/rspec/rspec-expectations/statuses/d659ec528109997fb3c59c9a52ddfe145d3ed95d"}}}}