Rails assets pipeline

2013-10-08T00:00:00+00:00 JavaScript Ruby Rails

何やらRailsを使っててJavaScriptとかをgemとかで配布してRailsプロジェクトに組み込んだりするっていうのがあったりするわけで。例えばTwitter BootstrapのCSSとかJSとかをGemfileにそういうgemを定義する事でサクッと出来るっつー訳。でその仕組み的なのがRails assets pipelineっていうのかなと、これCoffeeScriptとかならコンパイルして使えるようにする事も出来るらしいとの事(今回はやらないけど)

とりあえずこの仕組みを使ってangular.jsなプロジェクトを別にしてRailsプロジェクトに組み込むっていう事をしてみる

angular.jsなプロジェクトを作る

bundle gem sample-ui-rails

的な感じでプロジェクトを作る。やると何やらsample-ui-rails.gemspecなりが作られる訳で。でlib/sample/ui/rails.rbがあるので

require "sample/ui/rails/version"

module Sample
  module Ui
    module Rails
      # 追加
      class Engine < ::Rails::Engine
      end
    end
  end
end

的な感じでちょいと修正しておく。でJavaScriptだとかCSSとかを提供したい場合には

  • JavaScript: vendor/assets/javascripts
  • CSS: vendor/assets/stylesheets

におけば良い。という事でangular.jsなコントローラーなJSを書いて上記のルールに沿った方式な所は配置する

var SampleController = function($scope, $http) {
  $http.get("/sample/index")
    .success(function(data) {
      $scope.samples = data;
    });
};

んまぁテストも書きましょうかって事でkarma initでkarma.conf.jsを作る

// Karma configuration
// Generated on Tue Oct 08 2013 05:21:20 GMT+0900 (JST)

module.exports = function(config) {
  config.set({

    // base path, that will be used to resolve files and exclude
    basePath: "",


    // frameworks to use
    frameworks: ["jasmine", "ng-scenario"],


    // list of files / patterns to load in the browser
    files: [
      "tests/angular-mocks.js", // angular.js mock library
      "vendor/assets/javascripts/*.js", // source
      "tests/*_spec.js" // tests
    ],


    // list of files to exclude
    exclude: [
    ],


    // test results reporter to use
    // possible values: "dots", "progress", "junit", "growl", "coverage"
    reporters: ["progress"],


    // web server port
    port: 9876,


    // enable / disable colors in the output (reporters and logs)
    colors: true,


    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,


    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,


    // Start these browsers, currently available:
    // - Chrome
    // - ChromeCanary
    // - Firefox
    // - Opera
    // - Safari (only Mac)
    // - PhantomJS
    // - IE (only Windows)
    browsers: ["Chrome"],


    // If browser does not capture in given timeout [ms], kill it
    captureTimeout: 60000,


    // Continuous Integration mode
    // if true, it capture browsers, run tests and exit
    singleRun: false
  });
};

angular-mocks.jsはangular.js公式なやつに入ってるのでコピペして持ってくる。んでテスト書く

describe("SampleController", function() {

  var $_httpBackend, scope, controller;

  beforeEach(function() {
    inject(function($controller, $rootScope, $httpBackend) {
      $_httpBackend = $httpBackend;
      $_httpBackend.when("GET", "/sample/index").respond([{},{}]);

      scope = $rootScope.$new();

      // こうしないと$_httpBackend.flushをやると、「No pending request to flush」的なエラーが出る
      scope.$apply(function() {
        controller = $controller("SampleController", { $scope: scope });
      });
    });
  });

  it("#construcor", function() {
    expect(scope.samples).toBeUndefined();
    $_httpBackend.flush();
    expect(scope.samples).not.toBeUndefined();

    // 上記で/sample/indexにリクエストした結果としてはArray.size == 2なのでこれはfailする
    expect(scope.samples.length).toEqual(1);
  });
});

karma startなりで起動してテスト実行。あとはこのプロジェクトをRailsプロジェクトで参照してコピペとかする事無く利用できるようにと

Railsプロジェクトを作る

rails new sample

で、Gemfileにangularjs-railsと上記で作ったプロジェクトの参照を追加する

gem "angularjs-rails"
gem "sample-ui-rails", :path => "/path/to/sample-ui-rails-project"

でこれだけじゃスクリプトとか参照してくれないので、app/assets/javascripts/application.jsに追加する

//= require jquery
//= require jquery_ujs
//= require_tree .

// 以降追加
//= require angular
//= require sample

あとはビューとかで

html<div ng-controller="SampleController"> <ul> <li ng-repeat="sample in samples"> <span ng-bind-template="{% raw %}{{sample.name}}{% endraw %}"></span> </li> </ul> </div>

的な事やってみて確認。書いてないけどコントローラーではrespond_toとかで(ry

<canvas>でチャートを出力する Struts2をやってみる (16) - ModelDriven -