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

    View Slide

  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

    View Slide

  3. Phoenix contributors

    View Slide

  4. ME in Blue !

    View Slide

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

    View Slide

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

    View Slide

  7. Ruby on Rails
    vs
    Phoenix Framework

    View Slide

  8. Why this theme?

    View Slide

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

    View Slide

  10. • Scaffold mix phoenix.gen.html
    • eex template: erb like template
    • growing document
    • WebSocket
    • Performance
    • created apps in M3 Hackathon

    View Slide

  11. ! May Phoenix becomes instead
    of Rails

    View Slide

  12. ❓ How to improve my Rails app
    performance

    View Slide

  13. Use Phoenix

    View Slide

  14. Agenda
    • introduction
    • comparison in development
    • performance

    View Slide

  15. introduction

    View Slide

  16. Rails

    View Slide

  17. Programmer Happiness
    sustainable productivity

    View Slide

  18. Phoenix

    View Slide

  19. Speed
    Fun development environment

    View Slide

  20. Rails ⭐ 26325 1
    Phoenix ⭐ 2614 1
    1 at 2015/05/31

    View Slide

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

    View Slide

  22. Compare Phoenix features with Rails
    supported
    • WebSocket
    • Rails 5 plan to include this, but needs Redis

    View Slide

  23. Compare Phoenix features with Rails
    unsupported
    • Assets pipeline
    • brunch.io for JavaScript
    • SQLite adapter
    • https://github.com/jazzyb/sqlite_ecto

    View Slide

  24. Phoenix ≒ Rails + Speed
    thought

    View Slide

  25. Comparison in development

    View Slide

  26. • File Structure
    • Scaffold
    • Router
    • Controller
    • View
    • Model
    • Mailer
    • Assets

    View Slide

  27. View Slide

  28. Scaffold
    • Rails
    $ rails g scaffold todo content:text done:boolean
    • Phoenix
    $ mix phoenix.gen.html Todo todos content:text done:boolean

    View Slide

  29. Router
    # config/routes.rb
    resources :todos
    # web/router.ex
    resources "/todos", TodoController

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  35. View/Template: collection in Rails





    View Slide

  36. View/Template: collection in Phoenix



    class: "btn btn-default btn-xs" %>

    View Slide

  37. View/Template: partial render



    action: todo_path(@conn, :create) %>

    View Slide

  38. View/Template: form in Rails










    View Slide

  39. View/Template: form in Phoenix

    %>



    Content




    View Slide

  40. Model in Rails
    # app/models/todo.rb
    class Todo < ActiveRecord::Base
    # validations
    # queries
    end

    View Slide

  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

    View Slide

  42. in scaffolded controller
    # Rails
    @todos = Todo.all
    # Phoenix
    todos = Repo.all(Todo)

    View Slide

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

    View Slide

  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

    View Slide

  45. Mailer
    • Rails
    • ActionMailer
    • Phoenix
    • not provided
    • use other libraries such as gen_smtp

    View Slide

  46. Assets
    • Rails
    • Asset Pipeline
    • Phoenix
    • Brunch.io, gulp, etc...

    View Slide

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

    View Slide

  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

    View Slide

  49. Phoenix ≒ Rails
    development

    View Slide

  50. Performance

    View Slide

  51. NOTICE !
    • Not same template file
    • On my macbook air
    • Rough measurement
    • Using WebRick server for Rails app

    View Slide

  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

    View Slide

  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)

    View Slide

  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)

    View Slide

  55. 3X faster !

    View Slide

  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)

    View Slide

  57. Phoenix > Rails
    performance

    View Slide

  58. Phoenix is
    Rails like development
    with Speed

    View Slide

  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

    View Slide

  60. We're hiring!
    at.m3.com/job

    View Slide

  61. Enjoy

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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/

    View Slide

  66. Resources: Hex
    • Publishing a package
    • https://hex.pm/docs/publish
    • Hex Ͱ Elixir ͷϥΠϒϥϦΛϦϦʔε͢Δํ๏
    • http://qiita.com/ma2ge/items/0e19bf3f03078f589096

    View Slide

  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

    View Slide