AngularJSとRails4の使用を開始する
AngularJSの使用を開始するのは難しくありません。ドキュメントはそこにある最高のもののいくつかであり、チュートリアルは十分に単純です。
しかし、テクノロジーを組み合わせ始めると、物事はトリッキーになります。
ストレートJavaScriptの代わりにCoffeeScriptを使用している場合は、前処理の問題と、明らかな構文の違いを考慮に入れる必要があることをご存知でしょう。これらはそれ自体は小さな問題ですが、Ruby on Rails、Jasmine、Karmaを組み合わせて使用するとどうなりますか?驚くほどトリッキーになります。
これはまさに、このチュートリアルで使用するスタックです。私たちが罰の無駄遣いであるからではなく、これは現実の世界で見られるような設定だからです。
このチュートリアルは、Railsに慣れていることを前提としていますが、必ずしもAngularJSである必要はありません。
非常に多くのテクノロジーレイヤーが関係しているので、ほとんど何もしない単純なアプリケーションを作成します。レストラン用にCRUD機能を設定します。実際にはCR部分だけです。 -UDは、読者の練習問題として残されています。;-)
このアプリケーションをレストラン経営者と呼びます 。
ここではPostgreSQLとRSpecを使用していますが、DBMSとサーバー側のテストフレームワークは重要ではありません。好きなものを使うことができます。
最初にプロジェクトを作成します:
$ rails new restauranteur --database=postgresql --skip-test-unit
Powを使用している場合は、プロジェクトをPowに追加します:
$ ln -s /Users/jasonswett/projects/restauranteur ~/.pow/restauranteur
PostgreSQLデータベースユーザーを作成します:
$ createuser -P -s -e restauranteur
RSpecをGemfileに追加します:
# Gemfile
gem "rspec-rails", "~> 2.14.0"
RSpecのインストール:
$ bundle install
$ rails g rspec:install
データベースを作成します:
$ rake db:create
プロジェクトとデータベースが作成されたので、最初のリソースを作成しましょう。レストランリソースには、名前という1つの属性のみがあります。 、これは文字列です。
$ rails generate scaffold restaurant name:string
さて、それについてのOCDであるために、レストラン名が一意であることを確認します。
# db/migrate/[timestamp]_create_restaurants.rb
class CreateRestaurants < ActiveRecord::Migration
def change
create_table :restaurants do |t|
t.string :name
t.timestamps
end
# Add the following line
add_index :restaurants, :name, unique: true
end
end
移行を実行します:
$ rake db:migrate
無効なレストランを作成できないことを確認するために、いくつかの仕様を追加しましょう。固有障害が生のエラーをもたらすことに注意してください。
require 'spec_helper'
describe Restaurant do
before do
@restaurant = Restaurant.new(name: "Momofuku")
end
subject { @restaurant }
it { should respond_to(:name) }
it { should be_valid }
describe "when name is not present" do
before { @restaurant.name = " " }
it { should_not be_valid }
end
describe "when name is already taken" do
before do
restaurant_with_same_name = @restaurant.dup
restaurant_with_same_name.name = @restaurant.name.upcase
restaurant_with_same_name.save
end
it { should_not be_valid }
end
end
これらのバリデーターを追加すると、仕様に合格します:
class Restaurant < ActiveRecord::Base
validates :name, presence: true, uniqueness: { case_sensitive: false }
end
これで先に進むことができます。
AngularJSをミックスに取り入れます
すべてを一度にダンプするのではなく、まずAngularJS-Railsアプリケーションの最も単純な「Hello、world」バージョンをデモンストレーションしてから、レストランのCRUD機能をその上に構築したいと思います。
「Hello、world」ページを特定のRailsリソースに関連付ける必要がある、または関連付ける必要がある理由はありません。このため、StaticPagesController
を作成します AngularJSホームページを提供します。
$ rails generate controller static_pages index
現在のルートルートは、「WelcometoRails」ページです。 index
に設定しましょう 新しいStaticPagesController
のアクション :
# config/routes.rb
Restauranteur::Application.routes.draw do
# Add the following line
root 'static_pages#index'
end
- 後でテストを正しく機能させるには、
angular-mocks.js
というファイルが必要です。 。 Angularのドキュメントにはこれについての言及はどこにもないと思いますが、必要です。 - AngularJSチュートリアルでは、ドキュメントに最新の最先端バージョンがリストされていますが、正しく思い出せば、
angular.js
間の互換性に問題がありました。 およびangular-mocks.js
最新バージョンの場合。バージョン1.1.5が連携して動作したことはわかっているので、これは最新の安定バージョンではありませんが、ここにリストしているバージョンです。もちろん、時間が経つにつれて、互換性の状況はおそらく改善されるでしょう。
angular.js
をダウンロードする およびangular-mocks.js
code.angularjs.orgから、ファイルをapp/assets/javascripts
に移動します 。
$ wget https://code.angularjs.org/1.1.5/angular.js \
https://code.angularjs.org/1.1.5/angular-mocks.js
$ mv angular* app/assets/javascripts
次に、アプリケーションにAngularJSファイルを要求するように指示し、それに依存する他のファイルよりも先にファイルが読み込まれるようにします。 (これらの依存関係を管理するためにRequireJSのようなものを使用できます。これはおそらく本番製品で行うことですが、このチュートリアルの目的のために、テクノロジースタックを可能な限り薄くしたいと思います。)
注: AngularとTurbolinkは互いに競合する可能性があるため、ここでは無効にします
// app/assets/javascripts/application.js
// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
// Add the following two lines
//= require angular
//= require main
//= require_tree .
ng-appとng-viewを追加します。これらは、ページにAngularアプリがあることを示します。また、ターボリンクの言及が削除されていることにも注意してください。
<%= yield %>
まず、コントローラー用のディレクトリを作成しましょう。好きな名前を付けることができます。
$ mkdir -p app/assets/javascripts/angular/controllers
それでは、コントローラーファイル自体を作成しましょう。私はこのコントローラーを「ホームコントローラー」と呼んでいます。Angularの規則では、コントローラーのファイル名にCtrl
を追加します。 。したがって、ファイル名はapp/assets/javascripts/angular/controllers/HomeCtrl.js.coffee
になります。 :
# app/assets/javascripts/angular/controllers/HomeCtrl.js.coffee
@restauranteur.controller 'HomeCtrl', ['$scope', ($scope) ->
# Notice how this controller body is empty
]
次に、HomeCtrl
を作成するために、ルーティングディレクティブを追加します。 「デフォルトページ」になります。ここでは、app/assets/javascripts/main.js.coffee
でルーティングを定義しています。 、しかし、ファイル名は重要ではないと思います。
# app/assets/javascripts/main.js.coffee
# This line is related to our Angular app, not to our
# HomeCtrl specifically. This is basically how we tell
# Angular about the existence of our application.
@restauranteur = angular.module('restauranteur', [])
# This routing directive tells Angular about the default
# route for our application. The term "otherwise" here
# might seem somewhat awkward, but it will make more
# sense as we add more routes to our application.
@restauranteur.config(['$routeProvider', ($routeProvider) ->
$routeProvider.
otherwise({
templateUrl: '../templates/home.html',
controller: 'HomeCtrl'
})
])
また、Angularテンプレートを保持する場所も必要です。 public/templates
に入れることにしました 。繰り返しになりますが、好きな場所に配置できます。
mkdir public/templates
ファイルを作成する場合public/templates/home.html
任意のコンテンツがあれば、ブラウザで表示できるはずです。
This is the home page.
ここで、https://restauranteur.dev/
にアクセスすると (またはhttps://localhost:3000/
Powを使用していない場合)、home.html
の内容が表示されます。 。
それは種類です 興味深いですが、おそらくあまり印象的ではありません。実際にネットワークを介して何かを送信してみましょう。 app/assets/angular/controllers/HomeCtrl.js.coffee
を編集します このように:
# app/assets/angular/controllers/HomeCtrl.js.coffee
@restauranteur.controller 'HomeCtrl', ['$scope', ($scope) ->
$scope.foo = 'bar'
]
これは、@foo = "bar"
と言うのと似ています。 Railsコントローラーで。 foo
をプラグインできます 次のような二重中括弧構文を使用して、テンプレートに追加します。
Value of "foo": {{foo}}
簡単なHelloWorldアプリを既に作成しました。本格的なCRUDアプリケーションの作成はそれほど難しくありません。
データベース内のいくつかのレストランから始めると、レストランCRUDでの作業はもう少し意味があります。使用できるシードファイルは次のとおりです。
# db/seeds.rb
Restaurant.create([
{ name: "The French Laundry" },
{ name: "Chez Panisse" },
{ name: "Bouchon" },
{ name: "Noma" },
{ name: "Taco Bell" },
])
rake db:seed
まず、レストランのテンプレートフォルダを作成しましょう:
mkdir public/templates/restaurants
作成する最初のテンプレートはインデックスページです:
[index](/#)
* {{ restaurant.name }}
これらの意味については、すぐに説明します。まず、コントローラーを作成しましょう:
# app/assets/javascripts/angular/controllers/RestaurantIndexCtrl.js.coffee
@restauranteur.controller 'RestaurantIndexCtrl', ['$scope', '$location', '$http', ($scope, $location, $http) ->
$scope.restaurants = []
$http.get('./restaurants.json').success((data) ->
$scope.restaurants = data
)
]
最後に、ルーティング構成を調整します:
# app/assets/javascripts/main.js.coffee
@restauranteur = angular.module('restauranteur', [])
@restauranteur.config(['$routeProvider', ($routeProvider) ->
$routeProvider.
when('/restaurants', {
templateUrl: '../templates/restaurants/index.html',
controller: 'RestaurantIndexCtrl'
}).
otherwise({
templateUrl: '../templates/home.html',
controller: 'HomeCtrl'
})
])
これで、最後に、URI /#/restaurants
に移動できます。 そして、レストランのリストを見ることができるはずです。先に進む前に、テストを追加しましょう。
JSテストフォルダーを追加します:
mkdir spec/javascripts
テストを書く:
# spec/javascripts/controllers_spec.js.coffee
describe "Restauranteur controllers", ->
beforeEach module("restauranteur")
describe "RestaurantIndexCtrl", ->
it "should set restaurants to an empty array", inject(($controller) ->
scope = {}
ctrl = $controller("RestaurantIndexCtrl",
$scope: scope
)
expect(scope.restaurants.length).toBe 0
)
構成の追加:
// spec/javascripts/restauranteur.conf.js
module.exports = function(config) {
config.set({
basePath: '../..',
frameworks: ['jasmine'],
autoWatch: true,
preprocessors: {
'**/*.coffee': 'coffee'
},
files: [
'app/assets/javascripts/angular.js',
'app/assets/javascripts/angular-mocks.js',
'app/assets/javascripts/main.js.coffee',
'app/assets/javascripts/angular/controllers/RestaurantIndexCtrl.js.coffee',
'app/assets/javascripts/angular/*',
'spec/javascripts/*_spec.js.coffee'
]
});
};
Karmaをインストールし、サーバーを起動します:
sudo npm install -g karma
sudo npm install -g karma-ng-scenario
karma start spec/javascripts/restauranteur.conf.js
https://localhost:9876/
にアクセスした場合 、テストが実行され、成功します。テストが失敗することを確認したい場合は、expect(scope.restaurants.length).toBe 0
を変更してください。 to expect(scope.restaurants.length).toBe 1
もう一度テストを実行します。
追加したこのテストの意味は明らかに疑わしいですが、ここでの私の意図は、Angularコードをテストハーネスに取り込む方法を理解する手間を省くことです。 CoffeeScriptプリプロセッサやangular-mocks.js
などの特定のものがあります 完全に明白ではなく、正しく理解するために頭を悩ませるのに数時間かかった包含。
次に、レストランのインデックステンプレートを一時的に調整しましょう:
* {{restaurant.name}} ({{restaurant.id}})
ここで/#/restaurants
に再度アクセスした場合 、どのレストランにもIDがないことに気付くでしょう。なぜ空白なのですか?
Rails 4でスキャフォールディングを生成すると、.jbuilder
が得られます。 ファイル:
$ ls -1 app/views/restaurants/*.jbuilder
app/views/restaurants/index.json.jbuilder
app/views/restaurants/show.json.jbuilder
app/views/restaurants/index.json.jbuilder
を開いた場合 、これが表示されます:
# app/views/restaurants/index.json.jbuilder
json.array!(@restaurants) do |restaurant|
json.extract! restaurant, :name
json.url restaurant_url(restaurant, format: :json)
end
ご覧のとおり、:name
が含まれています ただし、:id
ではありません 。追加しましょう:
# app/views/restaurants/index.json.jbuilder
json.array!(@restaurants) do |restaurant|
json.extract! restaurant, :id, :name
json.url restaurant_url(restaurant, format: :json)
end
ファイルを保存して/#/restaurants
を更新した場合 、IDが表示されるはずです。
次に、テンプレートを元の状態に戻します。
[index](/#)
* {{ restaurant.name }}
ある時点で、これらをviewRestaurant()
と呼ばれるものに向けていることに気付いたかもしれません。 しかし、実際にはviewRestaurant()
と呼ばれるものを定義したことはありません。 。今すぐやってみましょう:
# app/assets/javascripts/angular/controllers/RestaurantIndexCtrl.js.coffee
@restauranteur.controller 'RestaurantIndexCtrl', ['$scope', '$location', '$http', ($scope, $location, $http) ->
$scope.restaurants = []
$http.get('./restaurants.json').success((data) ->
$scope.restaurants = data
)
# Add the following lines
$scope.viewRestaurant = (id) ->
$location.url "/restaurants/#{id}"
]
Railsの規則では、resource_name/:id
「表示」ページにマップします。これをここで行います。ショーテンプレート、ルート、コントローラーを作成しましょう。
# {{restaurant.name}}
# app/assets/javascripts/main.js.coffee
@restauranteur = angular.module('restauranteur', [])
@restauranteur.config(['$routeProvider', ($routeProvider) ->
$routeProvider.
when('/restaurants', {
templateUrl: '../templates/restaurants/index.html',
controller: 'RestaurantIndexCtrl'
}).
when('/restaurants/:id', {
templateUrl: '../templates/restaurants/show.html',
controller: 'RestaurantShowCtrl'
}).
otherwise({
templateUrl: '../templates/home.html',
controller: 'HomeCtrl'
})
])
# app/assets/javascripts/angular/controllers/RestaurantShowCtrl.js.coffee
@restauranteur.controller 'RestaurantShowCtrl', ['$scope', '$http', '$routeParams', ($scope, $http, $routeParams) ->
$http.get("./restaurants/#{$routeParams.id}.json").success((data) ->
$scope.restaurant = data
)
]
ここで、/#/restaurants
を更新すると レストランをクリックすると、そのレストランのショーページが表示されます。イェーイ!
特に印象的な結果は見られなかったかもしれませんが、AngularJSをRails 4に接続する時間を節約できたと思います。次に、CRUD機能をよりドライにするのに役立つintongResourceを調べることをお勧めします。
詳細を学ぶことに興味がありますか?
Rails4.0シリーズでAngularJSアプリをブートストラップすることでAngularJSとRailsを使い始めることができたAdamAndersonのすばらしい投稿をチェックしてください。彼のチュートリアルも試してみたいと思うかもしれませんが、このチュートリアルは、雑草に巻き込まれる可能性を最小限に抑えて、すべての詳細を_really_spoon-feedしようとしているという意味で異なります。
-
ウェブ用の Android メッセージの使用を開始する
Google は 1 つの巨大なプラットフォームであり、疑いの余地はありません。しかし、最高の検索エンジンの 1 つであるだけでなく、日常生活を楽にするさまざまなサービスも提供しています。 Google は最近、どの Web ブラウザからでもテキスト メッセージを送受信できる Android メッセージ アプリのアップデートをリリースしました。このサービスを使用すると、Android ユーザーは任意の PC または Mac に簡単にメッセージを送信できます。 開始するには、Android メッセージ アプリの更新バージョンが必要です。それが終わったら、Web サービスで Android メッ
-
Xen 仮想化の開始
Zで綴られるZenは、8時間保持した後、雪の中でおしっこをしているときに頭頂部にある典型的な感覚です. Xen は X で綴られており、KVM と同様に、企業市場を対象としていますが、家庭でもビジネスでもセットアップを検討できるオープンソースの仮想化テクノロジです。 KVM に関するいくつかのチュートリアルがあり、導入記事、ストレージとネットワーク (ブリッジ ネットワークを含む) のセットアップと構成の方法、および VirtualBox との競合の解決方法をカバーしています。ここで、Xen についてもう少し学びましょう。同様に、仮想マシンをインストールして実行するために必要な最初の手順、