Ruby on RailsでSPAアプリケーションを構築する方法論に興味を持った私は、各アプリケーションに実装され、その後個別の
Oxymoron gemに分離されるアイデアを思いつきました。 現時点では、Oxymoronは20を超えるかなり大きな商用鉄道アプリケーションを作成しています。 ヘムを公の裁判所に持ち込みたい。 したがって、私はそれに基づいてさらに物語を進めていきます。
完成したアプリケーションの例。
Oxymoronはどのようなタスクを解決しますか?
私にとって、このgemはルーチンコードの量を1桁削減し、その結果、開発速度を大幅に向上させます。 これにより、AngularJSとRoRの相互運用性を非常に簡単に構築できます。
- routes.rbに基づいて、AngularJSルーティングを自動的に構築する
- routes.rbからAngularJSリソースを自動生成
- AngularJSコントローラーのアーキテクチャの厳密な設定
- 常に使用される構成の処方
- フォーム検証
- FormBuilderが自動的にngモデルを付加する
- 通知
- 一般的に使用されるディレクティブ(ajax fileupload、click-outside、content-for、check-list)
- JsRoutesのコンパクトなアナログの実装
どのように機能しますか?
まず、gemをGemfileに接続する必要があります。
gem 'oxymoron'
これで、
routes.rbを変更する
たびに 、またはアプリケーションを再起動するたびに、アプリケーションを構築するために必要なすべてのコードを含む
oxymoron.jsファイルが
app / asset / javascriptsに生成されます。
次のステップは、アセットを構成することです。 最も単純な場合、次のようになります。
application.jsの場合:
application.cssの場合:
UIルーターを使用するため、レイアウトでui-viewタグを定義する必要があります。 アプリケーションはHTML5ルーティングを使用するため、ベースタグを指定する必要があります。 私たちの場合、これはapplication.html.slimです。 私は
SLIMをプリプロセッサとして使用し、すべての人に強くアドバイスします。
html ng-app="app" head title base href="/" = stylesheet_link_tag 'application' body ui-view = javascript_include_tag 'application'
すべてのAJAXリクエストについて、レイアウトをオフにする必要があります。 これを行うには、ApplicationControllerに必要なロジックを記述します。
layout proc { if request.xhr? false else "application" end }
フォームの正しい処理とng-modelのインストールのために、デフォルトのFormBuilderをOxymoronFormBuilderにオーバーライドする初期化子を作成する必要があります。
ActionView::Base.default_form_builder = OxymoronFormBuilder
最後に行う必要があるのは、アプリケーションにoxymoronモジュールを挿入し、自動生成されたルーティングが使用されることをUIルーターに伝えることです。
var app = angular.module("app", ['ui.router', 'oxymoron']); app.config(['$stateProvider', function ($stateProvider) { $stateProvider.rails() }])
すべてが本格的なSPAアプリケーションを作成する準備ができました!
最も簡単なSPAブログを書きましょう
だから。 最初に、このモデルを管理するためのPostモデルとRESTfulコントローラーを準備します。 これを行うには、コンソールで次のコマンドを実行します。
rails g model post title:string description:text rake db:migrate rails g controller posts index show
routes.rbで、postsリソースを作成します。
Rails.application.routes.draw do root to: "posts#index" resources :posts end
次に、コントローラーのメソッドについて説明します。 多くの場合、同じメソッドが応答でJSON構造とHTMLマークアップの両方を返すことがあるため、そのようなメソッドは
respond_toでラップする必要があります。
典型的なRailsコントローラーの例 class PostsController < ActiveRecord::Base before_action :set_post, only: [:show, :edit, :update, :destroy] def index respond_to do |format| format.html format.json { @posts = Post.all render json: @posts } end end def show respond_to do |format| format.html format.json { render json: @post } end end def new respond_to do |format| format.html format.json { render json: Post.new } end end def edit respond_to do |format| format.html format.json { render json: @post } end end def create @post = Post.new post_params if @post.save render json: {post: @post, msg: "Post successfully created", redirect_to: "posts_path"} else render json: {errors: @post.errors, msg: @post.errors.full_messages.join(', ')}, status: 422 end end def update if @post.update(post_params) render json: {post: @post, msg: "Post successfully updated", redirect_to: "posts_path"} else render json: {errors: @post.errors, msg: @post.errors.full_messages.join(', ')}, status: 422 end end def destroy @post.destroy render json: {msg: "Post successfully deleted"} end private def set_post @post = Post.find(params[:id]) end def post_params params.require(:post).permit(:title, :description) end end
各Railsコントローラーには、AngularJSコントローラーがあります。 マッチングルールは非常に簡単です。
PostsController => PostsCtrl Admin::PostsController => AdminPostsCtrl
app / javascripts / controllers / post_ctrl.jsに適切なコントローラーを作成します。
典型的なAngularJSコントローラーの例 app.controller('PostsCtrl', ['Post', 'action', function (Post, action) { var ctrl = this;
工場出荷時の
措置に注意してください。 これを使用すると、アプリケーションのページ間でコードを分割するのに非常に便利です。 ファクトリーは、oxymoron.jsで生成された状態を介して解決し、その結果、コントローラーの現在のrailメソッドを認識します。
action(['edit', 'new'], function(){
次に、
ポストファクトリに注意してください。 このファクトリは、routes.rbで定義されたリソースから自動的に生成されます。 適切に生成するには、リソースでshowメソッドを定義する必要があります。 次のリソースの操作方法は、ボックスから利用できます。
Post.query()
カスタムリソースメソッド(メンバーとコレクション)はまったく同じように機能します。 例:
resources :posts do member do get "comments", is_array: true end end
AngularJSリソースに適切なメソッドを作成します。
Post.comments({id: id})
応答で配列が予期されることが予想される場合は、
is_array:trueオプションを設定します。 そうでない場合、AngularJSは例外をスローします。
不足しているビューを作成するために残ります。
投稿/ index.html.slim h1 Posts input.form-control type="text" ng-model="search" placeholder="" br table.table.table-bordered thead tr th Date th Title th tbody tr ng-repeat="post in ctrl.posts | filter:search" td ng-bind="post.created_at | date:'dd.MM.yyyy'" td a ui-sref="post_path(post)" ng-bind="post.title" td.w1 a.btn.btn-danger ng-click="ctrl.destroy(post)" a.btn.btn-primary ui-sref="edit_post_path(post)"
投稿/ show.html.slim .small ng-bind="ctrl.post.created_at | date:'dd.MM.yyyy'" a.btn.btn-primary ui-sref="edit_post_path(ctrl.post)" a.btn.btn-danger ng-click="ctrl.destroy(ctrl.post)" h1 ng-bind="ctrl.post.title" p ng-bind="ctrl.post.description"
投稿/ new.html.slim h1 New post = render 'form'
投稿/ edit.html.slim h1 Edit post = render 'form'
投稿/ _form.html.slim = form_for Post.new do |f| div = f.label :title = f.text_field :title div = f.label :description = f.text_area :description = f.submit "Save"
form_forヘルパーの生成結果に特に注意を払う必要があります。
<form ng-submit="formQuery = ctrl.save({form_name: 'post', id: ctrl.post.id, post: ctrl.post}); $event.preventDefault();"></form>
コントローラー内でctrl.saveメソッドを定義するだけで十分です。フォームを送信して表示されるパラメーターを渡すたびに実行されます。 ただし、これらのパラメーターはリソースメソッドの更新および作成の引数として理想的であるため、コントローラーでは
ctrl.save = Post.createのみを記述できます。 PostsCtrlリストでは、このポイントには対応するコメントが付けられています。
ng-model属性は、
text_fieldおよび
text_areaタグに対して自動的に追加されました。 ng-modelコンパイルルールは次のとおりです。
ng-model="ctrl._._"
JSON機能のレンダリング:{}
PostsControllerのレールリストで、おそらくrenderメソッドのmsg、redirect_toなどのフィールドに気付いたでしょう。 これらのフィールドには特別なインターセプターが機能し、結果がコントローラーに送信される前に必要なアクションを実行します。
msg-画面上部の緑色のポップアップに内容が表示されます。 エラーのステータスをレンダリングに渡すと、色が赤に変わります
errors-エラーオブジェクトを受け取り、フォームフィールド自体にエラーを直接表示するのに役立ちます。
redirect_to-必要なUIルーター状態にリダイレクトします
redirect_to_options-状態にオプションが必要な場合、たとえば、show pageにはidが必要な場合、このフィールドでそれらを指定する必要があります
redirect_to_url-指定されたURLにジャンプします
reload-ページをユーザーに完全にリロードします
これらすべてのアクションは、ユーザーページをリロードすることなく実行されます。 UIルーターに基づくHTML5ルーティングを使用します。
今link_toなし
以前は、ルートの名前に応じてリンクを定義する場合、
link_toヘルパーを使用する必要がありました。 現在、この機能はルートを記述する通常の方法で
ui-srefによって実装されています。
a ui-sref="posts_path" a ui-sref="post_path({id: 2})" №2 a ui-sref="edit_post_path({id: 2})" №2 a ui-sref="new_post_path"
js-routesの軽量アナログ。 対立
グローバルスコープでは、Routes変数を見つけることができます。 js-routesとほぼ同じように機能します。 唯一の違いは、この実装はオブジェクトのみを受け入れ、数値引数として砂糖を持たないことです。 競合がある可能性があるため、js-routesを無効にすることをお勧めします。
Routes.posts_path()
まとめ
プリミティブなSPAアプリケーションを作成しました。 同時に、コードは完全にレールに見え、ロジックは最小限に記述されており、すでに最も一般的なものです。 完璧に制限はなく、Oxymoronは理想からほど遠いことを理解していますが、私のアプローチに誰かに興味を持てたことを望みます。 私は宝石の人生に対する批判と積極的な参加に喜んでいます。
完成したアプリケーションの例。