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. 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