Rails開発者のためのフェニックス実用例−第1部


これはフェニックス、エリクサーのWebフレームワークへの入門記事です.それはダイビングに物事の多くの大きなフレームワークであるので、完全なガイドであることを意図していないが、むしろ物事が古典的なブログの例で自分たちのベストプラクティスにいくつかの洞察をスローするために提供する足場を使用して両方のフレームワークで行われている方法の側の比較を示すために.
それは2つの部分ブログ記事です、前半で、我々は両方のフレームワークが最も類似しているウェブ層を見ます.
アイデアは、彼らがどのように似て表示するには、十分に自分でそれを試して宣伝!

導入


私は多くの言語の探索的な段階が私にそれを導いた後にルビーに取り組んだ.構文はちょうど私を魅了しました、それが英語のように読まれることができたように、それはとても表現力があって、それが私にこれまでより多くの生産的に物事をするのを許した多くのツールを持っていました.これ以上の文字列ヘルパー関数や配列を操作するための厄介なループは、ボックスのすべてのそれらのものを持つことができるだけであなたのソリューションをコーディングに焦点を当てる.しばらくして私は柵を見つけ、ルビーの哲学と共に感じた.私は他のツールよりも生産的であると感じました、そして、それは含まれるバッテリーで来ました.すべての作業を行う必要があるライブラリの設定や研究の時間.
その時以来、私はいろいろな言語で多くの他のウェブ開発フレームワークを試みました、しかし、私は彼らのどれとも家で決して感じませんでした.たとえ多くの人が何か欠けているのかを模索しようとしていたとしても、それが何かを欠落していたとしても、それが言語のためであったのか、あるいはそれが発散したかという決定のために、彼らはいつも私にとって単なるコピーのように感じた.

フェニックス


eLixVirtual Machineの上で走るRubyのような構文で、Elixir(機能言語)の上に構築されるウェブフレームワークに入ってください.このフレームワークはRailsを作る機能の多くの後に取りました:MVCアーキテクチャ、独断的なファイル構造、ORM、テンプレートエンジンとルーティング層のようなツールを含めました.しかし、それは決して別のコピーにしようとして、代わりに、時間とともに分岐し、生産性や開発者の幸福を犠牲にすることなく、すべての機能のパラダイムと異なる言語に合うように多くの意思決定を行った.
時間内に、これは独立したWebフレームワークにつながったが、その特別な風味で我々はすべてのレールから愛している.Elxirは非常にスケーラブルなアプリケーションを構築するように設計されたErlangの上に構築されていたので、一つの違いがあります.これはあなたが離れて大きなリーグに到達したら、アプリが実行される方法について心配することなくコード化することができます.これは、多くのレールのアプリの闘争は、何かであり、それはなぜジョイスValimは最初の場所でエリクサーを開発した主な理由です.
しかし、十分な説教、行動でそれを見ましょう!

ファイル構造


どのようにファイルを整理するかを取ることなく、完全なフレームワークは完全ではありません.では、まず最初にフォルダービューから見たものを見てみましょう.これは、両方のフレームワークを使用してアプリケーションを生成するときに取得します.

フェニックスの構造は、パッケージ(EmacxirのGemに相当する)がどのように構成されているかを継承し、カスタムコードはlib/ フォルダ.内部では、すぐにこの面で両方のフレームワークの間に主な違いを見つけるでしょう:フェニックスは、ビジネスロジックからWebプレゼンテーションの層を分離します.上の画像ではblog/ ビジネスロジックをビルドするための基本モジュールを含むフォルダblog_web これは柵にかなり似ているapp/ ディレクトリ.いくつかの微妙な違いがありますが、以下のセクションでそれらを深く見ていきます.

足場離れた


私が言及したように、両方のフレームワークは、アプリケーションの異なる部分を足場にするためのコマンドを提供します.この例では、ビューとルートを含む完全なリソースを生成する出力を比較します.
bin/rails generate scaffold Article title:string text:text
mix phx.gen.html Articles Article articles title:string text:text
もう一度、微妙な違いで類似しているように見えます.この場合、フェニックスは、それが作成される文脈モジュールを指定するよう頼むことによって、より冗長なファッションのために行きます.

路線


すべてのWebリクエストは正しいハンドラにルーティングされることから始まり、単純なルートで最初に行きましょう.
Rails.application.routes.draw do
  resources :articles
end
Railsのルートは、あなたがそれらを知るようになると、かなり簡単です.彼らは、エンドポイントのユーザーが利用可能なエンドポイントを指定しますauthenticate メソッド.要求の操作は、コントローラ上で行われ、時からは、値がどこから来たかを知るのは少し難しいです.フェニックスにはこれに違いがあります.
defmodule BlogWeb.Router do
  use BlogWeb, :router

  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_flash
    plug :protect_from_forgery
    plug :put_secure_browser_headers
  end

  pipeline :api do
    plug :accepts, ["json"]
  end

  scope "/", BlogWeb do
    pipe_through :browser

    resources "/articles", ArticleController
    get "/", PageController, :index
  end


  scope "/api", BlogWeb do
    pipe_through :api
  end
