├── .gitignore ├── .travis.yml ├── README.md ├── lib ├── client.ex ├── github_ecto.ex ├── github_ecto │ └── search.ex └── schema.ex ├── mix.exs ├── mix.lock └── test ├── github_ecto └── search_test.exs ├── github_ecto_test.exs ├── test_helper.exs └── vcr_cassettes ├── issues_create_update.json ├── issues_search.json ├── repositories_create.json └── repositories_search.json /.gitignore: -------------------------------------------------------------------------------- 1 | /_build 2 | /cover 3 | /deps 4 | erl_crash.dump 5 | *.ez 6 | .env 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: elixir 2 | sudo: false 3 | elixir: 4 | - 1.2 5 | otp_release: 6 | - 18.2 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GitHub.Ecto 2 | 3 | [![Build Status](https://travis-ci.org/wojtekmach/github_ecto.svg?branch=master)](https://travis-ci.org/wojtekmach/github_ecto) 4 | 5 | ## Example 6 | 7 | ```elixir 8 | # Paste below to iex 9 | 10 | # 0. Install this application (see instructions at the end of the README) 11 | 12 | # 1. Define `Repo` (or `GitHub` or whatever): 13 | defmodule Repo do 14 | use Ecto.Repo, 15 | otp_app: :my_app, 16 | adapter: GitHub.Ecto 17 | end 18 | 19 | # 2. Configure this application. In a real project you'd configure it in config/*.exs as does every other adapter. 20 | Application.put_env(:my_app, Repo, [ 21 | token: nil # set to a string to be able to write or access private repos. Be careful! 22 | ]) 23 | 24 | # 3. Start the Repo process. In a real project you'd put the Repo module in your project's supervision tree: 25 | {:ok, _pid} = Repo.start_link 26 | 27 | # 4. Import Ecto.Query 28 | import Ecto.Query 29 | 30 | # 5. List titles and comment counts of all open feature requests in Ecto, sorted by comment counts: 31 | q = from(i in GitHub.Issue, # or: from i in "issues" for all fields that API returns 32 | select: {i.title, i.comments}, 33 | where: i.repo == "elixir-ecto/ecto" and 34 | i.state == "open" and 35 | "Kind:Feature" in i.labels, 36 | order_by: [desc: :comments]) 37 | Repo.all(q) 38 | # => [{"Introducing Ecto.Multi", 60}, 39 | # {"Support map update syntax", 14}, 40 | # {"Create test db from development schema", 9}, 41 | # {"Provide integration tests with ownership with Hound", 0}] 42 | # (as of 2015-02-14) 43 | 44 | # 6. (optional) Create an issue if something doesn't look right :-) 45 | issue = Repo.insert!(%GitHub.Issue{title: "Something went wrong", body: "Everything's broken", repo: "wojtekmach/github_ecto"}) 46 | 47 | # 7. (optional) Mark the issue as resolved. 48 | Repo.update!(GitHub.Issue.changeset(issue, %{state: "closed"})) 49 | ``` 50 | 51 | See more examples of usage in [tests](test/github_ecto_test.exs). Also see the [Ecto API](http://hexdocs.pm/ecto/Ecto.html) and [GitHub API](https://developer.github.com/v3). 52 | 53 | ## Why? 54 | 55 | First of all this library is in a very early stage and isn't suitable for production use. 56 | Second of all, it may never be suitable for production use :-) 57 | There're already existing wrappers for GitHub API and, honestly, it may or may not be such a good 58 | idea to wrap it with Ecto. The primary goal of this project is for me to learn more about Ecto and it's internals and secondarily to build something useful :-) 59 | 60 | ## Installation 61 | 62 | 1. Add `github_ecto` to your list of dependencies in `mix.exs`: 63 | 64 | ```elixir 65 | def deps do 66 | [{:github_ecto, github: "wojtekmach/github_ecto"}] 67 | end 68 | ``` 69 | 70 | 2. Ensure `github_ecto` is started before your application: 71 | 72 | ```elixir 73 | def application do 74 | [applications: [:logger, :github_ecto, :ecto]] 75 | end 76 | ``` 77 | 78 | ## License 79 | 80 | The MIT License (MIT) 81 | 82 | Copyright (c) 2016 Wojciech Mach 83 | 84 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 85 | 86 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 87 | 88 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 89 | -------------------------------------------------------------------------------- /lib/client.ex: -------------------------------------------------------------------------------- 1 | defmodule GitHub.Client do 2 | use GenServer 3 | 4 | def start_link(token) do 5 | GenServer.start_link(__MODULE__, token, name: __MODULE__) 6 | end 7 | 8 | ## Interface 9 | 10 | # Returns list of search results 11 | def get!(path) do 12 | GenServer.call(__MODULE__, {:get!, path}) 13 | end 14 | 15 | # Returns url of the created entity 16 | def post!({path, json}) do 17 | GenServer.call(__MODULE__, {:post!, path, json}) 18 | end 19 | 20 | def patch!({path, json}) do 21 | GenServer.call(__MODULE__, {:patch!, path, json}) 22 | end 23 | 24 | ## Callbacks 25 | 26 | def handle_call({:get!, path}, _from, token) do 27 | url = url(path, token) 28 | result = HTTPoison.get!(url).body |> Poison.decode! 29 | {:reply, result, token} 30 | end 31 | 32 | def handle_call({:post!, path, json}, _from, token) do 33 | url = url(path, token) 34 | result = HTTPoison.post!(url, json).body |> Poison.decode! 35 | {:reply, result, token} 36 | end 37 | 38 | def handle_call({:patch!, path, json}, _from, token) do 39 | url = url(path, token) 40 | result = HTTPoison.patch!(url, json).body |> Poison.decode! 41 | {:reply, result, token} 42 | end 43 | 44 | @base_url "https://api.github.com" 45 | 46 | defp url(path, nil) do 47 | @base_url <> path 48 | end 49 | defp url(path, token) do 50 | c = if String.contains?(path, "?"), do: "&", else: "?" 51 | @base_url <> path <> c <> "access_token=" <> token 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /lib/github_ecto.ex: -------------------------------------------------------------------------------- 1 | defmodule GitHub.Ecto do 2 | alias GitHub.Ecto.Search 3 | alias GitHub.Ecto.Request 4 | alias GitHub.Client 5 | 6 | ## Boilerplate 7 | 8 | @behaviour Ecto.Adapter 9 | 10 | defmacro __before_compile__(_opts), do: :ok 11 | 12 | def application do 13 | :github_ecto 14 | end 15 | 16 | def child_spec(_repo, opts) do 17 | token = Keyword.get(opts, :token) 18 | Supervisor.Spec.worker(Client, [token]) 19 | end 20 | 21 | def ensure_all_started(_repo, _type) do 22 | {:ok, []} 23 | end 24 | 25 | def stop(_, _, _), do: :ok 26 | 27 | def loaders(primitive, _type), do: [primitive] 28 | 29 | def dumpers(primitive, _type), do: [primitive] 30 | 31 | def embed_id(_), do: raise "Not supported by adapter" 32 | 33 | def prepare(operation, query), do: {:nocache, {operation, query}} 34 | 35 | def autogenerate(_), do: "" 36 | 37 | ## Reads 38 | 39 | def execute(_repo, %{fields: fields} = _meta, {:nocache, {:all, query}}, [] = _params, preprocess, opts) do 40 | client = opts[:client] || Client 41 | path = Search.build(query) 42 | 43 | items = 44 | client.get!(path) 45 | |> Map.fetch!("items") 46 | |> Enum.map(fn item -> process_item(item, fields, preprocess) end) 47 | 48 | {0, items} 49 | end 50 | 51 | defp process_item(item, [{:&, [], [0, nil, _]}], _preprocess) do 52 | [item] 53 | end 54 | defp process_item(item, [{:&, [], [0, field_names, _]}], preprocess) do 55 | field_names = field_names -- [:repo] 56 | 57 | fields = [{:&, [], [0, field_names, nil]}] 58 | values = Enum.map(field_names, fn field -> Map.fetch!(item, Atom.to_string(field)) end) 59 | [preprocess.(hd(fields), values, nil) |> process_assocs(item) ] 60 | end 61 | defp process_item(item, exprs, preprocess) do 62 | Enum.map(exprs, fn {{:., [], [{:&, [], [0]}, field]}, _, []} -> 63 | preprocess.(field, Map.fetch!(item, Atom.to_string(field)), nil) 64 | end) 65 | end 66 | 67 | defp process_assocs(%{__struct__: struct} = schema, item) do 68 | Enum.map(struct.__schema__(:associations), fn assoc -> 69 | attributes = item[Atom.to_string(assoc)] 70 | 71 | if attributes do 72 | queryable = struct.__schema__(:association, assoc).queryable 73 | fields = queryable.__schema__(:fields) |> Enum.map(&Atom.to_string/1) 74 | 75 | attributes = 76 | Enum.into(attributes, %{}, fn {key, value} -> 77 | if key in fields do 78 | {String.to_atom(key), value} 79 | else 80 | {nil, nil} 81 | end 82 | end) 83 | 84 | {assoc, struct(queryable, attributes)} 85 | else 86 | {assoc, nil} 87 | end 88 | end) 89 | |> Enum.reduce(schema, fn({assoc, assoc_schema}, schema) -> 90 | Map.put(schema, assoc, assoc_schema) 91 | end) 92 | end 93 | 94 | ## Writes 95 | 96 | def insert(_repo, %{schema: schema} = _meta, params, _autogen, _opts) do 97 | result = Request.build(schema, params) |> Client.post! 98 | do_insert(schema, result) 99 | end 100 | 101 | defp do_insert(GitHub.Issue, %{"url" => url, "number" => number, "html_url" => html_url, "user" => user, "assignee" => assignee}) do 102 | {:ok, [id: url, number: number, url: html_url, user: user, assignee: assignee]} 103 | end 104 | defp do_insert(GitHub.Repository, %{"url" => url, "private" => private, "owner" => owner}) do 105 | {:ok, [id: url, private: private, owner: owner]} 106 | end 107 | 108 | def insert_all(_, _, _, _, _, _), do: raise "Not supported by adapter" 109 | 110 | def delete(_, _, _, _), do: raise "Not supported by adapter" 111 | 112 | def update(_repo, %{schema: schema} = _meta, params, filter, _autogen, _opts) do 113 | id = Keyword.fetch!(filter, :id) 114 | 115 | Request.build_patch(schema, id, params) |> Client.patch! 116 | {:ok, %{}} 117 | end 118 | end 119 | 120 | defmodule GitHub.Ecto.Request do 121 | def build(GitHub.Issue, params) do 122 | repo = Keyword.fetch!(params, :repo) 123 | title = Keyword.fetch!(params, :title) 124 | body = Keyword.fetch!(params, :body) 125 | assignee = get_in(params, [:assignee, :login]) 126 | 127 | path = "/repos/#{repo}/issues" 128 | json = Poison.encode!(%{title: title, body: body, assignee: assignee}) 129 | 130 | {path, json} 131 | end 132 | def build(GitHub.Repository, params) do 133 | path = "/user/repos" 134 | json = Poison.encode!(Enum.into(params, %{})) 135 | 136 | {path, json} 137 | end 138 | 139 | def build_patch(GitHub.Issue, id, params) do 140 | "https://api.github.com" <> path = id 141 | json = Enum.into(params, %{}) |> Poison.encode! 142 | 143 | {path, json} 144 | end 145 | end 146 | -------------------------------------------------------------------------------- /lib/github_ecto/search.ex: -------------------------------------------------------------------------------- 1 | defmodule GitHub.Ecto.Search do 2 | def build(query) do 3 | {from, _} = query.from 4 | 5 | str = 6 | [where(query), order_by(query), limit_offset(query)] 7 | |> Enum.filter(&(&1 != "")) 8 | |> Enum.join("&") 9 | 10 | "/search/#{from}?#{str}" 11 | end 12 | 13 | defp where(%Ecto.Query{wheres: wheres} = query) do 14 | "q=" <> Enum.map_join(wheres, "", fn where -> 15 | %Ecto.Query.QueryExpr{expr: expr, params: params} = where 16 | expr(expr, params, query) 17 | end) 18 | end 19 | 20 | defp order_by(%Ecto.Query{order_bys: []}), do: "" 21 | defp order_by(%Ecto.Query{from: {from, _}, order_bys: [order_by]} = query) do 22 | %Ecto.Query.QueryExpr{expr: [{left, right}], params: params} = order_by 23 | order = expr(left, params, query) 24 | sort = expr(right, params, query) 25 | sort = normalize(from, sort) 26 | 27 | "sort=#{sort}&order=#{order}" 28 | end 29 | defp order_by(_), do: raise ArgumentError, "GitHub API can only order by one field" 30 | 31 | defp limit_offset(%Ecto.Query{limit: limit, offset: offset} = query) do 32 | limit = if limit do 33 | %Ecto.Query.QueryExpr{expr: expr, params: params} = limit 34 | expr(expr, params, query) 35 | end 36 | 37 | offset = if offset do 38 | %Ecto.Query.QueryExpr{expr: expr, params: params} = offset 39 | expr(expr, params, query) 40 | end 41 | 42 | case {limit, offset} do 43 | {nil, nil} -> 44 | "" 45 | 46 | {limit, nil} -> 47 | "per_page=#{limit}" 48 | 49 | {nil, offset} -> 50 | "page=2&per_page=#{offset}" 51 | 52 | {limit, offset} -> 53 | page = (offset / limit) + 1 |> round 54 | "page=#{page}&per_page=#{limit}" 55 | end 56 | end 57 | 58 | defp expr({:and, [], [left, right]}, params, query) do 59 | "#{expr(left, params, query)}+#{expr(right, params, query)}" 60 | end 61 | defp expr({:==, [], [left, right]}, params, query) do 62 | field = expr(left, params, query) 63 | value = expr(right, params, query) 64 | "#{field}:#{value}" 65 | end 66 | defp expr({:in, [], [left, right]}, params, query) do 67 | field = expr(right, params, query) 68 | field = normalize(query.from, field) 69 | value = expr(left, params, query) 70 | "#{field}:#{value}" 71 | end 72 | defp expr({{:., _, [{:&, _, [_idx]}, field]}, _, []}, _params, _query) do 73 | field 74 | end 75 | defp expr(%Ecto.Query.Tagged{type: _type, value: value}, params, query) do 76 | expr(value, params, query) 77 | end 78 | defp expr({:^, [], [idx]}, params, _query) do 79 | Enum.at(params, idx) |> elem(0) 80 | end 81 | defp expr(value, _params, _query) when is_binary(value) or is_number(value) or is_atom(value) do 82 | value 83 | end 84 | 85 | defp normalize({name, _schema}, field), do: normalize(name, field) 86 | defp normalize("issues", :labels), do: "label" 87 | defp normalize("issues", :comments), do: "comments" 88 | defp normalize("issues", :created_at), do: "created" 89 | defp normalize("issues", :updated_at), do: "updated" 90 | defp normalize("repositories", :stars), do: "stars" 91 | defp normalize("repositories", :forks), do: "forks" 92 | defp normalize("repositories", :updated_at), do: "updated" 93 | defp normalize("users", :followers), do: "followers" 94 | defp normalize("users", :public_repos), do: "repositories" 95 | defp normalize("users", :created_at), do: "joined" 96 | end 97 | -------------------------------------------------------------------------------- /lib/schema.ex: -------------------------------------------------------------------------------- 1 | defmodule GitHub.User do 2 | use Ecto.Schema 3 | 4 | @primary_key {:id, :binary_id, [autogenerate: true]} # id is the API url of the user 5 | schema "users" do 6 | field :login, :string 7 | end 8 | 9 | @required ~w(login) 10 | @optional ~w() 11 | 12 | def changeset(user, params \\ :empty) do 13 | user 14 | |> Ecto.Changeset.cast(params, @required, @optional) 15 | end 16 | end 17 | 18 | defmodule GitHub.Issue do 19 | use Ecto.Schema 20 | 21 | @primary_key {:id, :string, []} # id is the API url of the issue 22 | schema "issues" do 23 | field :body, :string, default: "" 24 | field :closed_at, Ecto.DateTime 25 | field :comments, :integer, default: 0 26 | field :created_at, Ecto.DateTime 27 | field :labels, {:array, :string}, default: [] 28 | field :locked, :boolean, default: false 29 | field :number, :integer 30 | field :repo, :string 31 | field :state, :string, default: "open" 32 | field :title, :string, default: "" 33 | field :updated_at, Ecto.DateTime 34 | field :url, :string 35 | 36 | embeds_one :assignee, GitHub.User 37 | embeds_one :user, GitHub.User 38 | 39 | @required ~w(title repo) 40 | @optional ~w(body state) 41 | 42 | def changeset(issue, params \\ :empty) do 43 | issue 44 | |> Ecto.Changeset.cast(params, @required, @optional) 45 | |> Ecto.Changeset.cast_embed(:assignee) 46 | end 47 | end 48 | end 49 | 50 | defmodule GitHub.Repository do 51 | use Ecto.Schema 52 | 53 | @primary_key {:id, :string, []} # id is the API url of the repository 54 | schema "repositories" do 55 | field :created_at, Ecto.DateTime 56 | field :default_branch, :string 57 | field :description, :string 58 | field :fork, :boolean 59 | field :forks_count, :integer 60 | field :homepage, :string 61 | field :language, :string 62 | field :name, :string 63 | field :open_issues_count, :integer 64 | field :private, :boolean 65 | field :pushed_at, Ecto.DateTime 66 | field :stargazers_count, :integer 67 | field :updated_at, Ecto.DateTime 68 | field :url, :string 69 | field :watchers_count, :integer 70 | 71 | embeds_one :owner, GitHub.User 72 | end 73 | 74 | @required ~w(name description) 75 | @optional ~w() 76 | 77 | def changeset(repo, params \\ :empty) do 78 | repo 79 | |> Ecto.Changeset.cast(params, @required, @optional) 80 | end 81 | end 82 | -------------------------------------------------------------------------------- /mix.exs: -------------------------------------------------------------------------------- 1 | defmodule GitHub.Ecto.Mixfile do 2 | use Mix.Project 3 | 4 | def project do 5 | [ 6 | app: :github_ecto, 7 | version: "0.0.1", 8 | description: "Ecto adapter for GitHub API", 9 | package: package(), 10 | elixir: "~> 1.0", 11 | build_embedded: Mix.env == :prod, 12 | start_permanent: Mix.env == :prod, 13 | deps: deps(), 14 | ] 15 | end 16 | 17 | def application do 18 | [applications: [:logger, :ecto, :httpoison]] 19 | end 20 | 21 | defp deps do 22 | [ 23 | {:ecto, "~> 2.0.0"}, 24 | {:httpoison, "~> 0.9"}, 25 | {:poison, "~> 2.0"}, 26 | {:exvcr, "~> 0.7", only: :test}, 27 | ] 28 | end 29 | 30 | defp package do 31 | [ 32 | maintainers: ["Wojtek Mach"], 33 | licenses: ["MIT"], 34 | links: %{"GitHub" => "https://github.com/wojtekmach/github_ecto"}, 35 | ] 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /mix.lock: -------------------------------------------------------------------------------- 1 | %{"certifi": {:hex, :certifi, "1.0.0", "1c787a85b1855ba354f0b8920392c19aa1d06b0ee1362f9141279620a5be2039", [:rebar3], []}, 2 | "decimal": {:hex, :decimal, "1.3.1", "157b3cedb2bfcb5359372a7766dd7a41091ad34578296e951f58a946fcab49c6", [:mix], []}, 3 | "ecto": {:hex, :ecto, "2.0.6", "9dcbf819c2a77f67a66b83739b7fcc00b71aaf6c100016db4f798930fa4cfd47", [:mix], [{:db_connection, "~> 1.0", [hex: :db_connection, optional: true]}, {:decimal, "~> 1.1.2 or ~> 1.2", [hex: :decimal, optional: false]}, {:mariaex, "~> 0.8.0", [hex: :mariaex, optional: true]}, {:poison, "~> 1.5 or ~> 2.0", [hex: :poison, optional: true]}, {:poolboy, "~> 1.5", [hex: :poolboy, optional: false]}, {:postgrex, "~> 0.12.0", [hex: :postgrex, optional: true]}, {:sbroker, "~> 1.0-beta", [hex: :sbroker, optional: true]}]}, 4 | "exactor": {:hex, :exactor, "2.2.3", "a6972f43bb6160afeb73e1d8ab45ba604cd0ac8b5244c557093f6e92ce582786", [:mix], []}, 5 | "exjsx": {:hex, :exjsx, "3.2.1", "1bc5bf1e4fd249104178f0885030bcd75a4526f4d2a1e976f4b428d347614f0f", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, optional: false]}]}, 6 | "exvcr": {:hex, :exvcr, "0.8.7", "e76f33b10dfefbcf32afa6d6867140566d0d54797e352b47485eed0241dd7edf", [:mix], [{:exactor, "~> 2.2", [hex: :exactor, optional: false]}, {:exjsx, "~> 3.2", [hex: :exjsx, optional: false]}, {:httpoison, "~> 0.8", [hex: :httpoison, optional: true]}, {:httpotion, "~> 3.0", [hex: :httpotion, optional: true]}, {:ibrowse, "~> 4.2.2", [hex: :ibrowse, optional: true]}, {:meck, "~> 0.8.3", [hex: :meck, optional: false]}]}, 7 | "hackney": {:hex, :hackney, "1.7.1", "e238c52c5df3c3b16ce613d3a51c7220a784d734879b1e231c9babd433ac1cb4", [:rebar3], [{:certifi, "1.0.0", [hex: :certifi, optional: false]}, {:idna, "4.0.0", [hex: :idna, optional: false]}, {:metrics, "1.0.1", [hex: :metrics, optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, optional: false]}]}, 8 | "httpoison": {:hex, :httpoison, "0.11.1", "d06c571274c0e77b6cc50e548db3fd7779f611fbed6681fd60a331f66c143a0b", [:mix], [{:hackney, "~> 1.7.0", [hex: :hackney, optional: false]}]}, 9 | "idna": {:hex, :idna, "4.0.0", "10aaa9f79d0b12cf0def53038547855b91144f1bfcc0ec73494f38bb7b9c4961", [:rebar3], []}, 10 | "jsx": {:hex, :jsx, "2.8.2", "7acc7d785b5abe8a6e9adbde926a24e481f29956dd8b4df49e3e4e7bcc92a018", [:mix, :rebar3], []}, 11 | "meck": {:hex, :meck, "0.8.4", "59ca1cd971372aa223138efcf9b29475bde299e1953046a0c727184790ab1520", [:make, :rebar], []}, 12 | "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], []}, 13 | "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], []}, 14 | "poison": {:hex, :poison, "2.2.0", "4763b69a8a77bd77d26f477d196428b741261a761257ff1cf92753a0d4d24a63", [:mix], []}, 15 | "poolboy": {:hex, :poolboy, "1.5.1", "6b46163901cfd0a1b43d692657ed9d7e599853b3b21b95ae5ae0a777cf9b6ca8", [:rebar], []}, 16 | "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], []}, 17 | "ssl_verify_hostname": {:hex, :ssl_verify_hostname, "1.0.5"}} 18 | -------------------------------------------------------------------------------- /test/github_ecto/search_test.exs: -------------------------------------------------------------------------------- 1 | defmodule GitHub.Ecto.SearchTest do 2 | use ExUnit.Case, async: true 3 | import Ecto.Query, only: [from: 2] 4 | import GitHub.Ecto.Search, only: [build: 1] 5 | 6 | test "from" do 7 | q = from r in "repositories", where: r.user == "elixir-lang" 8 | assert build(q) == "/search/repositories?q=user:elixir-lang" 9 | 10 | q = from i in "issues", where: i.repo == "elixir-lang/ecto" 11 | assert build(q) == "/search/issues?q=repo:elixir-lang/ecto" 12 | end 13 | 14 | test "multiple fields" do 15 | q = from i in "issues", where: i.repo == "elixir-lang/ecto" and i.state == "closed" 16 | assert build(q) == "/search/issues?q=repo:elixir-lang/ecto+state:closed" 17 | 18 | repo = "elixir-lang/ecto" 19 | state = "closed" 20 | q = from i in "issues", where: i.repo == ^repo and i.state == ^state 21 | assert build(q) == "/search/issues?q=repo:elixir-lang/ecto+state:closed" 22 | end 23 | 24 | test "label" do 25 | q = from i in "issues", where: i.repo == "elixir-lang/ecto" and "Kind:Bug" in i.labels 26 | assert build(q) == "/search/issues?q=repo:elixir-lang/ecto+label:Kind:Bug" 27 | 28 | repo = "elixir-lang/ecto" 29 | label = "Kind:Bug" 30 | q = from i in "issues", where: i.repo == ^repo and ^label in i.labels 31 | assert build(q) == "/search/issues?q=repo:elixir-lang/ecto+label:Kind:Bug" 32 | end 33 | 34 | test "multiple labels" do 35 | q = from i in "issues", where: i.repo == "elixir-lang/ecto" and "Kind:Bug" in i.labels and "Level:Advanced" in i.labels 36 | assert build(q) == "/search/issues?q=repo:elixir-lang/ecto+label:Kind:Bug+label:Level:Advanced" 37 | end 38 | 39 | test "order_by" do 40 | q = from i in "issues", where: i.repo == "elixir-lang/ecto", order_by: i.created_at 41 | assert build(q) == "/search/issues?q=repo:elixir-lang/ecto&sort=created&order=asc" 42 | 43 | q = from i in "issues", where: i.repo == "elixir-lang/ecto", order_by: [desc: i.created_at] 44 | assert build(q) == "/search/issues?q=repo:elixir-lang/ecto&sort=created&order=desc" 45 | 46 | order_by = :created_at 47 | q = from i in "issues", where: i.repo == "elixir-lang/ecto", order_by: ^order_by 48 | assert build(q) == "/search/issues?q=repo:elixir-lang/ecto&sort=created&order=asc" 49 | end 50 | 51 | test "limit" do 52 | q = from i in "issues", where: i.repo == "elixir-lang/ecto", limit: 10 53 | assert build(q) == "/search/issues?q=repo:elixir-lang/ecto&per_page=10" 54 | end 55 | 56 | test "offset" do 57 | q = from i in "issues", where: i.repo == "elixir-lang/ecto", offset: 10 58 | assert build(q) == "/search/issues?q=repo:elixir-lang/ecto&page=2&per_page=10" 59 | end 60 | 61 | test "limit and offset" do 62 | q = from i in "issues", where: i.repo == "elixir-lang/ecto", limit: 5, offset: 10 63 | assert build(q) == "/search/issues?q=repo:elixir-lang/ecto&page=3&per_page=5" 64 | 65 | limit = 5 66 | offset = 10 67 | q = from i in "issues", where: i.repo == "elixir-lang/ecto", limit: ^limit, offset: ^offset 68 | assert build(q) == "/search/issues?q=repo:elixir-lang/ecto&page=3&per_page=5" 69 | end 70 | end 71 | -------------------------------------------------------------------------------- /test/github_ecto_test.exs: -------------------------------------------------------------------------------- 1 | defmodule GitHub.EctoIntegrationTest do 2 | use ExUnit.Case, async: false 3 | import Ecto.Query, only: [from: 2] 4 | 5 | use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney 6 | 7 | setup_all do 8 | ExVCR.Config.filter_sensitive_data("access_token=.*", "access_token=[FILTERED]") 9 | ExVCR.Config.cassette_library_dir("test/vcr_cassettes") 10 | :ok 11 | end 12 | 13 | test "issues: search" do 14 | use_cassette("issues_search") do 15 | q = from(i in "issues", 16 | where: i.repo == "elixir-lang/ecto" and i.state == "closed" and "Kind:Bug" in i.labels, 17 | order_by: [asc: i.created_at]) 18 | 19 | issues = TestRepo.all(q) 20 | assert length(issues) == 30 21 | assert %{ 22 | "title" => "Support div and rem, discuss what should happen with /", 23 | "state" => "closed", 24 | "url" => "https://api.github.com/repos/elixir-lang/ecto/issues/43", 25 | "labels" => [%{"name" => "Kind:Bug"}, %{"name" => "Note:Discussion"}], 26 | } = hd(issues) 27 | end 28 | end 29 | 30 | test "issues: create and update" do 31 | use_cassette("issues_create_update") do 32 | params = %{ 33 | title: "Test", 34 | body: "Integration tests are a scam!", 35 | repo: "wojtekmach/github_ecto_test", 36 | assignee: %{login: "wojtekmach"}, 37 | } 38 | issue = GitHub.Issue.changeset(%GitHub.Issue{}, params) 39 | issue = TestRepo.insert!(issue) 40 | assert issue.title == "Test" 41 | assert issue.body == "Integration tests are a scam!" 42 | assert "https://github.com/wojtekmach/github_ecto_test/issues/" <> _number = issue.url 43 | assert issue.state == "open" 44 | assert issue.user.login == "wojtekmach" 45 | assert issue.assignee.login == "wojtekmach" 46 | 47 | changeset = GitHub.Issue.changeset(issue, %{state: "closed"}) 48 | TestRepo.update!(changeset) 49 | end 50 | end 51 | 52 | test "repositories: search" do 53 | use_cassette("repositories_search") do 54 | q = from(r in GitHub.Repository, 55 | where: r.language == "elixir", 56 | order_by: [desc: r.stars]) 57 | 58 | repositories = TestRepo.all(q) 59 | assert Enum.at(repositories, 0).name == "elixir" 60 | assert Enum.at(repositories, 1).name == "phoenix" 61 | end 62 | end 63 | 64 | test "repositories: create" do 65 | use_cassette("repositories_create") do 66 | params = %{name: "github_ecto_test_create", 67 | description: "Integration tests are a scam!"} 68 | repo = GitHub.Repository.changeset(%GitHub.Repository{}, params) 69 | repo = TestRepo.insert!(repo) 70 | assert repo.name == "github_ecto_test_create" 71 | assert repo.private == false 72 | assert repo.description == "Integration tests are a scam!" 73 | assert repo.owner.login == "wojtekmach" 74 | end 75 | end 76 | end 77 | 78 | defmodule GitHub.EctoTest do 79 | use ExUnit.Case, async: false 80 | import Ecto.Query 81 | 82 | defmodule FakeClient do 83 | def get!(_path) do 84 | items = [ 85 | build(%{number: 1, title: "Issue 1"}), 86 | build(%{number: 2, title: "Issue 2"}), 87 | ] 88 | 89 | %{"items" => items} 90 | end 91 | 92 | defp build(params) do 93 | Map.merge(defaults("issues"), params) 94 | |> Enum.into(%{}, fn {field, value} -> {Atom.to_string(field), value} end) 95 | |> Poison.encode! |> Poison.decode! 96 | end 97 | 98 | defp defaults("issues") do 99 | %{ 100 | id: nil, 101 | body: "", 102 | closed_at: nil, 103 | comments: 0, 104 | created_at: nil, 105 | labels: [], 106 | locked: false, 107 | number: 222, 108 | repo: nil, 109 | state: "open", 110 | title: "", 111 | url: nil, 112 | updated_at: nil, 113 | user: defaults("user"), 114 | assignee: nil, 115 | } 116 | end 117 | defp defaults("user") do 118 | %{ 119 | login: "alice", 120 | } 121 | end 122 | end 123 | 124 | test "select: all fields" do 125 | q = from i in "issues" 126 | assert [ 127 | %{"number" => 1, "title" => "Issue 1", "user" => %{"login" => "alice"}}, 128 | %{"number" => 2, "title" => "Issue 2", "user" => %{"login" => "alice"}}, 129 | ] = TestRepo.all(q, client: FakeClient) 130 | 131 | q = from i in GitHub.Issue 132 | assert [ 133 | %GitHub.Issue{number: 1, title: "Issue 1", user: %GitHub.User{login: "alice"}}, 134 | %GitHub.Issue{number: 2, title: "Issue 2", user: %GitHub.User{login: "alice"}}, 135 | ] = TestRepo.all(q, client: FakeClient) 136 | end 137 | 138 | test "select: some fields" do 139 | q = from i in "issues", select: i.title 140 | assert TestRepo.all(q, client: FakeClient) == 141 | ["Issue 1", "Issue 2"] 142 | 143 | q = from i in "issues", select: {i.number, i.title} 144 | assert TestRepo.all(q, client: FakeClient) == 145 | [{1, "Issue 1"}, {2, "Issue 2"}] 146 | 147 | q = from i in GitHub.Issue, select: {i.number, i.title} 148 | assert TestRepo.all(q, client: FakeClient) == 149 | [{1, "Issue 1"}, {2, "Issue 2"}] 150 | end 151 | end 152 | -------------------------------------------------------------------------------- /test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start() 2 | 3 | Application.put_env(:my_app, TestRepo, 4 | adapter: GitHub.Ecto, 5 | token: System.get_env("GITHUB_TOKEN")) 6 | 7 | defmodule TestRepo do 8 | use Ecto.Repo, otp_app: :my_app 9 | end 10 | 11 | {:ok, _pid} = TestRepo.start_link 12 | -------------------------------------------------------------------------------- /test/vcr_cassettes/issues_create_update.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "{\"title\":\"Test\",\"body\":\"Integration tests are a scam!\",\"assignee\":\"wojtekmach\"}", 5 | "headers": [], 6 | "method": "post", 7 | "options": [], 8 | "request_body": "", 9 | "url": "https://api.github.com/repos/wojtekmach/github_ecto_test/issues?access_token=[FILTERED]" 10 | }, 11 | "response": { 12 | "body": "{\"url\":\"https://api.github.com/repos/wojtekmach/github_ecto_test/issues/64\",\"repository_url\":\"https://api.github.com/repos/wojtekmach/github_ecto_test\",\"labels_url\":\"https://api.github.com/repos/wojtekmach/github_ecto_test/issues/64/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/wojtekmach/github_ecto_test/issues/64/comments\",\"events_url\":\"https://api.github.com/repos/wojtekmach/github_ecto_test/issues/64/events\",\"html_url\":\"https://github.com/wojtekmach/github_ecto_test/issues/64\",\"id\":151733426,\"number\":64,\"title\":\"Test\",\"user\":{\"login\":\"wojtekmach\",\"id\":76071,\"avatar_url\":\"https://avatars.githubusercontent.com/u/76071?v=3\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/wojtekmach\",\"html_url\":\"https://github.com/wojtekmach\",\"followers_url\":\"https://api.github.com/users/wojtekmach/followers\",\"following_url\":\"https://api.github.com/users/wojtekmach/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/wojtekmach/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/wojtekmach/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/wojtekmach/subscriptions\",\"organizations_url\":\"https://api.github.com/users/wojtekmach/orgs\",\"repos_url\":\"https://api.github.com/users/wojtekmach/repos\",\"events_url\":\"https://api.github.com/users/wojtekmach/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/wojtekmach/received_events\",\"type\":\"User\",\"site_admin\":false},\"labels\":[],\"state\":\"open\",\"locked\":false,\"assignee\":{\"login\":\"wojtekmach\",\"id\":76071,\"avatar_url\":\"https://avatars.githubusercontent.com/u/76071?v=3\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/wojtekmach\",\"html_url\":\"https://github.com/wojtekmach\",\"followers_url\":\"https://api.github.com/users/wojtekmach/followers\",\"following_url\":\"https://api.github.com/users/wojtekmach/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/wojtekmach/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/wojtekmach/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/wojtekmach/subscriptions\",\"organizations_url\":\"https://api.github.com/users/wojtekmach/orgs\",\"repos_url\":\"https://api.github.com/users/wojtekmach/repos\",\"events_url\":\"https://api.github.com/users/wojtekmach/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/wojtekmach/received_events\",\"type\":\"User\",\"site_admin\":false},\"milestone\":null,\"comments\":0,\"created_at\":\"2016-04-28T20:17:44Z\",\"updated_at\":\"2016-04-28T20:17:44Z\",\"closed_at\":null,\"body\":\"Integration tests are a scam!\",\"closed_by\":null}", 13 | "headers": { 14 | "Server": "GitHub.com", 15 | "Date": "Thu, 28 Apr 2016 20:17:45 GMT", 16 | "Content-Type": "application/json; charset=utf-8", 17 | "Content-Length": "2563", 18 | "Status": "201 Created", 19 | "X-RateLimit-Limit": "5000", 20 | "X-RateLimit-Remaining": "4997", 21 | "X-RateLimit-Reset": "1461878184", 22 | "Cache-Control": "private, max-age=60, s-maxage=60", 23 | "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP", 24 | "ETag": "\"6557b0deab35652f518cf2229f51d758\"", 25 | "X-OAuth-Scopes": "repo", 26 | "X-Accepted-OAuth-Scopes": "", 27 | "Location": "https://api.github.com/repos/wojtekmach/github_ecto_test/issues/64", 28 | "X-GitHub-Media-Type": "github.v3; format=json", 29 | "Access-Control-Expose-Headers": "ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval", 30 | "Access-Control-Allow-Origin": "*", 31 | "Content-Security-Policy": "default-src 'none'", 32 | "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", 33 | "X-Content-Type-Options": "nosniff", 34 | "X-Frame-Options": "deny", 35 | "X-XSS-Protection": "1; mode=block", 36 | "X-Served-By": "4c8b2d4732c413f4b9aefe394bd65569", 37 | "X-GitHub-Request-Id": "5940D12D:76D6:2856855A:57226FE8" 38 | }, 39 | "status_code": 201, 40 | "type": "ok" 41 | } 42 | }, 43 | { 44 | "request": { 45 | "body": "{\"state\":\"closed\"}", 46 | "headers": [], 47 | "method": "patch", 48 | "options": [], 49 | "request_body": "", 50 | "url": "https://api.github.com/repos/wojtekmach/github_ecto_test/issues/64?access_token=[FILTERED]" 51 | }, 52 | "response": { 53 | "body": "{\"url\":\"https://api.github.com/repos/wojtekmach/github_ecto_test/issues/64\",\"repository_url\":\"https://api.github.com/repos/wojtekmach/github_ecto_test\",\"labels_url\":\"https://api.github.com/repos/wojtekmach/github_ecto_test/issues/64/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/wojtekmach/github_ecto_test/issues/64/comments\",\"events_url\":\"https://api.github.com/repos/wojtekmach/github_ecto_test/issues/64/events\",\"html_url\":\"https://github.com/wojtekmach/github_ecto_test/issues/64\",\"id\":151733426,\"number\":64,\"title\":\"Test\",\"user\":{\"login\":\"wojtekmach\",\"id\":76071,\"avatar_url\":\"https://avatars.githubusercontent.com/u/76071?v=3\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/wojtekmach\",\"html_url\":\"https://github.com/wojtekmach\",\"followers_url\":\"https://api.github.com/users/wojtekmach/followers\",\"following_url\":\"https://api.github.com/users/wojtekmach/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/wojtekmach/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/wojtekmach/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/wojtekmach/subscriptions\",\"organizations_url\":\"https://api.github.com/users/wojtekmach/orgs\",\"repos_url\":\"https://api.github.com/users/wojtekmach/repos\",\"events_url\":\"https://api.github.com/users/wojtekmach/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/wojtekmach/received_events\",\"type\":\"User\",\"site_admin\":false},\"labels\":[],\"state\":\"closed\",\"locked\":false,\"assignee\":{\"login\":\"wojtekmach\",\"id\":76071,\"avatar_url\":\"https://avatars.githubusercontent.com/u/76071?v=3\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/wojtekmach\",\"html_url\":\"https://github.com/wojtekmach\",\"followers_url\":\"https://api.github.com/users/wojtekmach/followers\",\"following_url\":\"https://api.github.com/users/wojtekmach/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/wojtekmach/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/wojtekmach/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/wojtekmach/subscriptions\",\"organizations_url\":\"https://api.github.com/users/wojtekmach/orgs\",\"repos_url\":\"https://api.github.com/users/wojtekmach/repos\",\"events_url\":\"https://api.github.com/users/wojtekmach/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/wojtekmach/received_events\",\"type\":\"User\",\"site_admin\":false},\"milestone\":null,\"comments\":0,\"created_at\":\"2016-04-28T20:17:44Z\",\"updated_at\":\"2016-04-28T20:17:45Z\",\"closed_at\":\"2016-04-28T20:17:45Z\",\"body\":\"Integration tests are a scam!\",\"closed_by\":{\"login\":\"wojtekmach\",\"id\":76071,\"avatar_url\":\"https://avatars.githubusercontent.com/u/76071?v=3\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/wojtekmach\",\"html_url\":\"https://github.com/wojtekmach\",\"followers_url\":\"https://api.github.com/users/wojtekmach/followers\",\"following_url\":\"https://api.github.com/users/wojtekmach/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/wojtekmach/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/wojtekmach/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/wojtekmach/subscriptions\",\"organizations_url\":\"https://api.github.com/users/wojtekmach/orgs\",\"repos_url\":\"https://api.github.com/users/wojtekmach/repos\",\"events_url\":\"https://api.github.com/users/wojtekmach/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/wojtekmach/received_events\",\"type\":\"User\",\"site_admin\":false}}", 54 | "headers": { 55 | "Server": "GitHub.com", 56 | "Date": "Thu, 28 Apr 2016 20:17:45 GMT", 57 | "Content-Type": "application/json; charset=utf-8", 58 | "Content-Length": "3471", 59 | "Status": "200 OK", 60 | "X-RateLimit-Limit": "5000", 61 | "X-RateLimit-Remaining": "4996", 62 | "X-RateLimit-Reset": "1461878184", 63 | "Cache-Control": "private, max-age=60, s-maxage=60", 64 | "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP", 65 | "ETag": "\"58b05c55ba467c47475a7673cd6a0ab9\"", 66 | "X-OAuth-Scopes": "repo", 67 | "X-Accepted-OAuth-Scopes": "", 68 | "X-GitHub-Media-Type": "github.v3; format=json", 69 | "Access-Control-Expose-Headers": "ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval", 70 | "Access-Control-Allow-Origin": "*", 71 | "Content-Security-Policy": "default-src 'none'", 72 | "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", 73 | "X-Content-Type-Options": "nosniff", 74 | "X-Frame-Options": "deny", 75 | "X-XSS-Protection": "1; mode=block", 76 | "X-Served-By": "065b43cd9674091fec48a221b420fbb3", 77 | "X-GitHub-Request-Id": "5940D12D:76D6:2856861B:57226FE9" 78 | }, 79 | "status_code": 200, 80 | "type": "ok" 81 | } 82 | } 83 | ] -------------------------------------------------------------------------------- /test/vcr_cassettes/issues_search.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": [], 8 | "request_body": "", 9 | "url": "https://api.github.com/search/issues?q=repo:elixir-lang/ecto+state:closed+label:Kind:Bug&sort=created&order=asc&access_token=[FILTERED]" 10 | }, 11 | "response": { 12 | "body": "{\"total_count\":47,\"incomplete_results\":false,\"items\":[{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/43\",\"repository_url\":\"https://api.github.com/repos/elixir-lang/ecto\",\"labels_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/43/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/43/comments\",\"events_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/43/events\",\"html_url\":\"https://github.com/elixir-lang/ecto/issues/43\",\"id\":17493488,\"number\":43,\"title\":\"Support div and rem, discuss what should happen with /\",\"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},\"labels\":[{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Kind:Bug\",\"name\":\"Kind:Bug\",\"color\":\"fc2929\"},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Note:Discussion\",\"name\":\"Note:Discussion\",\"color\":\"bfe5bf\"}],\"state\":\"closed\",\"locked\":false,\"assignee\":null,\"milestone\":null,\"comments\":1,\"created_at\":\"2013-08-01T07:09:25Z\",\"updated_at\":\"2013-08-05T12:26:22Z\",\"closed_at\":\"2013-08-05T12:26:22Z\",\"body\":\"\",\"score\":1.0},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/59\",\"repository_url\":\"https://api.github.com/repos/elixir-lang/ecto\",\"labels_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/59/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/59/comments\",\"events_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/59/events\",\"html_url\":\"https://github.com/elixir-lang/ecto/issues/59\",\"id\":18353982,\"number\":59,\"title\":\"Join binding should work even if too few bindings are specified\",\"user\":{\"login\":\"ericmj\",\"id\":316890,\"avatar_url\":\"https://avatars.githubusercontent.com/u/316890?v=3\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/ericmj\",\"html_url\":\"https://github.com/ericmj\",\"followers_url\":\"https://api.github.com/users/ericmj/followers\",\"following_url\":\"https://api.github.com/users/ericmj/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/ericmj/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/ericmj/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/ericmj/subscriptions\",\"organizations_url\":\"https://api.github.com/users/ericmj/orgs\",\"repos_url\":\"https://api.github.com/users/ericmj/repos\",\"events_url\":\"https://api.github.com/users/ericmj/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/ericmj/received_events\",\"type\":\"User\",\"site_admin\":false},\"labels\":[{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Kind:Bug\",\"name\":\"Kind:Bug\",\"color\":\"fc2929\"}],\"state\":\"closed\",\"locked\":false,\"assignee\":null,\"milestone\":null,\"comments\":0,\"created_at\":\"2013-08-21T13:37:10Z\",\"updated_at\":\"2013-08-30T21:34:34Z\",\"closed_at\":\"2013-08-30T21:34:34Z\",\"body\":\"The following will fail right now because the `c` binding will refer to `Post` because not enough bindings were specified in the `join`.\\r\\n\\r\\n```elixir\\r\\nfrom(Post) |> join([], c in Comment, c.id == 42)\\r\\n```\\r\\n\\r\\nWe need to take into account the number of entities on the query at runtime when escaping the \\\"on\\\" expression. (Make sure to only unquote the query once, will probably need to use `var!`.)\",\"score\":1.0},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/66\",\"repository_url\":\"https://api.github.com/repos/elixir-lang/ecto\",\"labels_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/66/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/66/comments\",\"events_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/66/events\",\"html_url\":\"https://github.com/elixir-lang/ecto/issues/66\",\"id\":19064063,\"number\":66,\"title\":\"`Repo.all(post.comments)` should fail when post has nil primary key\",\"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},\"labels\":[{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Kind:Bug\",\"name\":\"Kind:Bug\",\"color\":\"fc2929\"}],\"state\":\"closed\",\"locked\":false,\"assignee\":null,\"milestone\":null,\"comments\":0,\"created_at\":\"2013-09-05T17:51:14Z\",\"updated_at\":\"2013-09-06T16:22:35Z\",\"closed_at\":\"2013-09-06T16:22:35Z\",\"body\":\"\",\"score\":1.0},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/75\",\"repository_url\":\"https://api.github.com/repos/elixir-lang/ecto\",\"labels_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/75/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/75/comments\",\"events_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/75/events\",\"html_url\":\"https://github.com/elixir-lang/ecto/issues/75\",\"id\":19636300,\"number\":75,\"title\":\"has_many not respecting foreign_key option\",\"user\":{\"login\":\"reset\",\"id\":54036,\"avatar_url\":\"https://avatars.githubusercontent.com/u/54036?v=3\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/reset\",\"html_url\":\"https://github.com/reset\",\"followers_url\":\"https://api.github.com/users/reset/followers\",\"following_url\":\"https://api.github.com/users/reset/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/reset/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/reset/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/reset/subscriptions\",\"organizations_url\":\"https://api.github.com/users/reset/orgs\",\"repos_url\":\"https://api.github.com/users/reset/repos\",\"events_url\":\"https://api.github.com/users/reset/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/reset/received_events\",\"type\":\"User\",\"site_admin\":false},\"labels\":[{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Kind:Bug\",\"name\":\"Kind:Bug\",\"color\":\"fc2929\"}],\"state\":\"closed\",\"locked\":false,\"assignee\":null,\"milestone\":null,\"comments\":2,\"created_at\":\"2013-09-17T19:39:51Z\",\"updated_at\":\"2013-09-17T21:15:25Z\",\"closed_at\":\"2013-09-17T21:05:36Z\",\"body\":\"Given this contrived queryable definition:\\r\\n\\r\\n```elixir\\r\\ndefmodule User\\r\\n queryable \\\"users\\\" do\\r\\n has_many :sent_friend_requests, FriendRequest, foreign_key: :sender_id\\r\\n has_many :received_friend_requests, FriendRequest, foreign_key: :receiver_id\\r\\n ...\\r\\n end\\r\\nend\\r\\n```\\r\\n\\r\\nThe foreign_key will be set to the default value of `user_id` upon inspection of the entity's generated association\",\"score\":1.0},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/96\",\"repository_url\":\"https://api.github.com/repos/elixir-lang/ecto\",\"labels_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/96/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/96/comments\",\"events_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/96/events\",\"html_url\":\"https://github.com/elixir-lang/ecto/issues/96\",\"id\":21643538,\"number\":96,\"title\":\"mix text creates - (ArgumentError) expected contents inside brackets to be a Keyword\",\"user\":{\"login\":\"nicholasf\",\"id\":19967,\"avatar_url\":\"https://avatars.githubusercontent.com/u/19967?v=3\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/nicholasf\",\"html_url\":\"https://github.com/nicholasf\",\"followers_url\":\"https://api.github.com/users/nicholasf/followers\",\"following_url\":\"https://api.github.com/users/nicholasf/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/nicholasf/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/nicholasf/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/nicholasf/subscriptions\",\"organizations_url\":\"https://api.github.com/users/nicholasf/orgs\",\"repos_url\":\"https://api.github.com/users/nicholasf/repos\",\"events_url\":\"https://api.github.com/users/nicholasf/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/nicholasf/received_events\",\"type\":\"User\",\"site_admin\":false},\"labels\":[{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Kind:Bug\",\"name\":\"Kind:Bug\",\"color\":\"fc2929\"}],\"state\":\"closed\",\"locked\":false,\"assignee\":null,\"milestone\":null,\"comments\":5,\"created_at\":\"2013-10-26T23:51:39Z\",\"updated_at\":\"2013-10-29T07:25:12Z\",\"closed_at\":\"2013-10-29T07:25:12Z\",\"body\":\"Hi,\\r\\n\\r\\nPlease see:\\r\\n\\r\\n```\\r\\n♪ ecto git:(master) mix test\\r\\n** (ArgumentError) expected contents inside brackets to be a Keyword\\r\\n /Users/nicholasf/code/nicholasf/elixir/lib/elixir/lib/record.ex:424: Record.access/4\\r\\n test/ecto/associations_test.exs:7: Kernel.access/2\\r\\n test/ecto/associations_test.exs:7: Ecto.Entity.__before_compile__/1\\r\\n```\\r\\n\\r\\n\\r\\nI'm using Elixir 0.10.4-dev.\\r\\n\\r\\nCheers,\\r\\nNicholas\\r\\n\",\"score\":1.0},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/104\",\"repository_url\":\"https://api.github.com/repos/elixir-lang/ecto\",\"labels_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/104/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/104/comments\",\"events_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/104/events\",\"html_url\":\"https://github.com/elixir-lang/ecto/issues/104\",\"id\":22002415,\"number\":104,\"title\":\"Commit 46744986ed appears to break queries.\",\"user\":{\"login\":\"john-vinters\",\"id\":147399,\"avatar_url\":\"https://avatars.githubusercontent.com/u/147399?v=3\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/john-vinters\",\"html_url\":\"https://github.com/john-vinters\",\"followers_url\":\"https://api.github.com/users/john-vinters/followers\",\"following_url\":\"https://api.github.com/users/john-vinters/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/john-vinters/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/john-vinters/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/john-vinters/subscriptions\",\"organizations_url\":\"https://api.github.com/users/john-vinters/orgs\",\"repos_url\":\"https://api.github.com/users/john-vinters/repos\",\"events_url\":\"https://api.github.com/users/john-vinters/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/john-vinters/received_events\",\"type\":\"User\",\"site_admin\":false},\"labels\":[{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Kind:Bug\",\"name\":\"Kind:Bug\",\"color\":\"fc2929\"}],\"state\":\"closed\",\"locked\":false,\"assignee\":null,\"milestone\":null,\"comments\":6,\"created_at\":\"2013-11-02T14:27:47Z\",\"updated_at\":\"2013-11-02T18:07:38Z\",\"closed_at\":\"2013-11-02T16:55:18Z\",\"body\":\"After updating to 46744986ed or later, queries involving boolean operators seem to fail. For example, running the ecto_simple example code gives the following error:\\r\\n```\\r\\n** (Ecto.InvalidQuery) function `or/2` not defined in query API\\r\\n deps/ecto/lib/ecto/query/validator.ex:272: Ecto.Query.Validator.type_check/2\\r\\n deps/ecto/lib/ecto/query/validator.ex:133: Ecto.Query.Validator.\\\"-validate_booleans/3-fun-0-\\\"/3\\r\\n /private/tmp/elixir-ltF6/lib/elixir/lib/enum.ex:354: Enum.\\\"-each/2-lists^foreach/1-0-\\\"/2\\r\\n /private/tmp/elixir-ltF6/lib/elixir/lib/enum.ex:354: Enum.each/2\\r\\n deps/ecto/lib/ecto/query/validator.ex:40: Ecto.Query.Validator.validate/3\\r\\n deps/ecto/lib/ecto/repo/backend.ex:45: Ecto.Repo.Backend.all/3\\r\\n```\\r\\n\\r\\nEcto's in-built test suite seems to pass OK.\\r\\nI'm running Elixir 0.11.1-dev (updated immediately before testing).\\r\\n\",\"score\":1.0},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/118\",\"repository_url\":\"https://api.github.com/repos/elixir-lang/ecto\",\"labels_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/118/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/118/comments\",\"events_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/118/events\",\"html_url\":\"https://github.com/elixir-lang/ecto/issues/118\",\"id\":23409215,\"number\":118,\"title\":\"Table names and field names should be quoted\",\"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},\"labels\":[{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Kind:Bug\",\"name\":\"Kind:Bug\",\"color\":\"fc2929\"},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Kind:Enhancement\",\"name\":\"Kind:Enhancement\",\"color\":\"207de5\"}],\"state\":\"closed\",\"locked\":false,\"assignee\":null,\"milestone\":null,\"comments\":0,\"created_at\":\"2013-11-27T19:16:47Z\",\"updated_at\":\"2013-12-27T17:22:18Z\",\"closed_at\":\"2013-12-27T17:22:18Z\",\"body\":\"There are two reasons for this:\\r\\n\\r\\n1. To ensure we won't have an injection once we add more flexibility to the language (for example, `field/2` is vulnerable in the field name). Here is a failing test:\\r\\n\\r\\n ```elixir\\r\\n x = :\\\"\\\\\\\"id\\\"\\r\\n query = from(Model) |> where([m], field(m, ^x) == 1) |> normalize\\r\\n assert SQL.select(query) == %s[SELECT m0.id, m0.x, m0.y\\\\nFROM model AS m0\\\\nWHERE (m0.\\\"\\\\\\\"id\\\" = 1)]\\r\\n ```\\r\\n\\r\\n2. To ensure people can name their columns \\\"year\\\" and it won't conflict with keywords from SQL\",\"score\":1.0},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/120\",\"repository_url\":\"https://api.github.com/repos/elixir-lang/ecto\",\"labels_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/120/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/120/comments\",\"events_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/120/events\",\"html_url\":\"https://github.com/elixir-lang/ecto/issues/120\",\"id\":23538162,\"number\":120,\"title\":\"Should group_by allow more than one var?\",\"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},\"labels\":[{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Kind:Bug\",\"name\":\"Kind:Bug\",\"color\":\"fc2929\"}],\"state\":\"closed\",\"locked\":false,\"assignee\":null,\"milestone\":null,\"comments\":2,\"created_at\":\"2013-12-01T15:33:34Z\",\"updated_at\":\"2013-12-27T19:15:59Z\",\"closed_at\":\"2013-12-27T19:15:59Z\",\"body\":\"Today group_by allows a variable only at the \\\"root\\\":\\r\\n\\r\\n group_by: p\\r\\n\\r\\nShould we also allow:\\r\\n\\r\\n group_by: [p, c]\\r\\n\\r\\nOr:\\r\\n\\r\\n group_by: [p, c.field]\\r\\n\\r\\n?\",\"score\":1.0},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/187\",\"repository_url\":\"https://api.github.com/repos/elixir-lang/ecto\",\"labels_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/187/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/187/comments\",\"events_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/187/events\",\"html_url\":\"https://github.com/elixir-lang/ecto/issues/187\",\"id\":28847166,\"number\":187,\"title\":\"Handling of Ecto.Binary and Ecto.Array in Repo.create/1 return value\",\"user\":{\"login\":\"TanYewWei\",\"id\":204289,\"avatar_url\":\"https://avatars.githubusercontent.com/u/204289?v=3\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/TanYewWei\",\"html_url\":\"https://github.com/TanYewWei\",\"followers_url\":\"https://api.github.com/users/TanYewWei/followers\",\"following_url\":\"https://api.github.com/users/TanYewWei/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/TanYewWei/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/TanYewWei/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/TanYewWei/subscriptions\",\"organizations_url\":\"https://api.github.com/users/TanYewWei/orgs\",\"repos_url\":\"https://api.github.com/users/TanYewWei/repos\",\"events_url\":\"https://api.github.com/users/TanYewWei/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/TanYewWei/received_events\",\"type\":\"User\",\"site_admin\":false},\"labels\":[{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Kind:Bug\",\"name\":\"Kind:Bug\",\"color\":\"fc2929\"}],\"state\":\"closed\",\"locked\":false,\"assignee\":null,\"milestone\":null,\"comments\":2,\"created_at\":\"2014-03-06T03:22:04Z\",\"updated_at\":\"2014-03-06T11:17:15Z\",\"closed_at\":\"2014-03-06T11:01:36Z\",\"body\":\"I'm finding that `Repo.create/1` is returning an entity with raw `Ecto.Binary` and `Ecto.Array` values, while `Repo.all/1` or `Repo.get/2` returns entities with these Ecto types casted to their Elixir counterparts.\\r\\n\\r\\nHere's an example using the existing integration test code -- https://github.com/TanYewWei/ecto/commit/694d8b3f8183d94f8415e68790c3dee2b413002a\\r\\n\\r\\nShouldn't the create function also return an entity with Elixir strings and lists instead of the corresponding Ecto types?\\r\\n\\r\\n---\\r\\n\\r\\nWe should also update the README to use `:array` instead of `:list`, as well as document the handling of the Ecto.Array and Ecto.Binary types somewhere.\\r\\n\",\"score\":1.0},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/196\",\"repository_url\":\"https://api.github.com/repos/elixir-lang/ecto\",\"labels_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/196/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/196/comments\",\"events_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/196/events\",\"html_url\":\"https://github.com/elixir-lang/ecto/issues/196\",\"id\":30304587,\"number\":196,\"title\":\"parse_url should be imported into Ecto.Repo rather than defined\",\"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},\"labels\":[{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Kind:Bug\",\"name\":\"Kind:Bug\",\"color\":\"fc2929\"}],\"state\":\"closed\",\"locked\":false,\"assignee\":null,\"milestone\":null,\"comments\":0,\"created_at\":\"2014-03-27T14:27:01Z\",\"updated_at\":\"2014-05-23T14:40:42Z\",\"closed_at\":\"2014-05-23T14:40:42Z\",\"body\":\"[Similar to how we handle `app_dir`](https://github.com/elixir-lang/ecto/blob/master/lib/ecto/repo.ex#L57).\",\"score\":1.0},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/202\",\"repository_url\":\"https://api.github.com/repos/elixir-lang/ecto\",\"labels_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/202/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/202/comments\",\"events_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/202/events\",\"html_url\":\"https://github.com/elixir-lang/ecto/issues/202\",\"id\":30923388,\"number\":202,\"title\":\"broken \\\"where\\\" statement\",\"user\":{\"login\":\"kalloc\",\"id\":177687,\"avatar_url\":\"https://avatars.githubusercontent.com/u/177687?v=3\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/kalloc\",\"html_url\":\"https://github.com/kalloc\",\"followers_url\":\"https://api.github.com/users/kalloc/followers\",\"following_url\":\"https://api.github.com/users/kalloc/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/kalloc/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/kalloc/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/kalloc/subscriptions\",\"organizations_url\":\"https://api.github.com/users/kalloc/orgs\",\"repos_url\":\"https://api.github.com/users/kalloc/repos\",\"events_url\":\"https://api.github.com/users/kalloc/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/kalloc/received_events\",\"type\":\"User\",\"site_admin\":false},\"labels\":[{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Kind:Bug\",\"name\":\"Kind:Bug\",\"color\":\"fc2929\"}],\"state\":\"closed\",\"locked\":false,\"assignee\":null,\"milestone\":null,\"comments\":1,\"created_at\":\"2014-04-05T20:32:12Z\",\"updated_at\":\"2014-04-08T17:04:27Z\",\"closed_at\":\"2014-04-08T17:04:27Z\",\"body\":\"I found a bug, If you can, please, help me!\\r\\n\\r\\nnext statement\\r\\n```\\r\\nquery = from(p in Post,\\r\\n where: p.id > 0)\\r\\nquery = from(p in query,\\r\\n join: u in User, on: u.id == p.user_id)\\r\\nMy.Repo.all(from p in query,\\r\\n left_join: v in Views, on: v.post_id == p.id and v.user_id == 26,\\r\\n where: v.id == nil,\\r\\n select: p.id)\\r\\n```\\r\\nwill be produced\\r\\n```\\r\\n[LOG/query] SELECT p0.\\\"id\\\" FROM \\\"post\\\" AS p0\\r\\nINNER JOIN \\\"users\\\" AS u0 ON u0.\\\"id\\\" = p0.\\\"user_id\\\"\\r\\nLEFT OUTER JOIN \\\"views\\\" AS v0 ON (v0.\\\"post_id\\\" = p0.\\\"id\\\") AND (v0.\\\"user_id\\\" = 26)\\r\\nWHERE (p0.\\\"id\\\" > 0) AND (u0.\\\"id\\\" IS NULL)\\r\\n```\\r\\nbut must produced\\r\\n```\\r\\n[LOG/query] SELECT p0.\\\"id\\\" FROM \\\"post\\\" AS p0\\r\\nINNER JOIN \\\"users\\\" AS u0 ON u0.\\\"id\\\" = p0.\\\"user_id\\\"\\r\\nLEFT OUTER JOIN \\\"views\\\" AS v0 ON (v0.\\\"post_id\\\" = p0.\\\"id\\\") AND (v0.\\\"user_id\\\" = 26)\\r\\nWHERE (p0.\\\"id\\\" > 0) AND (v0.\\\"id\\\" IS NULL)\\r\\n```\\r\\n\",\"score\":1.0},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/252\",\"repository_url\":\"https://api.github.com/repos/elixir-lang/ecto\",\"labels_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/252/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/252/comments\",\"events_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/252/events\",\"html_url\":\"https://github.com/elixir-lang/ecto/issues/252\",\"id\":39296990,\"number\":252,\"title\":\"Do not ensure a non-required model was compiled from a model\",\"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},\"labels\":[{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Kind:Bug\",\"name\":\"Kind:Bug\",\"color\":\"fc2929\"}],\"state\":\"closed\",\"locked\":false,\"assignee\":null,\"milestone\":null,\"comments\":2,\"created_at\":\"2014-08-01T14:54:17Z\",\"updated_at\":\"2014-08-23T16:03:26Z\",\"closed_at\":\"2014-08-23T16:03:26Z\",\"body\":\"If we are inside a model, we should only ensure another model is compiled if that model is myself or if the model was explicitly required before hand. This way, we avoid the race conditions at outlined here: https://github.com/elixir-lang/elixir/issues/2568\",\"score\":1.0},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/287\",\"repository_url\":\"https://api.github.com/repos/elixir-lang/ecto\",\"labels_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/287/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/287/comments\",\"events_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/287/events\",\"html_url\":\"https://github.com/elixir-lang/ecto/issues/287\",\"id\":43693494,\"number\":287,\"title\":\"Query with :preload returns nil if associated record was not found\",\"user\":{\"login\":\"ayarulin\",\"id\":903562,\"avatar_url\":\"https://avatars.githubusercontent.com/u/903562?v=3\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/ayarulin\",\"html_url\":\"https://github.com/ayarulin\",\"followers_url\":\"https://api.github.com/users/ayarulin/followers\",\"following_url\":\"https://api.github.com/users/ayarulin/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/ayarulin/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/ayarulin/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/ayarulin/subscriptions\",\"organizations_url\":\"https://api.github.com/users/ayarulin/orgs\",\"repos_url\":\"https://api.github.com/users/ayarulin/repos\",\"events_url\":\"https://api.github.com/users/ayarulin/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/ayarulin/received_events\",\"type\":\"User\",\"site_admin\":false},\"labels\":[{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Kind:Bug\",\"name\":\"Kind:Bug\",\"color\":\"fc2929\"}],\"state\":\"closed\",\"locked\":false,\"assignee\":null,\"milestone\":null,\"comments\":1,\"created_at\":\"2014-09-23T22:39:55Z\",\"updated_at\":\"2014-09-24T19:27:47Z\",\"closed_at\":\"2014-09-24T19:27:47Z\",\"body\":\"This is example from README:\\r\\n```\\r\\nquery = from(c in Comment, where: c.id == 42, preload: :post)\\r\\n[comment] = Repo.all(query)\\r\\n```\\r\\nIt returns ```nil``` if no post was found for comment with id 42. Seems like this is bug, and query should return comment anyway, and ```nil``` only for ```comment.post```, right?\",\"score\":1.0},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/290\",\"repository_url\":\"https://api.github.com/repos/elixir-lang/ecto\",\"labels_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/290/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/290/comments\",\"events_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/290/events\",\"html_url\":\"https://github.com/elixir-lang/ecto/issues/290\",\"id\":44469067,\"number\":290,\"title\":\"How to use UUID's as primary key?\",\"user\":{\"login\":\"Psli\",\"id\":43417,\"avatar_url\":\"https://avatars.githubusercontent.com/u/43417?v=3\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/Psli\",\"html_url\":\"https://github.com/Psli\",\"followers_url\":\"https://api.github.com/users/Psli/followers\",\"following_url\":\"https://api.github.com/users/Psli/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/Psli/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/Psli/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/Psli/subscriptions\",\"organizations_url\":\"https://api.github.com/users/Psli/orgs\",\"repos_url\":\"https://api.github.com/users/Psli/repos\",\"events_url\":\"https://api.github.com/users/Psli/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/Psli/received_events\",\"type\":\"User\",\"site_admin\":false},\"labels\":[{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Kind:Bug\",\"name\":\"Kind:Bug\",\"color\":\"fc2929\"}],\"state\":\"closed\",\"locked\":false,\"assignee\":null,\"milestone\":null,\"comments\":3,\"created_at\":\"2014-09-30T16:35:29Z\",\"updated_at\":\"2014-10-03T15:34:48Z\",\"closed_at\":\"2014-10-01T18:10:51Z\",\"body\":\"ecto version: \\\"0.2.6-dev\\\"\\r\\n\\r\\nI wanted to use UUID's as my primary key on postgres db. \\r\\nThe model like this: \\r\\n```elixir\\r\\ndefmodule Item do\\r\\n use Ecto.Model\\r\\n schema \\\"items\\\", primary_key: { :id, :uuid, []} do\\r\\n field :some, :string\\r\\n field :created_at, :datetime\\r\\n end\\r\\nend\\r\\n```\\r\\nWhen I try to get the item I get the following error:\\r\\n```elixir\\r\\niex(7)> id = <<142, 180, 236, 138, 221, 1, 69, 20, 156, 16, 182, 24, 34, 37, 183, 102>>\\r\\niex(7)> Repo.get(Item, id)\\r\\n** (Ecto.Query.TypeCheckError) the following expression does not type check:\\r\\n\\r\\n &0.id() == ^0\\r\\n\\r\\nAllowed types for ==/2:\\r\\n\\r\\n number == number\\r\\n var == var\\r\\n nil == _\\r\\n _ == nil\\r\\n\\r\\nGot: uuid == string\\r\\n\\r\\n (ecto) lib/ecto/query/validator.ex:320: Ecto.Query.Validator.type_check/2\\r\\n (ecto) lib/ecto/query/validator.ex:518: Ecto.Query.Validator.catch_grouped/1\\r\\n (ecto) lib/ecto/query/validator.ex:114: anonymous fn/3 in Ecto.Query.Validator.validate_booleans/3\\r\\n (ecto) lib/ecto/query/validator.ex:530: Ecto.Query.Validator.rescue_metadata/3\\r\\n (elixir) lib/enum.ex:537: Enum.\\\"-each/2-lists^foreach/1-0-\\\"/2\\r\\n (elixir) lib/enum.ex:537: Enum.each/2\\r\\n (ecto) lib/ecto/query/validator.ex:29: Ecto.Query.Validator.validate/3\\r\\n (ecto) lib/ecto/repo/backend.ex:80: Ecto.Repo.Backend.all/4\\r\\n```\\r\\n\\r\\n\",\"score\":1.0},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/292\",\"repository_url\":\"https://api.github.com/repos/elixir-lang/ecto\",\"labels_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/292/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/292/comments\",\"events_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/292/events\",\"html_url\":\"https://github.com/elixir-lang/ecto/issues/292\",\"id\":44591069,\"number\":292,\"title\":\"Tracking down \\\"no process\\\" error\",\"user\":{\"login\":\"BinaryMuse\",\"id\":189606,\"avatar_url\":\"https://avatars.githubusercontent.com/u/189606?v=3\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/BinaryMuse\",\"html_url\":\"https://github.com/BinaryMuse\",\"followers_url\":\"https://api.github.com/users/BinaryMuse/followers\",\"following_url\":\"https://api.github.com/users/BinaryMuse/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/BinaryMuse/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/BinaryMuse/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/BinaryMuse/subscriptions\",\"organizations_url\":\"https://api.github.com/users/BinaryMuse/orgs\",\"repos_url\":\"https://api.github.com/users/BinaryMuse/repos\",\"events_url\":\"https://api.github.com/users/BinaryMuse/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/BinaryMuse/received_events\",\"type\":\"User\",\"site_admin\":false},\"labels\":[{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Kind:Bug\",\"name\":\"Kind:Bug\",\"color\":\"fc2929\"}],\"state\":\"closed\",\"locked\":false,\"assignee\":null,\"milestone\":null,\"comments\":11,\"created_at\":\"2014-10-01T17:20:19Z\",\"updated_at\":\"2015-01-19T13:21:12Z\",\"closed_at\":\"2015-01-19T13:21:12Z\",\"body\":\"Hey, guys,\\r\\n\\r\\nI'm running Ecto 0.2.3 on a cluster of four machines. Occasionally, one of the nodes gives me the following error:\\r\\n\\r\\n```\\r\\n2014-10-01 16:44:21.231 [error] GenServer #PID<0.150.0> terminating\\r\\nLast message: {:query, \\\"SELECT r0.\\\\\\\"id\\\\\\\", r0.\\\\\\\"uuid\\\\\\\", r0.\\\\\\\"script_hash\\\\\\\", r0.\\\\\\\"started\\\\\\\", r0.\\\\\\\"ended\\\\\\\", r0.\\\\\\\"active\\\\\\\", r0.\\\\\\\"node\\\\\\\", r0.\\\\\\\"label\\\\\\\"\\\\nFROM \\\\\\\"recordings\\\\\\\" AS r0\\\\nWHERE (r0.\\\\\\\"active\\\\\\\" = TRUE)\\\\nORDER BY r0.\\\\\\\"started\\\\\\\" DESC\\\", [], 5000}\\r\\nState: %{conn: #PID<0.592.0>, monitor: nil, params: [port: 5432, decoder: #Function<15.98203264/4 in Ecto.Adapters.Postgres.prepare_start/2>, username: \\\"xxxxxxx\\\", password: \\\"xxxxxxx\\\", hostname: \\\"xxxxxxx\\\", database: \\\"xxxxxxx\\\"]}\\r\\n** (exit) exited in: :gen_server.call(#PID<0.592.0>, :stop, :infinity)\\r\\n ** (EXIT) no process\\r\\n2014-10-01 16:44:21.232 [error] GenServer RecagentExecutor.Server terminating\\r\\nLast message: {:recording_list, [page: 0]}\\r\\nState: %{autostop_timer: nil, pid: nil, uuid: nil, working: false}\\r\\n** (exit) exited in: :gen_server.call(#PID<0.150.0>, {:query, \\\"SELECT r0.\\\\\\\"id\\\\\\\", r0.\\\\\\\"uuid\\\\\\\", r0.\\\\\\\"script_hash\\\\\\\", r0.\\\\\\\"started\\\\\\\", r0.\\\\\\\"ended\\\\\\\", r0.\\\\\\\"active\\\\\\\", r0.\\\\\\\"node\\\\\\\", r0.\\\\\\\"label\\\\\\\"\\\\nFROM \\\\\\\"recordings\\\\\\\" AS r0\\\\nWHERE (r0.\\\\\\\"active\\\\\\\" = TRUE)\\\\nORDER BY r0.\\\\\\\"started\\\\\\\" DESC\\\", [], 5000}, 5000)\\r\\n ** (EXIT) time out\\r\\n```\\r\\n\\r\\nTrying the request again gives the same error with different pids. I'm having trouble figuring out how I might track down the cause of the problem. Near as I can tell, Ecto is calling `Postgrex.Connection.stop` [in `terminate`](https://github.com/elixir-lang/ecto/blob/fffe9335a980e6e39a4dc0784b7973bcbd871814/lib/ecto/adapters/postgres/worker.ex#L123) and the \\\"no process\\\" exception comes [from there](https://github.com/ericmj/postgrex/blob/bb12d101b659d3383eb8c701f975ce20ec64c46a/lib/postgrex/connection.ex#L70).\\r\\n\\r\\nThe query is:\\r\\n\\r\\n```elixir\\r\\ndefp get_sub_list(active) do\\r\\n query = from r in Recording, where: r.active == ^active, order_by: [desc: r.started]\\r\\n RecagentLibrarian.Repo.all(query)\\r\\nend\\r\\n```\\r\\n\\r\\nI have my Repo supervised as such:\\r\\n\\r\\n```elixir\\r\\ndefmodule RecagentLibrarian do\\r\\n use Application\\r\\n\\r\\n def start(_type, _args) do\\r\\n import Supervisor.Spec, warn: false\\r\\n\\r\\n children = [\\r\\n worker(RecagentLibrarian.Repo, [], restart: :permanent)\\r\\n ]\\r\\n\\r\\n opts = [strategy: :one_for_one, name: RecagentLibrarian.Supervisor]\\r\\n Supervisor.start_link(children, opts)\\r\\n end\\r\\nend\\r\\n```\\r\\n\\r\\nAny help or hints in the right direction would be greatly appreciated.\",\"score\":1.0},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/293\",\"repository_url\":\"https://api.github.com/repos/elixir-lang/ecto\",\"labels_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/293/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/293/comments\",\"events_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/293/events\",\"html_url\":\"https://github.com/elixir-lang/ecto/issues/293\",\"id\":44767744,\"number\":293,\"title\":\"can't migrate repo on postgres 9.2 with trusted auth\",\"user\":{\"login\":\"j-mcnally\",\"id\":892382,\"avatar_url\":\"https://avatars.githubusercontent.com/u/892382?v=3\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/j-mcnally\",\"html_url\":\"https://github.com/j-mcnally\",\"followers_url\":\"https://api.github.com/users/j-mcnally/followers\",\"following_url\":\"https://api.github.com/users/j-mcnally/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/j-mcnally/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/j-mcnally/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/j-mcnally/subscriptions\",\"organizations_url\":\"https://api.github.com/users/j-mcnally/orgs\",\"repos_url\":\"https://api.github.com/users/j-mcnally/repos\",\"events_url\":\"https://api.github.com/users/j-mcnally/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/j-mcnally/received_events\",\"type\":\"User\",\"site_admin\":false},\"labels\":[{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Kind:Bug\",\"name\":\"Kind:Bug\",\"color\":\"fc2929\"}],\"state\":\"closed\",\"locked\":false,\"assignee\":null,\"milestone\":null,\"comments\":7,\"created_at\":\"2014-10-03T05:06:16Z\",\"updated_at\":\"2015-01-13T11:32:47Z\",\"closed_at\":\"2015-01-13T11:32:47Z\",\"body\":\"```\\r\\n** (exit) exited in: :gen_server.call(#PID<0.181.0>, {:query, \\\"CREATE TABLE IF NOT EXISTS schema_migrations (id serial primary key, version bigint)\\\", [], [timeout: 5000]}, 5000)\\r\\n ** (EXIT) exited in: :gen_server.call(#PID<0.186.0>, {:connect, [port: 5432, encoder: #Function<17.12881986/3 in Ecto.Adapters.Postgres.prepare_start/2>, decoder: #Function<16.12881986/4 in Ecto.Adapters.Postgres.prepare_start/2>, formatter: #Function<15.12881986/1 in Ecto.Adapters.Postgres.prepare_start/2>, username: \\\"webapp\\\", hostname: \\\"localhost\\\", database: \\\"struct\\\"]}, :infinity)\\r\\n ** (EXIT) an exception was raised:\\r\\n ** (ArgumentError) argument error\\r\\n :erlang.iolist_to_binary([nil, \\\"webapp\\\"])\\r\\n (crypto) crypto.erl:223: :crypto.hash/2\\r\\n (postgrex) lib/postgrex/connection.ex:519: Postgrex.Connection.message/3\\r\\n (postgrex) lib/postgrex/connection.ex:491: Postgrex.Connection.new_data/2\\r\\n (postgrex) lib/postgrex/connection.ex:401: Postgrex.Connection.handle_info/2\\r\\n (stdlib) gen_server.erl:599: :gen_server.handle_msg/5\\r\\n (stdlib) proc_lib.erl:239: :proc_lib.init_p_do_apply/3\\r\\n (stdlib) gen_server.erl:190: :gen_server.call/3\\r\\n (ecto) lib/ecto/adapters/postgres/worker.ex:18: Ecto.Adapters.Postgres.Worker.query!/4\\r\\n (ecto) lib/ecto/adapters/postgres.ex:353: Ecto.Adapters.Postgres.use_worker/3\\r\\n (ecto) lib/ecto/adapters/postgres.ex:514: Ecto.Adapters.Postgres.migrated_versions/1\\r\\n (ecto) lib/ecto/migrator.ex:92: Ecto.Migrator.pending_in_direction/3\\r\\n (ecto) lib/ecto/migrator.ex:87: Ecto.Migrator.run_all/3\\r\\n (mix) lib/mix/cli.ex:55: Mix.CLI.run_task/2\\r\\n\\r\\n\\r\\n04:59:20.401 [error] GenServer #PID<0.186.0> terminating\\r\\nLast message: {:tcp, #Port<0.6186>, <<82, 0, 0, 0, 12, 0, 0, 0, 5, 188, 234, 102, 118>>}\\r\\nState: %{backend_key: nil, bootstrap: false, opts: [port: 5432, encoder: #Function<17.12881986/3 in Ecto.Adapters.Postgres.prepare_start/2>, decoder: #Function<16.12881986/4 in Ecto.Adapters.Postgres.prepare_start/2>, formatter: #Function<15.12881986/1 in Ecto.Adapters.Postgres.prepare_start/2>, username: \\\"webapp\\\", hostname: \\\"localhost\\\", database: \\\"struct\\\"], parameters: %{}, portal: nil, queue: {[{{:connect, [port: 5432, encoder: #Function<17.12881986/3 in Ecto.Adapters.Postgres.prepare_start/2>, decoder: #Function<16.12881986/4 in Ecto.Adapters.Postgres.prepare_start/2>, formatter: #Function<15.12881986/1 in Ecto.Adapters.Postgres.prepare_start/2>, username: \\\"webapp\\\", hostname: \\\"localhost\\\", database: \\\"struct\\\"]}, {#PID<0.181.0>, #Reference<0.0.0.1954>}, nil}], []}, rows: [], sock: {:gen_tcp, #Port<0.6186>}, state: :auth, statement: nil, tail: \\\"\\\", transactions: 0, types: :types_removed}\\r\\n** (exit) an exception was raised:\\r\\n ** (ArgumentError) argument error\\r\\n :erlang.iolist_to_binary([nil, \\\"webapp\\\"])\\r\\n (crypto) crypto.erl:223: :crypto.hash/2\\r\\n (postgrex) lib/postgrex/connection.ex:519: Postgrex.Connection.message/3\\r\\n (postgrex) lib/postgrex/connection.ex:491: Postgrex.Connection.new_data/2\\r\\n (postgrex) lib/postgrex/connection.ex:401: Postgrex.Connection.handle_info/2\\r\\n (stdlib) gen_server.erl:599: :gen_server.handle_msg/5\\r\\n (stdlib) proc_lib.erl:239: :proc_lib.init_p_do_apply/3\\r\\n```\",\"score\":1.0},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/311\",\"repository_url\":\"https://api.github.com/repos/elixir-lang/ecto\",\"labels_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/311/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/311/comments\",\"events_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/311/events\",\"html_url\":\"https://github.com/elixir-lang/ecto/issues/311\",\"id\":48313398,\"number\":311,\"title\":\"mix ecto.create fails when URL includes a custom port\",\"user\":{\"login\":\"bjhaid\",\"id\":593852,\"avatar_url\":\"https://avatars.githubusercontent.com/u/593852?v=3\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/bjhaid\",\"html_url\":\"https://github.com/bjhaid\",\"followers_url\":\"https://api.github.com/users/bjhaid/followers\",\"following_url\":\"https://api.github.com/users/bjhaid/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/bjhaid/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/bjhaid/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/bjhaid/subscriptions\",\"organizations_url\":\"https://api.github.com/users/bjhaid/orgs\",\"repos_url\":\"https://api.github.com/users/bjhaid/repos\",\"events_url\":\"https://api.github.com/users/bjhaid/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/bjhaid/received_events\",\"type\":\"User\",\"site_admin\":false},\"labels\":[{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Kind:Bug\",\"name\":\"Kind:Bug\",\"color\":\"fc2929\"}],\"state\":\"closed\",\"locked\":false,\"assignee\":null,\"milestone\":null,\"comments\":2,\"created_at\":\"2014-11-10T21:01:04Z\",\"updated_at\":\"2014-11-12T13:27:53Z\",\"closed_at\":\"2014-11-12T13:27:53Z\",\"body\":\"Sample URI with custom port:\\r\\n\\r\\n`\\\"ecto://postgres:postgres@localhost:5433/foo_dev\\\"`\\r\\n\\r\\nmix task to reproduce: `mix ecto.create Repo`\",\"score\":1.0},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/333\",\"repository_url\":\"https://api.github.com/repos/elixir-lang/ecto\",\"labels_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/333/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/333/comments\",\"events_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/333/events\",\"html_url\":\"https://github.com/elixir-lang/ecto/issues/333\",\"id\":52728423,\"number\":333,\"title\":\"Improve Ecto.Model.validate return types\",\"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},\"labels\":[{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Kind:Bug\",\"name\":\"Kind:Bug\",\"color\":\"fc2929\"}],\"state\":\"closed\",\"locked\":false,\"assignee\":null,\"milestone\":null,\"comments\":0,\"created_at\":\"2014-12-23T10:10:05Z\",\"updated_at\":\"2015-01-09T18:48:05Z\",\"closed_at\":\"2015-01-09T18:48:05Z\",\"body\":\"\",\"score\":1.0},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/381\",\"repository_url\":\"https://api.github.com/repos/elixir-lang/ecto\",\"labels_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/381/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/381/comments\",\"events_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/381/events\",\"html_url\":\"https://github.com/elixir-lang/ecto/issues/381\",\"id\":54872556,\"number\":381,\"title\":\"Ensure preloads are not called twice\",\"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},\"labels\":[{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Kind:Bug\",\"name\":\"Kind:Bug\",\"color\":\"fc2929\"}],\"state\":\"closed\",\"locked\":false,\"assignee\":null,\"milestone\":null,\"comments\":0,\"created_at\":\"2015-01-20T11:33:10Z\",\"updated_at\":\"2015-01-20T13:31:54Z\",\"closed_at\":\"2015-01-20T13:31:54Z\",\"body\":\"\",\"score\":1.0},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/423\",\"repository_url\":\"https://api.github.com/repos/elixir-lang/ecto\",\"labels_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/423/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/423/comments\",\"events_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/423/events\",\"html_url\":\"https://github.com/elixir-lang/ecto/issues/423\",\"id\":56140611,\"number\":423,\"title\":\"change doesn't work when it creates a table and an index\",\"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},\"labels\":[{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Kind:Bug\",\"name\":\"Kind:Bug\",\"color\":\"fc2929\"},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Level:Intermediate\",\"name\":\"Level:Intermediate\",\"color\":\"fad8c7\"}],\"state\":\"closed\",\"locked\":false,\"assignee\":null,\"milestone\":null,\"comments\":10,\"created_at\":\"2015-01-31T21:39:10Z\",\"updated_at\":\"2015-02-09T14:13:34Z\",\"closed_at\":\"2015-02-09T14:13:34Z\",\"body\":\"\",\"score\":1.0},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/449\",\"repository_url\":\"https://api.github.com/repos/elixir-lang/ecto\",\"labels_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/449/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/449/comments\",\"events_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/449/events\",\"html_url\":\"https://github.com/elixir-lang/ecto/issues/449\",\"id\":57383516,\"number\":449,\"title\":\"Allow only atoms in lock\",\"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},\"labels\":[{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Kind:Bug\",\"name\":\"Kind:Bug\",\"color\":\"fc2929\"},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Level:Intermediate\",\"name\":\"Level:Intermediate\",\"color\":\"fad8c7\"}],\"state\":\"closed\",\"locked\":false,\"assignee\":null,\"milestone\":null,\"comments\":4,\"created_at\":\"2015-02-11T21:55:50Z\",\"updated_at\":\"2015-02-12T16:12:32Z\",\"closed_at\":\"2015-02-12T16:12:32Z\",\"body\":\"\",\"score\":1.0},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/538\",\"repository_url\":\"https://api.github.com/repos/elixir-lang/ecto\",\"labels_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/538/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/538/comments\",\"events_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/538/events\",\"html_url\":\"https://github.com/elixir-lang/ecto/issues/538\",\"id\":63580788,\"number\":538,\"title\":\"Default engine to InnoDB when creating MySQL databases\",\"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},\"labels\":[{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Kind:Bug\",\"name\":\"Kind:Bug\",\"color\":\"fc2929\"},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Level:Starter\",\"name\":\"Level:Starter\",\"color\":\"fef2c0\"}],\"state\":\"closed\",\"locked\":false,\"assignee\":null,\"milestone\":null,\"comments\":3,\"created_at\":\"2015-03-22T22:00:55Z\",\"updated_at\":\"2015-03-24T15:33:54Z\",\"closed_at\":\"2015-03-24T15:33:54Z\",\"body\":\"We should make it an option for storage_up as the other existing options and document it.\\r\\n\\r\\n/cc @laurocaetano @liveforeverx\",\"score\":1.0},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/547\",\"repository_url\":\"https://api.github.com/repos/elixir-lang/ecto\",\"labels_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/547/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/547/comments\",\"events_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/547/events\",\"html_url\":\"https://github.com/elixir-lang/ecto/issues/547\",\"id\":65665811,\"number\":547,\"title\":\"Decimals not saved correctly in Postgres DB\",\"user\":{\"login\":\"swerter\",\"id\":11270,\"avatar_url\":\"https://avatars.githubusercontent.com/u/11270?v=3\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/swerter\",\"html_url\":\"https://github.com/swerter\",\"followers_url\":\"https://api.github.com/users/swerter/followers\",\"following_url\":\"https://api.github.com/users/swerter/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/swerter/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/swerter/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/swerter/subscriptions\",\"organizations_url\":\"https://api.github.com/users/swerter/orgs\",\"repos_url\":\"https://api.github.com/users/swerter/repos\",\"events_url\":\"https://api.github.com/users/swerter/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/swerter/received_events\",\"type\":\"User\",\"site_admin\":false},\"labels\":[{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Kind:Bug\",\"name\":\"Kind:Bug\",\"color\":\"fc2929\"},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Level:Advanced\",\"name\":\"Level:Advanced\",\"color\":\"f7c6c7\"}],\"state\":\"closed\",\"locked\":false,\"assignee\":null,\"milestone\":null,\"comments\":7,\"created_at\":\"2015-04-01T11:48:27Z\",\"updated_at\":\"2015-04-10T10:13:40Z\",\"closed_at\":\"2015-04-10T09:52:38Z\",\"body\":\"Hi\\r\\nI think I found a bug when trying to save a decimal into a postgresql database. \\r\\nHow to reproduce:\\r\\nChange in the file integration_test/support/migrations.exs the decimal precision to higher value, eg:\\r\\n\\r\\n add :cost, :decimal, precision: 5, scale: 3\\r\\n\\r\\nThe integration tests then fails: `MIX_ENV=pg mix test`\\r\\n```\\r\\n 1) test primitive types (Ecto.Integration.TypeTest)\\r\\n integration_test/cases/type.exs:10\\r\\n match (=) failed\\r\\n code: [^decimal] = TestRepo.all(from(p in Post, where: p.cost() == ^decimal, select: p.cost()))\\r\\n rhs: [#Decimal<1.00>]\\r\\n stacktrace:\\r\\n integration_test/cases/type.exs:34\\r\\n```\\r\\n\\r\\nI found this error by trying to save a small number (0.002) to postgres as a decimal. The stored value, however, was always 0.2 instead (only one decimal after the dot).\\r\\n\\r\\nThanks for your help.\",\"score\":1.0},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/582\",\"repository_url\":\"https://api.github.com/repos/elixir-lang/ecto\",\"labels_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/582/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/582/comments\",\"events_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/582/events\",\"html_url\":\"https://github.com/elixir-lang/ecto/issues/582\",\"id\":73055338,\"number\":582,\"title\":\"put_change/3, put_new_change/3 and change/2 should check if the value is different from the one in the model\",\"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},\"labels\":[{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Kind:Bug\",\"name\":\"Kind:Bug\",\"color\":\"fc2929\"}],\"state\":\"closed\",\"locked\":false,\"assignee\":null,\"milestone\":{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/milestones/1\",\"html_url\":\"https://github.com/elixir-lang/ecto/milestones/v1.0\",\"labels_url\":\"https://api.github.com/repos/elixir-lang/ecto/milestones/1/labels\",\"id\":1092462,\"number\":1,\"title\":\"v1.0\",\"description\":\"\",\"creator\":{\"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},\"open_issues\":0,\"closed_issues\":27,\"state\":\"closed\",\"created_at\":\"2015-05-01T12:34:05Z\",\"updated_at\":\"2015-09-12T11:30:47Z\",\"due_on\":null,\"closed_at\":\"2015-09-12T11:30:47Z\"},\"comments\":1,\"created_at\":\"2015-05-04T15:42:58Z\",\"updated_at\":\"2015-05-05T08:14:47Z\",\"closed_at\":\"2015-05-05T08:14:47Z\",\"body\":\"If the value is the same as in the model, we won't add it to the list of changes. If it is different, we add it.\\r\\n\\r\\nWe will also introduce `force_change/3` which works as `put_change/3` today.\\r\\n\\r\\nIs someone interested in picking this up? We should release v0.11.1 afterwards with those fixes.\",\"score\":1.0},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/586\",\"repository_url\":\"https://api.github.com/repos/elixir-lang/ecto\",\"labels_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/586/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/586/comments\",\"events_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/586/events\",\"html_url\":\"https://github.com/elixir-lang/ecto/issues/586\",\"id\":73432764,\"number\":586,\"title\":\"Give better error message when an alias is given as type in migration\",\"user\":{\"login\":\"ericmj\",\"id\":316890,\"avatar_url\":\"https://avatars.githubusercontent.com/u/316890?v=3\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/ericmj\",\"html_url\":\"https://github.com/ericmj\",\"followers_url\":\"https://api.github.com/users/ericmj/followers\",\"following_url\":\"https://api.github.com/users/ericmj/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/ericmj/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/ericmj/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/ericmj/subscriptions\",\"organizations_url\":\"https://api.github.com/users/ericmj/orgs\",\"repos_url\":\"https://api.github.com/users/ericmj/repos\",\"events_url\":\"https://api.github.com/users/ericmj/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/ericmj/received_events\",\"type\":\"User\",\"site_admin\":false},\"labels\":[{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Kind:Bug\",\"name\":\"Kind:Bug\",\"color\":\"fc2929\"}],\"state\":\"closed\",\"locked\":false,\"assignee\":null,\"milestone\":null,\"comments\":0,\"created_at\":\"2015-05-05T21:12:10Z\",\"updated_at\":\"2015-05-06T10:55:07Z\",\"closed_at\":\"2015-05-06T10:55:07Z\",\"body\":\"\",\"score\":1.0},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/621\",\"repository_url\":\"https://api.github.com/repos/elixir-lang/ecto\",\"labels_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/621/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/621/comments\",\"events_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/621/events\",\"html_url\":\"https://github.com/elixir-lang/ecto/issues/621\",\"id\":81094455,\"number\":621,\"title\":\"validate_number does not work with decimals\",\"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},\"labels\":[{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Kind:Bug\",\"name\":\"Kind:Bug\",\"color\":\"fc2929\"},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Level:Starter\",\"name\":\"Level:Starter\",\"color\":\"fef2c0\"}],\"state\":\"closed\",\"locked\":false,\"assignee\":null,\"milestone\":null,\"comments\":3,\"created_at\":\"2015-05-26T19:08:15Z\",\"updated_at\":\"2015-05-30T18:02:15Z\",\"closed_at\":\"2015-05-30T17:44:34Z\",\"body\":\"\",\"score\":1.0},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/693\",\"repository_url\":\"https://api.github.com/repos/elixir-lang/ecto\",\"labels_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/693/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/693/comments\",\"events_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/693/events\",\"html_url\":\"https://github.com/elixir-lang/ecto/issues/693\",\"id\":90754326,\"number\":693,\"title\":\"encoded URI\",\"user\":{\"login\":\"umatomba\",\"id\":1991518,\"avatar_url\":\"https://avatars.githubusercontent.com/u/1991518?v=3\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/umatomba\",\"html_url\":\"https://github.com/umatomba\",\"followers_url\":\"https://api.github.com/users/umatomba/followers\",\"following_url\":\"https://api.github.com/users/umatomba/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/umatomba/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/umatomba/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/umatomba/subscriptions\",\"organizations_url\":\"https://api.github.com/users/umatomba/orgs\",\"repos_url\":\"https://api.github.com/users/umatomba/repos\",\"events_url\":\"https://api.github.com/users/umatomba/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/umatomba/received_events\",\"type\":\"User\",\"site_admin\":false},\"labels\":[{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Kind:Bug\",\"name\":\"Kind:Bug\",\"color\":\"fc2929\"},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Level:Starter\",\"name\":\"Level:Starter\",\"color\":\"fef2c0\"}],\"state\":\"closed\",\"locked\":false,\"assignee\":null,\"milestone\":null,\"comments\":1,\"created_at\":\"2015-06-24T18:31:02Z\",\"updated_at\":\"2015-06-29T08:24:14Z\",\"closed_at\":\"2015-06-29T08:24:14Z\",\"body\":\"Currently, the encoded url (f.e. with special characters in password) can not be used, because is not decoded. I think we could add this future to support the URI format.\\r\\n\\r\\n\",\"score\":1.0},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/739\",\"repository_url\":\"https://api.github.com/repos/elixir-lang/ecto\",\"labels_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/739/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/739/comments\",\"events_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/739/events\",\"html_url\":\"https://github.com/elixir-lang/ecto/issues/739\",\"id\":92717966,\"number\":739,\"title\":\"Source is not respected in Preloading\",\"user\":{\"login\":\"reset\",\"id\":54036,\"avatar_url\":\"https://avatars.githubusercontent.com/u/54036?v=3\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/reset\",\"html_url\":\"https://github.com/reset\",\"followers_url\":\"https://api.github.com/users/reset/followers\",\"following_url\":\"https://api.github.com/users/reset/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/reset/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/reset/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/reset/subscriptions\",\"organizations_url\":\"https://api.github.com/users/reset/orgs\",\"repos_url\":\"https://api.github.com/users/reset/repos\",\"events_url\":\"https://api.github.com/users/reset/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/reset/received_events\",\"type\":\"User\",\"site_admin\":false},\"labels\":[{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Kind:Bug\",\"name\":\"Kind:Bug\",\"color\":\"fc2929\"},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Level:Intermediate\",\"name\":\"Level:Intermediate\",\"color\":\"fad8c7\"}],\"state\":\"closed\",\"locked\":false,\"assignee\":null,\"milestone\":{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/milestones/1\",\"html_url\":\"https://github.com/elixir-lang/ecto/milestones/v1.0\",\"labels_url\":\"https://api.github.com/repos/elixir-lang/ecto/milestones/1/labels\",\"id\":1092462,\"number\":1,\"title\":\"v1.0\",\"description\":\"\",\"creator\":{\"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},\"open_issues\":0,\"closed_issues\":27,\"state\":\"closed\",\"created_at\":\"2015-05-01T12:34:05Z\",\"updated_at\":\"2015-09-12T11:30:47Z\",\"due_on\":null,\"closed_at\":\"2015-09-12T11:30:47Z\"},\"comments\":10,\"created_at\":\"2015-07-02T19:41:33Z\",\"updated_at\":\"2015-07-21T07:21:35Z\",\"closed_at\":\"2015-07-16T22:18:02Z\",\"body\":\"I have an application which leverages Postgres schemas to \\\"shard\\\" data. There are X number of replicas contained within schemas named something like \\\"account_1\\\", \\\"account_2\\\", etc.\\r\\n\\r\\nIn Ecto 10 the ability to query on source was added by specifying `{\\\"account_1.accounts\\\", MyApp.Account}` in a query instead of just `MyApp.Account`. The source is annotated in any records found and it works very nicely when updating or deleting those records.\\r\\n\\r\\nPreloading associations is a problem, however. The source tagged in the metadata of a record is not used when attempting to preload an association, so I see an error like this:\\r\\n\\r\\n```\\r\\n** (Postgrex.Error) ERROR (undefined_table): relation \\\"relationships\\\" does not exist\\r\\n```\\r\\n\\r\\nWhere I would instead expect the relation to be \\\"account_1.relationships\\\".\\r\\n\\r\\nThank you so much for the support. Ecto is really kicking ass for us at Undead Labs!\",\"score\":1.0},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/763\",\"repository_url\":\"https://api.github.com/repos/elixir-lang/ecto\",\"labels_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/763/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/763/comments\",\"events_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/763/events\",\"html_url\":\"https://github.com/elixir-lang/ecto/issues/763\",\"id\":94063495,\"number\":763,\"title\":\"Has many through 2 relations not joining correctly.\",\"user\":{\"login\":\"alanpeabody\",\"id\":19368,\"avatar_url\":\"https://avatars.githubusercontent.com/u/19368?v=3\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/alanpeabody\",\"html_url\":\"https://github.com/alanpeabody\",\"followers_url\":\"https://api.github.com/users/alanpeabody/followers\",\"following_url\":\"https://api.github.com/users/alanpeabody/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/alanpeabody/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/alanpeabody/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/alanpeabody/subscriptions\",\"organizations_url\":\"https://api.github.com/users/alanpeabody/orgs\",\"repos_url\":\"https://api.github.com/users/alanpeabody/repos\",\"events_url\":\"https://api.github.com/users/alanpeabody/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/alanpeabody/received_events\",\"type\":\"User\",\"site_admin\":false},\"labels\":[{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Kind:Bug\",\"name\":\"Kind:Bug\",\"color\":\"fc2929\"},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Level:Advanced\",\"name\":\"Level:Advanced\",\"color\":\"f7c6c7\"}],\"state\":\"closed\",\"locked\":false,\"assignee\":null,\"milestone\":null,\"comments\":2,\"created_at\":\"2015-07-09T14:25:52Z\",\"updated_at\":\"2015-07-11T19:53:41Z\",\"closed_at\":\"2015-07-11T19:53:41Z\",\"body\":\"When joining a multiple tables via has_many through ran into a situation where the tables are not joining correctly. The tables are referenced before they are defined in the SQL.\\r\\n\\r\\nExample:\\r\\n\\r\\n```elixir\\r\\n\\r\\ndefmodule Models do\\r\\n defmodule User do\\r\\n use Ecto.Model\\r\\n schema \\\"users\\\" do\\r\\n has_many :team_members, Models.TeamMember\\r\\n has_many :environments, through: [:team_members, :environment]\\r\\n has_many :applications, through: [:team_members, :environment, :applications]\\r\\n end\\r\\n end\\r\\n\\r\\n defmodule TeamMember do\\r\\n use Ecto.Model\\r\\n schema \\\"team_members\\\" do\\r\\n belongs_to :team_members, Models.TeamMember\\r\\n belongs_to :environments, Models.Environment\\r\\n end\\r\\n end\\r\\n\\r\\n defmodule Environment do\\r\\n use Ecto.Model\\r\\n schema \\\"environments\\\" do\\r\\n has_many :team_members, Models.TeamMember\\r\\n has_many :applications, Models.Application\\r\\n end\\r\\n end\\r\\n\\r\\n defmodule Application do\\r\\n use Ecto.Model\\r\\n schema \\\"applications\\\" do\\r\\n belongs_to :environment, Models.Environment\\r\\n end\\r\\n end\\r\\nend\\r\\n```\\r\\n\\r\\nGiven data is populated and tables are correctly setup.\\r\\n\\r\\n```elixir\\r\\nuser = Repo.find(Models.User, 1)\\r\\nEcto.Model.assoc(user, :applications)\\r\\n|> IO.inspect\\r\\n|> Repo.all\\r\\n```\\r\\nEcto.Query:\\r\\n```\\r\\n#Ecto.Query\\r\\n```\\r\\nSQL:\\r\\n```\\r\\n[debug] SELECT DISTINCT a0.\\\"id\\\", a0.\\\"name\\\", a0.\\\"inserted_at\\\", a0.\\\"updated_at\\\", a0.\\\"environment_id\\\" FROM \\\"applications\\\" AS a0 INNER JOIN \\\"environments\\\" AS e1 ON e1.\\\"id\\\" = t2.\\\"environment_id\\\" INNER JOIN \\\"team_members\\\" AS t2 ON a0.\\\"environment_id\\\" = e1.\\\"id\\\" WHERE (t2.\\\"user_id\\\" IN ($1))\\r\\n```\\r\\n\\r\\nError:\\r\\n```\\r\\n(Postgrex.Error) ERROR (undefined_table): missing FROM-clause entry for table \\\"t2\\\"\\r\\n```\\r\\n\",\"score\":1.0},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/804\",\"repository_url\":\"https://api.github.com/repos/elixir-lang/ecto\",\"labels_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/804/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/804/comments\",\"events_url\":\"https://api.github.com/repos/elixir-lang/ecto/issues/804/events\",\"html_url\":\"https://github.com/elixir-lang/ecto/issues/804\",\"id\":95802282,\"number\":804,\"title\":\"Migration with reference can not be rolled back\",\"user\":{\"login\":\"ashneyderman\",\"id\":27250,\"avatar_url\":\"https://avatars.githubusercontent.com/u/27250?v=3\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/ashneyderman\",\"html_url\":\"https://github.com/ashneyderman\",\"followers_url\":\"https://api.github.com/users/ashneyderman/followers\",\"following_url\":\"https://api.github.com/users/ashneyderman/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/ashneyderman/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/ashneyderman/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/ashneyderman/subscriptions\",\"organizations_url\":\"https://api.github.com/users/ashneyderman/orgs\",\"repos_url\":\"https://api.github.com/users/ashneyderman/repos\",\"events_url\":\"https://api.github.com/users/ashneyderman/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/ashneyderman/received_events\",\"type\":\"User\",\"site_admin\":false},\"labels\":[{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Kind:Bug\",\"name\":\"Kind:Bug\",\"color\":\"fc2929\"},{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/labels/Level:Intermediate\",\"name\":\"Level:Intermediate\",\"color\":\"fad8c7\"}],\"state\":\"closed\",\"locked\":false,\"assignee\":null,\"milestone\":{\"url\":\"https://api.github.com/repos/elixir-lang/ecto/milestones/1\",\"html_url\":\"https://github.com/elixir-lang/ecto/milestones/v1.0\",\"labels_url\":\"https://api.github.com/repos/elixir-lang/ecto/milestones/1/labels\",\"id\":1092462,\"number\":1,\"title\":\"v1.0\",\"description\":\"\",\"creator\":{\"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},\"open_issues\":0,\"closed_issues\":27,\"state\":\"closed\",\"created_at\":\"2015-05-01T12:34:05Z\",\"updated_at\":\"2015-09-12T11:30:47Z\",\"due_on\":null,\"closed_at\":\"2015-09-12T11:30:47Z\"},\"comments\":3,\"created_at\":\"2015-07-18T08:12:46Z\",\"updated_at\":\"2015-07-23T21:40:07Z\",\"closed_at\":\"2015-07-23T21:40:07Z\",\"body\":\"Here is my migration\\r\\n\\r\\n```\\r\\ndefmodule EctoPlay.Repo.Migrations.Meteo do\\r\\n use Ecto.Migration\\r\\n\\r\\n def change do\\r\\n create table(:report) do\\r\\n add :name, :string\\r\\n add :month, :string, size: 7\\r\\n timestamps\\r\\n end\\r\\n \\r\\n create table(:weather) do\\r\\n add :city, :string, size: 40\\r\\n add :temp_lo, :integer\\r\\n add :temp_hi, :integer\\r\\n add :prcp, :float\\r\\n add :report_id, references(:report)\\r\\n timestamps\\r\\n end\\r\\n end\\r\\n\\r\\nend\\r\\n```\\r\\n\\r\\nHere is the result of ecto.migrate\\r\\n\\r\\n```\\r\\n10:05:45 ecto_play(master) > mix ecto.migrate -all --repo EctoPlay.Repo \\r\\n\\r\\n10:06:41.284 [info] == Running EctoPlay.Repo.Migrations.Meteo.change/0 forward\\r\\n\\r\\n10:06:41.284 [info] create table report\\r\\n\\r\\n10:06:41.290 [info] create table weather\\r\\n\\r\\n10:06:41.297 [info] == Migrated in 0.1s\\r\\n```\\r\\n\\r\\nAnd here is the error rolling it back\\r\\n\\r\\n```\\r\\n10:06:41 ecto_play(master) > mix ecto.rollback -v 20150709201340 --repo EctoPlay.Repo \\r\\n\\r\\n10:06:54.667 [info] == Running EctoPlay.Repo.Migrations.Meteo.change/0 backward\\r\\n\\r\\n10:06:54.667 [info] drop table report\\r\\n** (Postgrex.Error) ERROR (dependent_objects_still_exist): cannot drop table report because other objects depend on it\\r\\n (ecto) lib/ecto/adapters/sql.ex:170: Ecto.Adapters.SQL.query/4\\r\\n (ecto) lib/ecto/adapters/postgres.ex:61: Ecto.Adapters.Postgres.execute_ddl/3\\r\\n _build/dev/lib/ecto_play/priv/repo/migrations/20150709201340_meteo.exs:5: EctoPlay.Repo.Migrations.Meteo.change/0\\r\\n (stdlib) timer.erl:194: :timer.tc/3\\r\\n (ecto) lib/ecto/migration/runner.ex:22: Ecto.Migration.Runner.run/6\\r\\n (ecto) lib/ecto/migrator.ex:113: Ecto.Migrator.attempt/6\\r\\n (ecto) lib/ecto/migrator.ex:93: anonymous fn/4 in Ecto.Migrator.do_down/4\\r\\n (ecto) lib/ecto/adapters/sql.ex:479: Ecto.Adapters.SQL.transaction/9\\r\\n```\\r\\n\\r\\n\",\"score\":1.0}]}", 13 | "headers": { 14 | "Server": "GitHub.com", 15 | "Date": "Tue, 09 Feb 2016 22:58:49 GMT", 16 | "Content-Type": "application/json; charset=utf-8", 17 | "Content-Length": "76545", 18 | "Status": "200 OK", 19 | "X-RateLimit-Limit": "30", 20 | "X-RateLimit-Remaining": "29", 21 | "X-RateLimit-Reset": "1455058789", 22 | "Cache-Control": "no-cache", 23 | "X-OAuth-Scopes": "public_repo", 24 | "X-Accepted-OAuth-Scopes": "repo", 25 | "X-GitHub-Media-Type": "github.v3; format=json", 26 | "Link": "