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

Ruby on Rails vs Phoenix Framework #shinjukuex #m3dev

Ruby on Rails vs Phoenix Framework #shinjukuex #m3dev

comparing Phoenix to Rails in development

Takayuki Matsubara

June 02, 2015
Tweet

More Decks by Takayuki Matsubara

Other Decks in Programming

Transcript

  1. self-introduction ! • Takayuki Matsubara @ma2ge/@ma2gedev • Application Engineer @

    M3, Inc. • Rails/Java/JavaScript application • Ruby: breadcrumble, chrono_logger, bundle-star • Elixir: ltsvex, netrcex, qiita_ex • whisky
  2. • Scaffold mix phoenix.gen.html • eex template: erb like template

    • growing document • WebSocket • Performance • created apps in M3 Hackathon
  3. Compare Phoenix features with Rails unsupported • Assets pipeline •

    brunch.io for JavaScript • SQLite adapter • https://github.com/jazzyb/sqlite_ecto
  4. Scaffold • Rails $ rails g scaffold todo content:text done:boolean

    • Phoenix $ mix phoenix.gen.html Todo todos content:text done:boolean
  5. Named routes: Rails $ rake routes Prefix Verb URI Pattern

    Controller#Action todos GET /todos(.:format) todos#index POST /todos(.:format) todos#create new_todo GET /todos/new(.:format) todos#new edit_todo GET /todos/:id/edit(.:format) todos#edit todo GET /todos/:id(.:format) todos#show PATCH /todos/:id(.:format) todos#update PUT /todos/:id(.:format) todos#update DELETE /todos/:id(.:format) todos#destroy
  6. Named routes: Phoenix $ mix phoenix.routes page_path GET / PhoenixApp.PageController.index/2

    todo_path GET /todos PhoenixApp.TodoController.index/2 todo_path GET /todos/:id/edit PhoenixApp.TodoController.edit/2 todo_path GET /todos/new PhoenixApp.TodoController.new/2 todo_path GET /todos/:id PhoenixApp.TodoController.show/2 todo_path POST /todos PhoenixApp.TodoController.create/2 todo_path PATCH /todos/:id PhoenixApp.TodoController.update/2 PUT /todos/:id PhoenixApp.TodoController.update/2 todo_path DELETE /todos/:id PhoenixApp.TodoController.delete/2
  7. Controller: index action # app/controllers/todos_controller.rb def index @todos = Todo.all

    end # web/controllers/todo_controller.ex def index(conn, _params) do todos = Repo.all(Todo) render(conn, "index.html", todos: todos) end
  8. Controller: create action in Rails # app/controllers/todos_controller.rb def create @todo

    = Todo.new(todo_params) if @todo.save redirect_to @todo, notice: 'Todo was successfully created.' else render :new end end
  9. Controller: create action in Phoenix # web/controllers/todo_controller.ex def create(conn, %{"todo"

    => todo_params}) do changeset = Todo.changeset(%Todo{}, todo_params) if changeset.valid? do Repo.insert(changeset) conn |> put_flash(:info, "Todo created successfully.") |> redirect(to: todo_path(conn, :index)) else render(conn, "new.html", changeset: changeset) end end
  10. View/Template: collection in Rails <%# app/views/todos/index.html.erb %> <% @todos.each do

    |todo| %> <%= todo.content %> <%= link_to 'Show', todo %> <% end %>
  11. View/Template: collection in Phoenix <%# web/templates/todo/index.html.eex %> <%= for todo

    <- @todos do %> <%= todo.content %> <%= link "Show", to: todo_path(@conn, :show, todo), class: "btn btn-default btn-xs" %> <% end %>
  12. View/Template: partial render <%# *.erb %> <%= render 'form' %>

    <%# *.eex %> <%= render "form.html", changeset: @changeset, action: todo_path(@conn, :create) %>
  13. View/Template: form in Rails <%# *.erb %> <%= form_for(@todo) do

    |f| %> <% @todo.errors.full_messages.each do |message| %> <%= message %> <% end %> <%= f.label :content %> <%= f.text_area :content %> <%= f.check_box :done %> <%= f.submit %> <% end %>
  14. View/Template: form in Phoenix <%# *.eex %> <%= form_for @changeset,

    @action, fn f -> %> <%= for {attr, message} <- f.errors do %> <%= humanize(attr) %> <%= message %> <% end %> <label>Content</label> <%= textarea f, :content, class: "form-control" %> <%= checkbox f, :done, class: "form-control" %> <%= submit "Submit", class: "btn btn-primary" %> <% end %>
  15. Model in Phoenix # web/models/todo.ex defmodule PhoenixApp.Todo do use PhoenixApp.Web,

    :model schema "todos" do field :content, :string field :done, :boolean, default: false timestamps end @required_fields ~w(content done) @optional_fields ~w() def changeset(model, params \\ :empty) do model |> cast(params, @required_fields, @optional_fields) end end
  16. Query def self.recent(page) order(created_at: :desc) .offset((page.to_i - 1) * SIZE)

    .limit(SIZE) end def recent(page) do from(p in Todo, order_by: [desc: p.inserted_at], offset: ^((String.to_integer(page) - 1) * @size), limit: ^@size) |> Repo.all end
  17. Mailer • Rails • ActionMailer • Phoenix • not provided

    • use other libraries such as gen_smtp
  18. Ecosystem • Ruby/Rails -> Rubygems • many gems • Elixir/Phoenix

    -> Hex • few • potential to increse • Hex is easy to use • http://qiita.com/ma2ge/items/0e19bf3f03078f589096
  19. NOTICE ! • Not same template file • On my

    macbook air • Rough measurement • Using WebRick server for Rails app
  20. code # app/controllers/todos_controller.rb def index @todos = Todo.all end #

    web/controllers/todo_controller.ex def index(conn, _params) do todos = Repo.all(Todo) render(conn, "index.html", todos: todos) end
  21. Performance: development $ ab -n 50 localhost:3000/todos # Rails Requests

    per second: 21.85 [#/sec] (mean) # Phoenix Requests per second: 37.08 [#/sec] (mean)
  22. Performance: production $ ab -n 50 localhost:3000/todos # Rails Requests

    per second: 149.14 [#/sec] (mean) # Phoenix Requests per second: 450.58 [#/sec] (mean)
  23. Performance: production $ ab -n 500 -c 100 localhost:4000/todos #

    Rails same as single request mode, because WebRick server # Phoenix Requests per second: 1291.92 [#/sec] (mean)
  24. Conclusion/IMO • Elixir/Phoenix is not only for middleware but also

    web application • Phoenix has potential to switch current Rails application • Performance • Targeting developer happiness
  25. Resources: Rails and Phoenix • Ruby on Rails • http://rubyonrails.org/

    • https://github.com/rails/rails • Phoenix Framework • http://www.phoenixframework.org/ • https://github.com/phoenixframework/phoenix
  26. Resources: Libraries • Awesome Elixir • https://github.com/h4cc/awesome-elixir • PlugRailsCookieSessionStore •

    Rails compatible Plug session store • https://github.com/cconstantin/ plug_rails_cookie_session_store
  27. Resources: Mail Library in Elixir • gen_smtp • https://github.com/Vagabond/gen_smtp •

    mailman • https://hex.pm/packages/mailman • https://github.com/kamilc/mailman
  28. Resources: Ecto • Ecto • https://github.com/elixir-lang/ecto • Composable Queries with

    Ecto • http://blog.drewolson.org/composable-queries-ecto/ • Ecto vs Active Record • http://learnelixir.com/blog/2014/10/11/ecto-vs-active- record/
  29. Resources: Hex • Publishing a package • https://hex.pm/docs/publish • Hex

    Ͱ Elixir ͷϥΠϒϥϦΛϦϦʔε͢Δํ๏ • http://qiita.com/ma2ge/items/0e19bf3f03078f589096
  30. Resources: Performance • Elixir vs Ruby Showdown - Phoenix vs

    Rails • http://www.littlelines.com/blog/2014/07/08/elixir-vs- ruby-showdown-phoenix-vs-rails/ • Benchmarking Phoenix vs Rails vs Sinatra vs Express vs Martini... • https://github.com/mroth/phoenix-showdown