end
それはより多くのコードです、しかし、ちょうどより多くの責任があるので.The plug ここで参照するコールは、ミドルウェアと比較される可能性のあるものを定義します.彼らはpipeline 関数は、スコープ内でコールされることができます(これは柵のようなものです)、構文解析、認証、認証、そして何か他の何かを実行する前にやりたいことを実行するために.
これは、ユーザーを認可して、ほとんどの時間を要求することを拒絶することのロジックからのデカップリングコントローラを許しますbefore_action 呼び出しと多くの場合、コントローラ間の複雑な継承の必要性を減らします.

コントローラ


次のステップは実際のハンドリングです.これは両方のFameWorksがMVCパターンに従っているためです.これらのために、私はちょうど若干の行動を示して、違いの速いチュートリアルをすることに決めました.あなたがエリクサーの構文でもう少し学ぶことに興味があるならばElixir Getting Started Guide 出発する良い場所です.それ以上のADOなしで、私はあなたにコントローラに出席します:
class ArticlesController < ApplicationController
  before_action :set_article, only: [:show,
                                     :edit,
                                     :update,
                                     :destroy]

  def index
    @articles = Article.all
  end

 def new
    @article = Article.new
  end

 def create
    @article = Article.new(article_params)

    respond_to do |format|
      if @article.save
        format.html { redirect_to @article }
        format.json { render :show, status: :created,
                             location: @article }
      else
        format.html { render :new }
        format.json { render json: @article.errors,
                             status: :unprocessable_entity }
      end
    end
  end
end
defmodule BlogWeb.ArticleController do
  use BlogWeb, :controller

  alias Blog.Articles
  alias Blog.Articles.Article

  def index(conn, _params) do
    articles = Articles.list_articles()
    render(conn, "index.html", articles: articles)
  end

  def new(conn, _params) do
    changeset = Articles.change_article(%Article{})
    render(conn, "new.html", changeset: changeset)
  end

  def create(conn, %{"article" => article_params}) do
    case Articles.create_article(article_params) do
      {:ok, article} ->
        conn
        |> put_flash(:info, "Article created successfully.")
        |> redirect(to: Routes.article_path(conn, :show, article))

      {:error, %Ecto.Changeset{} = changeset} ->
        render(conn, "new.html", changeset: changeset)
    end
  end
end
ここでの主な違いはプログラミングパラダイムです.Elixirは機能的であるので、要求(または接続)とparamsは行動のパラメタとして受け取られます.それでも、構文は全く似ています、そして、私はそれがフェニックス断片で起こっていることの把握を得るのが簡単であると思います.
もう一つの小さな違いは、フェニックスで使用されるジェネレータがちょうどHTMLに反応するコントローラを足場にするということです、そして、RailsはJSONとHTMLの両方の意見を表示します.もちろん、JSONリソースを作成する別のジェネレータがありますが、別のパイプラインに行く新しいコントローラを作成します(ルートセクションに戻る場合は、そこに表示されます):api パイプライン).

ヘルパーと見解


最後には、少なくともWeb層上のデータを提示する方法です.ファイル構造体には2つのディレクトリがあることに気づいたでしょうviews/ and templates/ フェニックスのプロジェクトの構造では、あなたが行っていない場合は、近いビューを取る.あなたは、それらの間の違いは、よく、テンプレートだけでは、埋め込まれたコード(私たちはEexを持っているERBのようなテキストファイル)は、要求に応答するために使用されていると思われるかもしれません.一方で、ビューはヘルパーに似ていますが、1つの顕著な違いがあります.
例えば、彼らが例によって異なる方法を見てみましょう私たちの記事の読み取り時間を示したいと思います.DBにこの値を追跡していないので、プレゼンテーションのためだけにこのようにヘルパーに置きたいと思います.
module ArticlesHelper
  WORDS_PER_MINUTE = 200

  def read_time(article)
    words_count = article.text.split.size
    read_time_in_minutes = words_count / WORDS_PER_MINUTE.to_f
    #{read_time_in_minutes.ceil} minutes"
  end
end
簡単なペイシー、今我々はちょうど私たちのこの上で呼び出す必要がありますshow.html.erb そして、我々はされます.それほど速くないので、私がこれで見る問題は、それがあらゆる見解に含まれるということです.確かに、このような小さなアプリケーションのために、特定の名前のように、問題はないが、それが成長し始めると、あなたのような名前を持つヘルパーを持ってformat_title and format_title_for_user あなたはトラブルを開始します.フェニックスのヘルパー(またはフレームワークで呼ばれるビュー)は非常によく似ています.
defmodule BlogWeb.ArticleView do
  use BlogWeb, :view

  alias Blog.Articles.Article

  @words_per_minute 200

  defp read_time(%Article{text: text}) do
    words_count =
      text
      |> String.split(" ")
      |> Enum.count()
    read_time_in_minutes = Float.ceil(words_count / @words_per_minute)
    "#{trunc(read_time_in_minutes)} minutes"
  end
end
しかし、私が前に言ったように、彼らはいくつかのプレゼンターにスコープされているので、このビューは、例えば、記事テンプレート上でのみ呼び出すことができる機能を持っています.これは、グローバルスコープを汚染しない知っている任意の名前を使用することができます.そして、あなたは多くのテンプレート間で共通の機能を使用する場合はどうですか?シンプルで、これらの関数を使って別のモジュールを作成し、必要なビューを越えます.

フォローアップ


これは、Web層の違いの短いチュートリアルを終了します.次に、このポストの2番目の部分では、データとビジネス層です.