Upgrade to Pro — share decks privately, control downloads, hide ads and more …

GraphQL を Relay と Phoenix で実装する

Yas Okada
December 09, 2015

GraphQL を Relay と Phoenix で実装する

Yas Okada

December 09, 2015
Tweet

Other Decks in Programming

Transcript

  1. "1*ͷελΠϧ 3&45 ΦʔέετϨʔγϣϯ૚ %#ΞΫηε "1* ˓গͳ͍ɾγϯϓϧ ☓ଟ͍ɾෳࡶ ൚༻ੑ ˓ ☓

    "1*਺ ˓গͳ͍ ☓ଟ͍ "1*਺ը໘ ☓ଟ͍ ˓গͳ͍ ΫϥΠΞϯτ ͝ͱͷ࠷దԽ ☓ ˓
  2. (SBQI2- w 'BDFCPPL͕։ൃ w ΫΤϦʔܕͷ"1* w ̎ͭͷૢ࡞ w RVFSZͱNVUBUJPO query

    Q { viewer { totalCount todos(first:3) { edges { node { id text } } } } }
  3. 3FBDU w 8FCͷ7JFXͷͨΊͷ+BWB4DSJQUϥΠϒϥϦ w 7JSUVBM%0. w ίϯϙʔωϯτࢦ޲ w TUBUF w

    มߋ͢Δͱؔ࿈͢Δίϯϙʔωϯτ͕ߋ৽͞ΕΔ w QSPQT w JNNVUBCMF਌͔Βࢠ΁σʔλΛ౉͢
  4. 3FBDU class Comment extends React.Component {
 render() {
 return (


    <div className="comment">
 <h2 className="commentAuthor">
 {this.props.comment.author}
 </h2>
 {this.props.comment.text}
 </div>
 );
 }
 }
 
 class CommentList extends React.Component {
 : 
 componentDidMount() {
 $.ajax({
 success: function(data) {
 this.setState({comments: data});
 }.bind(this),
 });
 }
 
 render() {
 let commentNodes = this.state.comments.map(comment => {
 return (
 <Comment comment={comment} key={comment.id} />
 );
 });
 
 return (
 <div className="commentList">
 {commentNodes}
 </div>
 );
 }
 }
  5. 3FMBZ 5PEP-JTU 
 export default Relay.createContainer(TodoList, {
 
 fragments: {


    viewer: () => Relay.QL`
 fragment on User {
 completedCount,
 todos(status: $status, first: $limit) {
 edges {
 node {
 id,
 ${Todo.getFragment('todo')},
 },
 },
 },
 }
 `,
 },
 });
 class TodoList extends React.Component {
 renderTodos() {
 return this.props.viewer.todos.edges.map(edge =>
 <Todo
 key={edge.node.id}
 todo={edge.node}
 viewer={this.props.viewer}
 />
 );
 }
 render() {
 return (
 <section className="main">
 <ul className="todo-list">
 {this.renderTodos()}
 </ul>
 </section>
 );
 }
 }

  6. 3FMBZ export default Relay.createContainer(Todo, {
 fragments: {
 todo: () =>

    Relay.QL`
 fragment on Todo {
 complete,
 id,
 text,
 }
 `,
 },
 });
 5PEP class Todo extends React.Component {
 render() {
 return (
 <li>
 <div className=“view"> <input
 checked={this.props.todo.complete}
 className="toggle"
 onChange={this._handleCompleteChange}
 type="checkbox"
 /> <label>
 {this.props.todo.text}
 </label>
 <button
 className="destroy"
 onClick={this._handleDestroyClick}
 />
 </div>
 </li>
 );
 }
 }
  7. &DUP w TFMFDUʹࢦఆ͢ΔΧϥϜΛߏங͠ͳ͚Ε͹ ͳΒ͍ɻ w TFMFDUͷ ͷத͸&DUPಠࣗͷධՁ͕ͩɺ ֎ʹग़Δͱ&MJYJSͱͯ͠ධՁ͞ΕΔͷ Ͱɺ֎ͰߏஙͰ͖ͳ͍ɻ cols

    = %{ title: f.title, summary: f.summary } feed = RssFeed |> Query.select([f], cols) |> Query.limit([u], 1) |> Repo.all fragment on RssFeed {
 title,
 subtitle,
 summary
 }
  8. &DUP w ৽͍͠%4-ʢখ͞ͳϚΫϩʣΛ࡞੒͢Δ w 2VFSZ&YTFMFDU <lUJUMFz lTVNNBSZz>  w &DUPͷTFMFDU͸ԿΛ͍ͯ͠Δ͔ʁ

    w Ecto.Query.Select.build/4ΛݺΜͰ͍Δɻ defmodule Ecto.Query do defmacro select(query, binding, expr) do
 Select.build(query, binding, expr, __CALLER__)
 end end
  9. &DUP defmodule QueryEx do
 defmacro select(query, cols) do
 quote do


    Ecto.Query.Builder.Select.build(unquote(query), [{:f, [], nil}], ɹɹɹɹɹɹQueryEx.make_select(unquote(cols)), __ENV__)
 |> Code.eval_quoted
 |> elem(0)
 end
 end
 
 def make_select(cols) do
 {:%{}, [], make_col([], cols)}
 end
 
 defp make_col(cols, [col|tl]) do
 cols = Keyword.put(cols, String.to_atom(col), ɹɹɹɹɹɹɹɹɹɹɹɹɹɹ{{:., [], [{:f, [], nil}, String.to_atom(col)]}, [], []})
 make_col(cols, tl)
 end
 
 defp make_col(cols, []) do
 cols
 end
 end