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

Web development that hurts even less: taking lessons from Rails

Web development that hurts even less: taking lessons from Rails

It has been over ten years since the Rails framework brought Ruby to the forefront of web development. You might think Ruby is synonymous to Rails, but there’s more to the community than that. New languages and frameworks are no longer aiming to merely imitate Ruby and Rails — they are aiming to improve upon it. Lotus, ROM, Phoenix, Ecto, Sequel, Roda, Webpack: they all represent lessons learned about how we build software. It’s time to broaden our horizon (even if only a little bit). As good as Rails is, can we do better?

Arjan van der Gaag

November 14, 2015
Tweet

More Decks by Arjan van der Gaag

Other Decks in Programming

Transcript

  1. “So that's why I love software. It's not like modern

    art. You can't just keep spouting intellectual nonsense forever. At the end of the day, you have to translate your prescriptions into running code and that's when the bullshit meter activates.”
  2. module Web::Controllers::Articles class Show include Web::Action expose :article def call(params)

    @article = ArticleRepository .published .find(params[:id]) end end end
  3. module Web::Controllers::Articles class Create include Web::Action expose :article def call(params)

    @article = ArticleRepository .published .find(params[:id]) end end end
  4. module Web::Controllers::Articles class Create include Web::Action expose :article def call(params)

    @article = ArticleRepository .published .find(params[:id]) end end end
  5. module Web::Controllers::Articles class Create include Web::Action expose :article def call(params)

    @article = ArticleRepository .published .find(params[:id]) end end end
  6. module Web::Controllers::Articles class Create include Web::Action expose :article def call(params)

    @article = ArticleRepository .published .find(params[:id]) end end end
  7. module Web::Controllers::Articles class Create include Web::Action expose :article def call(params)

    @article = ArticleRepository .published .find(params[:id]) end end end
  8. module Web::Controllers::Articles class Create include Web::Action expose :article def call(params)

    @article = ArticleRepository .published .find(params[:id]) end end end
  9. class Article < ActiveRecord::Base validates :title, presence: true, unless: :draft?

    validates :slug, presence: true, on: :update before_validate :set_slug end
  10. class Article < ActiveRecord::Base validates :title, presence: true, unless: :draft?

    validates :slug, presence: true, on: :update before_validate :set_slug, on: :create end
  11. “There are nineteen callbacks in total, which give you immense

    power to react and prepare for each state in the Active Record life cycle.”
  12. defmodule Article do schema "articles" do field :title end @required_fields

    ~w(title) def changeset(article, params \\ :empty) do article |> cast(params, @required_fields, []) |> validate_length(:title, max: 255) end end
  13. class UserRepository < ROM::Repository::Base relations :users, :tasks def with_tasks(id) users.by_id(id)

    .combine_children(many: tasks) end end user_repo.with_tasks.to_a # [#<ROM::Struct[User] id=1 name="Jane" tasks=[#<ROM::Struct[Task] id=2 user_id=1 title="Jane Task">]>]
  14. class PostMapper < ROM::Mapper attribute :title, from: 'post_title' wrap :author

    do attribute :name, from: 'post_author' attribute :email, from: 'post_author_email' end end
  15. class Article < ActiveRecord::Base has_many :comments end article = Article.new

    article.comments # => <#ActiveRecord::Relation []>
  16. “Ecto does not provide functions like post.comments << comment that

    allows mixing persisted data with non-persisted data.”
  17. query = from a in Article, limit: 1 article =

    Repo.one(query) article.comments # => Ecto.Association.NotLoaded
  18. query = from a in Article, preload: [:comments], limit: 1

    article = Repo.one(query) article.comments # => []
  19. “Lazy loading is often a source of confusion and performance

    issues and Ecto pushes developers to do the proper thing.”
  20. class ArticlesController def index @articles = Article.recent respond_to do |format|

    format.html format.xml do @articles = @articles.limit(10) end end end end