Ruby on Rails vs Phoenix Framework #shinjukuex #m3dev

Ruby on Rails vs Phoenix Framework #shinjukuex #m3dev

comparing Phoenix to Rails in development

509e5167fdb3871d6b6e045e34a3e019?s=128

Takayuki Matsubara

June 02, 2015
Tweet

Transcript

  1. Ruby on Rails vs Phoenix Framework 2015/06/02 #shinjukuex #10

  2. 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
  3. Phoenix contributors

  4. ME in Blue !

  5. http://qiita.com/HirofumiTamori/items/0dfdbada30c7d8f183fd

  6. http://qiita.com/mizchi/items/e38d3f0461fe316021f7

  7. Ruby on Rails vs Phoenix Framework

  8. Why this theme?

  9. ! Is an Elixir/Phoenix app appropriate for only middleware or

    backend service?
  10. • Scaffold mix phoenix.gen.html • eex template: erb like template

    • growing document • WebSocket • Performance • created apps in M3 Hackathon
  11. ! May Phoenix becomes instead of Rails

  12. ❓ How to improve my Rails app performance

  13. Use Phoenix

  14. Agenda • introduction • comparison in development • performance

  15. introduction

  16. Rails

  17. Programmer Happiness sustainable productivity

  18. Phoenix

  19. Speed Fun development environment

  20. Rails ⭐ 26325 1 Phoenix ⭐ 2614 1 1 at

    2015/05/31
  21. Rails version: 4.2.1 1 Phoenix version: 0.13.1 1 1 at

    2015/05/31
  22. Compare Phoenix features with Rails supported • WebSocket • Rails

    5 plan to include this, but needs Redis
  23. Compare Phoenix features with Rails unsupported • Assets pipeline •

    brunch.io for JavaScript • SQLite adapter • https://github.com/jazzyb/sqlite_ecto
  24. Phoenix ≒ Rails + Speed thought

  25. Comparison in development

  26. • File Structure • Scaffold • Router • Controller •

    View • Model • Mailer • Assets
  27. None
  28. Scaffold • Rails $ rails g scaffold todo content:text done:boolean

    • Phoenix $ mix phoenix.gen.html Todo todos content:text done:boolean
  29. Router # config/routes.rb resources :todos # web/router.ex resources "/todos", TodoController

  30. 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
  31. 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
  32. 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
  33. 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
  34. 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
  35. View/Template: collection in Rails <%# app/views/todos/index.html.erb %> <% @todos.each do

    |todo| %> <%= todo.content %> <%= link_to 'Show', todo %> <% end %>
  36. 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 %>
  37. View/Template: partial render <%# *.erb %> <%= render 'form' %>

    <%# *.eex %> <%= render "form.html", changeset: @changeset, action: todo_path(@conn, :create) %>
  38. 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 %>
  39. 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 %>
  40. Model in Rails # app/models/todo.rb class Todo < ActiveRecord::Base #

    validations # queries end
  41. 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
  42. in scaffolded controller # Rails @todos = Todo.all # Phoenix

    todos = Repo.all(Todo)
  43. in realworld controller # Rails @todos = Todo.recent(page) # Phoenix

    todos = Todo.recent(page)
  44. 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
  45. Mailer • Rails • ActionMailer • Phoenix • not provided

    • use other libraries such as gen_smtp
  46. Assets • Rails • Asset Pipeline • Phoenix • Brunch.io,

    gulp, etc...
  47. Test • Rails • RSpec, Minitest, etc... • Phoenix •

    ExUnit
  48. Ecosystem • Ruby/Rails -> Rubygems • many gems • Elixir/Phoenix

    -> Hex • few • potential to increse • Hex is easy to use • http://qiita.com/ma2ge/items/0e19bf3f03078f589096
  49. Phoenix ≒ Rails development

  50. Performance

  51. NOTICE ! • Not same template file • On my

    macbook air • Rough measurement • Using WebRick server for Rails app
  52. 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
  53. Performance: development $ ab -n 50 localhost:3000/todos # Rails Requests

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

    per second: 149.14 [#/sec] (mean) # Phoenix Requests per second: 450.58 [#/sec] (mean)
  55. 3X faster !

  56. 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)
  57. Phoenix > Rails performance

  58. Phoenix is Rails like development with Speed

  59. 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
  60. We're hiring! at.m3.com/job

  61. Enjoy

  62. 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
  63. 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
  64. Resources: Mail Library in Elixir • gen_smtp • https://github.com/Vagabond/gen_smtp •

    mailman • https://hex.pm/packages/mailman • https://github.com/kamilc/mailman
  65. 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/
  66. Resources: Hex • Publishing a package • https://hex.pm/docs/publish • Hex

    Ͱ Elixir ͷϥΠϒϥϦΛϦϦʔε͢Δํ๏ • http://qiita.com/ma2ge/items/0e19bf3f03078f589096
  67. 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