{"action":"created","comment":{"url":"https://api.github.com/repos/elixir-lang/ecto/pulls/comments/34459156","id":34459156,"diff_hunk":"@@ -31,10 +44,142 @@ defmodule Ecto.EmbeddedTest do\n \n     assert Author.__schema__(:embed, :profile) ==\n       %Ecto.Embedded{field: :profile, cardinality: :one, owner: Author,\n-                     embed: Profile, container: nil}\n+                     embed: Profile, container: nil, changeset: :required_changeset}\n \n     assert Author.__schema__(:embed, :profiles) ==\n       %Ecto.Embedded{field: :profiles, cardinality: :many, owner: Author,\n-                     embed: Profile, container: :array}\n+                     embed: Profile, container: :array, changeset: :changeset}\n+  end\n+\n+\n+  test \"cast embeds_one with valid params\" do\n+    changeset = cast(%Author{}, %{\"profile\" => %{\"name\" => \"michal\"}}, ~w(profile))\n+    profile = changeset.changes.profile\n+    assert profile.changes == %{name: \"michal\"}\n+    assert profile.errors == []\n+    assert profile.status  == :insert\n+    assert profile.valid?\n+    assert changeset.valid?\n+  end\n+\n+  test \"cast embeds_one with invalid params\" do\n+    changeset = cast(%Author{}, %{\"profile\" => %{}}, ~w(profile))\n+    assert changeset.changes.profile.changes == %{}\n+    assert changeset.changes.profile.errors  == [name: \"can't be blank\"]\n+    assert changeset.changes.profile.status  == :insert\n+    refute changeset.changes.profile.valid?\n+    refute changeset.valid?\n+\n+    changeset = cast(%Author{}, %{\"profile\" => \"value\"}, ~w(profile))\n+    assert changeset.errors == [profile: \"is invalid\"]\n+    refute changeset.valid?\n+  end\n+\n+  test \"cast embeds_one with existing model updating\" do\n+    changeset = cast(%Author{profile: %Profile{name: \"michal\", id: \"michal\"}},\n+                     %{\"profile\" => %{\"name\" => \"new\", \"id\" => \"michal\"}}, ~w(profile))\n+    profile = changeset.changes.profile\n+    assert profile.changes == %{name: \"new\"}\n+    assert profile.errors  == []\n+    assert profile.status  == :update\n+    assert profile.valid?\n+    assert changeset.valid?\n+  end\n+\n+  test \"cast embeds_one with existing model replacing\" do\n+    changeset = cast(%Author{profile: %Profile{name: \"michal\", id: \"michal\"}},\n+                     %{\"profile\" => %{\"name\" => \"new\"}}, ~w(profile))\n+    profile = changeset.changes.profile\n+    assert profile.changes == %{name: \"new\"}\n+    assert profile.errors  == []\n+    assert profile.status  == :insert\n+    assert profile.valid?\n+    assert changeset.valid?\n+\n+    changeset = cast(%Author{profile: %Profile{name: \"michal\", id: \"michal\"}},\n+                     %{\"profile\" => %{\"name\" => \"new\", \"id\" => \"new\"}}, ~w(profile))\n+    profile = changeset.changes.profile\n+    assert profile.changes == %{name: \"new\", id: \"new\"}\n+    assert profile.errors  == []\n+    assert profile.status  == :insert\n+    assert profile.valid?\n+    assert changeset.valid?\n+  end\n+\n+  test \"cast embeds_one with custom changeset\" do\n+    changeset = cast(%Author{}, %{\"profile\" => %{\"name\" => \"michal\"}},\n+                     [profile: :optional_changeset])\n+    profile = changeset.changes.profile\n+    assert profile.changes == %{name: \"michal\"}\n+    assert profile.errors  == []\n+    assert profile.status  == :insert\n+    assert profile.valid?\n+    assert changeset.valid?\n+\n+    changeset = cast(%Author{}, %{\"profile\" => %{}}, [profile: :optional_changeset])\n+    profile = changeset.changes.profile\n+    assert profile.changes == %{}\n+    assert profile.errors  == []\n+    assert profile.status  == :insert\n+    assert profile.valid?\n+    assert changeset.valid?\n+  end\n+\n+  test \"cast embeds_many with only new models\" do\n+    changeset = cast(%Author{}, %{\"profiles\" => [%{\"name\" => \"michal\"}]}, ~w(profiles))\n+    [profile_change] = changeset.changes.profiles\n+    assert profile_change.changes == %{name: \"michal\"}\n+    assert profile_change.errors  == []\n+    assert profile_change.status  == :insert\n+    assert profile_change.valid?\n+    assert changeset.valid?\n+  end\n+\n+  test \"cast embeds_many with custom changeset\" do\n+    changeset = cast(%Author{}, %{\"profiles\" => [%{\"name\" => \"michal\"}]},\n+                     [profiles: :optional_changeset])\n+    [profile_change] = changeset.changes.profiles\n+    assert profile_change.changes == %{name: \"michal\"}\n+    assert profile_change.errors  == []\n+    assert profile_change.status  == :insert\n+    assert profile_change.valid?\n+    assert changeset.valid?\n+  end\n+\n+  # Please note the order is important in this test.\n+  test \"cast embeds_many changing models\" do\n+    profiles = [%Profile{name: \"michal\", id: \"michal\"},\n+                %Profile{name: \"unknown\", id: \"unknown\"},\n+                %Profile{name: \"other\", id: \"other\"}]\n+    params = [%{\"id\" => \"new\", \"name\" => \"new\"},\n+              %{\"id\" => \"unknown\", \"name\" => nil},\n+              %{\"id\" => \"other\", \"name\" => \"new name\"}]\n+\n+    changeset = cast(%Author{profiles: profiles}, %{\"profiles\" => params}, ~w(profiles))\n+    [new, unknown, other, michal] = changeset.changes.profiles\n+    assert new.changes == %{name: \"new\"}\n+    assert new.status == :insert\n+    assert new.valid?\n+    assert unknown.model.id == \"unknown\"\n+    assert unknown.errors == [name: \"can't be blank\"]\n+    assert unknown.status == :update\n+    refute unknown.valid?\n+    assert other.model.id == \"other\"\n+    assert other.status == :update\n+    assert other.valid?\n+    assert michal.model.id == \"michal\"\n+    assert michal.status == :delete\n+    assert michal.valid?\n+    refute changeset.valid?\n+  end\n+\n+  test \"cast embeds_many with invalid params\" do","path":"test/ecto/embedded_test.exs","position":177,"original_position":177,"commit_id":"3ccfbd8fe12c59047c167eaaa092b40d5173786f","original_commit_id":"3ccfbd8fe12c59047c167eaaa092b40d5173786f","user":{"login":"josevalim","id":9582,"avatar_url":"https://avatars.githubusercontent.com/u/9582?v=3","gravatar_id":"","url":"https://api.github.com/users/josevalim","html_url":"https://github.com/josevalim","followers_url":"https://api.github.com/users/josevalim/followers","following_url":"https://api.github.com/users/josevalim/following{/other_user}","gists_url":"https://api.github.com/users/josevalim/gists{/gist_id}","starred_url":"https://api.github.com/users/josevalim/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/josevalim/subscriptions","organizations_url":"https://api.github.com/users/josevalim/orgs","repos_url":"https://api.github.com/users/josevalim/repos","events_url":"https://api.github.com/users/josevalim/events{/privacy}","received_events_url":"https://api.github.com/users/josevalim/received_events","type":"User","site_admin":false},"body":"Let's also add an assertion when the parameter is nil. We shuold mark it as invalid too.","created_at":"2015-07-13T12:50:07Z","updated_at":"2015-07-13T12:50:07Z","html_url":"https://github.com/elixir-lang/ecto/pull/767#discussion_r34459156","pull_request_url":"https://api.github.com/repos/elixir-lang/ecto/pulls/767","_links":{"self":{"href":"https://api.github.com/repos/elixir-lang/ecto/pulls/comments/34459156"},"html":{"href":"https://github.com/elixir-lang/ecto/pull/767#discussion_r34459156"},"pull_request":{"href":"https://api.github.com/repos/elixir-lang/ecto/pulls/767"}}},"pull_request":{"url":"https://api.github.com/repos/elixir-lang/ecto/pulls/767","id":39685107,"html_url":"https://github.com/elixir-lang/ecto/pull/767","diff_url":"https://github.com/elixir-lang/ecto/pull/767.diff","patch_url":"https://github.com/elixir-lang/ecto/pull/767.patch","issue_url":"https://api.github.com/repos/elixir-lang/ecto/issues/767","number":767,"state":"open","locked":false,"title":"Embedding part 2","user":{"login":"michalmuskala","id":477062,"avatar_url":"https://avatars.githubusercontent.com/u/477062?v=3","gravatar_id":"","url":"https://api.github.com/users/michalmuskala","html_url":"https://github.com/michalmuskala","followers_url":"https://api.github.com/users/michalmuskala/followers","following_url":"https://api.github.com/users/michalmuskala/following{/other_user}","gists_url":"https://api.github.com/users/michalmuskala/gists{/gist_id}","starred_url":"https://api.github.com/users/michalmuskala/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/michalmuskala/subscriptions","organizations_url":"https://api.github.com/users/michalmuskala/orgs","repos_url":"https://api.github.com/users/michalmuskala/repos","events_url":"https://api.github.com/users/michalmuskala/events{/privacy}","received_events_url":"https://api.github.com/users/michalmuskala/received_events","type":"User","site_admin":false},"body":"Currently only works for `embeds_one`. We need to think how to represent changes and errors in db arrays.","created_at":"2015-07-10T13:40:44Z","updated_at":"2015-07-13T12:50:08Z","closed_at":null,"merged_at":null,"merge_commit_sha":"d3cf0f2fbe343d047f643dbfab9c5b5314e04970","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/elixir-lang/ecto/pulls/767/commits","review_comments_url":"https://api.github.com/repos/elixir-lang/ecto/pulls/767/comments","review_comment_url":"https://api.github.com/repos/elixir-lang/ecto/pulls/comments{/number}","comments_url":"https://api.github.com/repos/elixir-lang/ecto/issues/767/comments","statuses_url":"https://api.github.com/repos/elixir-lang/ecto/statuses/3ccfbd8fe12c59047c167eaaa092b40d5173786f","head":{"label":"michalmuskala:embeds2","ref":"embeds2","sha":"3ccfbd8fe12c59047c167eaaa092b40d5173786f","user":{"login":"michalmuskala","id":477062,"avatar_url":"https://avatars.githubusercontent.com/u/477062?v=3","gravatar_id":"","url":"https://api.github.com/users/michalmuskala","html_url":"https://github.com/michalmuskala","followers_url":"https://api.github.com/users/michalmuskala/followers","following_url":"https://api.github.com/users/michalmuskala/following{/other_user}","gists_url":"https://api.github.com/users/michalmuskala/gists{/gist_id}","starred_url":"https://api.github.com/users/michalmuskala/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/michalmuskala/subscriptions","organizations_url":"https://api.github.com/users/michalmuskala/orgs","repos_url":"https://api.github.com/users/michalmuskala/repos","events_url":"https://api.github.com/users/michalmuskala/events{/privacy}","received_events_url":"https://api.github.com/users/michalmuskala/received_events","type":"User","site_admin":false},"repo":{"id":36659898,"name":"ecto","full_name":"michalmuskala/ecto","owner":{"login":"michalmuskala","id":477062,"avatar_url":"https://avatars.githubusercontent.com/u/477062?v=3","gravatar_id":"","url":"https://api.github.com/users/michalmuskala","html_url":"https://github.com/michalmuskala","followers_url":"https://api.github.com/users/michalmuskala/followers","following_url":"https://api.github.com/users/michalmuskala/following{/other_user}","gists_url":"https://api.github.com/users/michalmuskala/gists{/gist_id}","starred_url":"https://api.github.com/users/michalmuskala/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/michalmuskala/subscriptions","organizations_url":"https://api.github.com/users/michalmuskala/orgs","repos_url":"https://api.github.com/users/michalmuskala/repos","events_url":"https://api.github.com/users/michalmuskala/events{/privacy}","received_events_url":"https://api.github.com/users/michalmuskala/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/michalmuskala/ecto","description":"A database wrapper and language integrated query for Elixir","fork":true,"url":"https://api.github.com/repos/michalmuskala/ecto","forks_url":"https://api.github.com/repos/michalmuskala/ecto/forks","keys_url":"https://api.github.com/repos/michalmuskala/ecto/keys{/key_id}","collaborators_url":"https://api.github.com/repos/michalmuskala/ecto/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/michalmuskala/ecto/teams","hooks_url":"https://api.github.com/repos/michalmuskala/ecto/hooks","issue_events_url":"https://api.github.com/repos/michalmuskala/ecto/issues/events{/number}","events_url":"https://api.github.com/repos/michalmuskala/ecto/events","assignees_url":"https://api.github.com/repos/michalmuskala/ecto/assignees{/user}","branches_url":"https://api.github.com/repos/michalmuskala/ecto/branches{/branch}","tags_url":"https://api.github.com/repos/michalmuskala/ecto/tags","blobs_url":"https://api.github.com/repos/michalmuskala/ecto/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/michalmuskala/ecto/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/michalmuskala/ecto/git/refs{/sha}","trees_url":"https://api.github.com/repos/michalmuskala/ecto/git/trees{/sha}","statuses_url":"https://api.github.com/repos/michalmuskala/ecto/statuses/{sha}","languages_url":"https://api.github.com/repos/michalmuskala/ecto/languages","stargazers_url":"https://api.github.com/repos/michalmuskala/ecto/stargazers","contributors_url":"https://api.github.com/repos/michalmuskala/ecto/contributors","subscribers_url":"https://api.github.com/repos/michalmuskala/ecto/subscribers","subscription_url":"https://api.github.com/repos/michalmuskala/ecto/subscription","commits_url":"https://api.github.com/repos/michalmuskala/ecto/commits{/sha}","git_commits_url":"https://api.github.com/repos/michalmuskala/ecto/git/commits{/sha}","comments_url":"https://api.github.com/repos/michalmuskala/ecto/comments{/number}","issue_comment_url":"https://api.github.com/repos/michalmuskala/ecto/issues/comments{/number}","contents_url":"https://api.github.com/repos/michalmuskala/ecto/contents/{+path}","compare_url":"https://api.github.com/repos/michalmuskala/ecto/compare/{base}...{head}","merges_url":"https://api.github.com/repos/michalmuskala/ecto/merges","archive_url":"https://api.github.com/repos/michalmuskala/ecto/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/michalmuskala/ecto/downloads","issues_url":"https://api.github.com/repos/michalmuskala/ecto/issues{/number}","pulls_url":"https://api.github.com/repos/michalmuskala/ecto/pulls{/number}","milestones_url":"https://api.github.com/repos/michalmuskala/ecto/milestones{/number}","notifications_url":"https://api.github.com/repos/michalmuskala/ecto/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/michalmuskala/ecto/labels{/name}","releases_url":"https://api.github.com/repos/michalmuskala/ecto/releases{/id}","created_at":"2015-06-01T12:41:23Z","updated_at":"2015-06-01T12:41:24Z","pushed_at":"2015-07-13T11:29:25Z","git_url":"git://github.com/michalmuskala/ecto.git","ssh_url":"git@github.com:michalmuskala/ecto.git","clone_url":"https://github.com/michalmuskala/ecto.git","svn_url":"https://github.com/michalmuskala/ecto","homepage":"","size":4396,"stargazers_count":0,"watchers_count":0,"language":"Elixir","has_issues":false,"has_downloads":true,"has_wiki":true,"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":"elixir-lang:master","ref":"master","sha":"0c530cdced6254b133bb6804908308d83b637326","user":{"login":"elixir-lang","id":1481354,"avatar_url":"https://avatars.githubusercontent.com/u/1481354?v=3","gravatar_id":"","url":"https://api.github.com/users/elixir-lang","html_url":"https://github.com/elixir-lang","followers_url":"https://api.github.com/users/elixir-lang/followers","following_url":"https://api.github.com/users/elixir-lang/following{/other_user}","gists_url":"https://api.github.com/users/elixir-lang/gists{/gist_id}","starred_url":"https://api.github.com/users/elixir-lang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/elixir-lang/subscriptions","organizations_url":"https://api.github.com/users/elixir-lang/orgs","repos_url":"https://api.github.com/users/elixir-lang/repos","events_url":"https://api.github.com/users/elixir-lang/events{/privacy}","received_events_url":"https://api.github.com/users/elixir-lang/received_events","type":"Organization","site_admin":false},"repo":{"id":10649374,"name":"ecto","full_name":"elixir-lang/ecto","owner":{"login":"elixir-lang","id":1481354,"avatar_url":"https://avatars.githubusercontent.com/u/1481354?v=3","gravatar_id":"","url":"https://api.github.com/users/elixir-lang","html_url":"https://github.com/elixir-lang","followers_url":"https://api.github.com/users/elixir-lang/followers","following_url":"https://api.github.com/users/elixir-lang/following{/other_user}","gists_url":"https://api.github.com/users/elixir-lang/gists{/gist_id}","starred_url":"https://api.github.com/users/elixir-lang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/elixir-lang/subscriptions","organizations_url":"https://api.github.com/users/elixir-lang/orgs","repos_url":"https://api.github.com/users/elixir-lang/repos","events_url":"https://api.github.com/users/elixir-lang/events{/privacy}","received_events_url":"https://api.github.com/users/elixir-lang/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/elixir-lang/ecto","description":"A database wrapper and language integrated query for Elixir","fork":false,"url":"https://api.github.com/repos/elixir-lang/ecto","forks_url":"https://api.github.com/repos/elixir-lang/ecto/forks","keys_url":"https://api.github.com/repos/elixir-lang/ecto/keys{/key_id}","collaborators_url":"https://api.github.com/repos/elixir-lang/ecto/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/elixir-lang/ecto/teams","hooks_url":"https://api.github.com/repos/elixir-lang/ecto/hooks","issue_events_url":"https://api.github.com/repos/elixir-lang/ecto/issues/events{/number}","events_url":"https://api.github.com/repos/elixir-lang/ecto/events","assignees_url":"https://api.github.com/repos/elixir-lang/ecto/assignees{/user}","branches_url":"https://api.github.com/repos/elixir-lang/ecto/branches{/branch}","tags_url":"https://api.github.com/repos/elixir-lang/ecto/tags","blobs_url":"https://api.github.com/repos/elixir-lang/ecto/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/elixir-lang/ecto/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/elixir-lang/ecto/git/refs{/sha}","trees_url":"https://api.github.com/repos/elixir-lang/ecto/git/trees{/sha}","statuses_url":"https://api.github.com/repos/elixir-lang/ecto/statuses/{sha}","languages_url":"https://api.github.com/repos/elixir-lang/ecto/languages","stargazers_url":"https://api.github.com/repos/elixir-lang/ecto/stargazers","contributors_url":"https://api.github.com/repos/elixir-lang/ecto/contributors","subscribers_url":"https://api.github.com/repos/elixir-lang/ecto/subscribers","subscription_url":"https://api.github.com/repos/elixir-lang/ecto/subscription","commits_url":"https://api.github.com/repos/elixir-lang/ecto/commits{/sha}","git_commits_url":"https://api.github.com/repos/elixir-lang/ecto/git/commits{/sha}","comments_url":"https://api.github.com/repos/elixir-lang/ecto/comments{/number}","issue_comment_url":"https://api.github.com/repos/elixir-lang/ecto/issues/comments{/number}","contents_url":"https://api.github.com/repos/elixir-lang/ecto/contents/{+path}","compare_url":"https://api.github.com/repos/elixir-lang/ecto/compare/{base}...{head}","merges_url":"https://api.github.com/repos/elixir-lang/ecto/merges","archive_url":"https://api.github.com/repos/elixir-lang/ecto/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/elixir-lang/ecto/downloads","issues_url":"https://api.github.com/repos/elixir-lang/ecto/issues{/number}","pulls_url":"https://api.github.com/repos/elixir-lang/ecto/pulls{/number}","milestones_url":"https://api.github.com/repos/elixir-lang/ecto/milestones{/number}","notifications_url":"https://api.github.com/repos/elixir-lang/ecto/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/elixir-lang/ecto/labels{/name}","releases_url":"https://api.github.com/repos/elixir-lang/ecto/releases{/id}","created_at":"2013-06-12T18:42:06Z","updated_at":"2015-07-13T09:31:57Z","pushed_at":"2015-07-13T12:39:36Z","git_url":"git://github.com/elixir-lang/ecto.git","ssh_url":"git@github.com:elixir-lang/ecto.git","clone_url":"https://github.com/elixir-lang/ecto.git","svn_url":"https://github.com/elixir-lang/ecto","homepage":"","size":9779,"stargazers_count":887,"watchers_count":887,"language":"Elixir","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":191,"mirror_url":null,"open_issues_count":18,"forks":191,"open_issues":18,"watchers":887,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/elixir-lang/ecto/pulls/767"},"html":{"href":"https://github.com/elixir-lang/ecto/pull/767"},"issue":{"href":"https://api.github.com/repos/elixir-lang/ecto/issues/767"},"comments":{"href":"https://api.github.com/repos/elixir-lang/ecto/issues/767/comments"},"review_comments":{"href":"https://api.github.com/repos/elixir-lang/ecto/pulls/767/comments"},"review_comment":{"href":"https://api.github.com/repos/elixir-lang/ecto/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/elixir-lang/ecto/pulls/767/commits"},"statuses":{"href":"https://api.github.com/repos/elixir-lang/ecto/statuses/3ccfbd8fe12c59047c167eaaa092b40d5173786f"}}}}