LoginSignup
8
8

Rails, CoffeeScript - classでラップしてネームスペース管理

Last updated at Posted at 2015-08-19

経緯

  • グローバルで変数名が衝突しないよう、ネームスペース・モジュール管理をやるべきらしい。
  • JSは多用しないので、可能であればRailsサイドで解決したい。
  • 今後は意識して実践していきたいのでメモ。

手法

調べてみるといろんな手法があったが、この方法が気に入った。

ネームスペース用のディレクトリーを作る(幾つでも良い)

/javascripts
    /namespace    # ネームスペース用のディレクトリー
        base.coffee
        charts.coffee
        moving_items.coffee
        [..]
    application.js
    namespace.js  # ネームスペース設定ファイル

ネームスペースをアセットパイプラインに読み込んでもらう

/app/assets/javascripts/application.js
//= require jquery
//= require jquery_ujs
//= require jquery.turbolinks
//= require bootstrap
//= require turbolinks
//...
//= require namespace
/app/assets/javascripts/namespace.js
//= require ./namespace/base
//= require_tree ./namespace

baseファイルにネームスペース用オブジェクトを準備

/app/assets/javascripts/namespace/base.coffee
@Namespace = {}

# $(document).on "ready page:load", ->
#  $('a[href^="/documents/"]').attr('target', '_blank')

JSコードをネームスペース配下のクラスでラップする

クラス内のコードはインスタンス化されるまで待機することになる

###constructorで何かを戻り値として返す例

/app/assets/javascripts/namespace/charts.coffee
# Chart.js configuration

Chart.defaults.global.tooltipEvents = ["mousemove", "touchstart", "touchmove"]
Chart.defaults.global.scaleLabel    = "<%=value%>cu.ft"

class @Components.ChartComponent

  constructor: (chartType)->
    return @createClass(chartType)

  createClass: (chartType) ->

    React.createClass
      displayName: "#{chartType}Chart"
      propTypes:
        name:    React.PropTypes.string
        data:    React.PropTypes.oneOfType([React.PropTypes.array, React.PropTypes.object])
        height:  React.PropTypes.number
        width:   React.PropTypes.number
        options: React.PropTypes.object

      getInitialState: ->
        chartInstance: null

      render: ->
        React.DOM.canvas
          ref:   @props.name
          style: { height: @props.height, width: @props.width }

      componentDidMount: ->
        @initializeChart()

      componentWillUnmount: ->
        @state.chartInstance.destroy() if @state.chartInstance

      initializeChart: ->
        canvas = React.findDOMNode(@refs[@props.name])
        ctx    = canvas.getContext("2d")
        chart  = new Chart(ctx)[chartType](@props.data)
        @setState.chartInstance = chart

###constructorでイベントリスナーを登録する例

/app/assets/javascripts/namespace/moving_items.coffee
# moving_items/new, moving_items/edit

class @Namespace.MovingItems

  constructor: ->

    setVolume = (volume) -> $("#moving_item_volume").val(volume)
    setSlider = (volume) -> $("#volume_slider").val(volume)

    # Slider

    document.getElementById('volume_slider').addEventListener 'change', ->
      setVolume(document.getElementById('volume_slider').value)

    # AutoComplete

    $('#moving_item_name').autocomplete
      source: Object.keys( $('#suggestions').data('items') )
      select: (e, ui) =>
        itemVolume = $('#suggestions').data('items')[ui.item.value]
        setVolume(itemVolume)
        setSlider(itemVolume)

    $('#moving_item_room').autocomplete
      source: $('#suggestions').data('rooms')

    $('#moving_item_category').autocomplete
      source: $('#suggestions').data('categories')

HAMLの:coffeeフィルターを利用しJSコードを呼び出しインスタンス化

/app/views/movings/_chart_panel.html.haml
:coffee
  window.BarChartComponent = new Namespace.ChartComponent("Bar")
  window.PieChartComponent = new Namespace.ChartComponent("Pie")

.panel.panel-blue
  .panel-heading
    /...
  - if @total_volume > 0
    .panel-body
      .row
        .col-sm-6
          = react_component 'BarChartComponent', { name: "MovingBarChart",
            data: @dataForBarChart, height: 200, width:  400 }
        .col-sm-6
          = react_component 'PieChartComponent', { name: "MovingPieChart",
            data: @dataForPieChart, height: 200, width:  200 }

同様のことが、content_for(:javascript)= yield(:javascript)でも可能。

/app/views/layouts/application.html.haml
!!!
%html
  %head
    /...
  %body
    = yield               # ページコンテンツ
    /...
    = yield(:javascript)  # 必要なJSコードを生成する
/app/views/movings/_chart_panel.html.haml
- content_for(:javascript) do
  :coffeescript
    jQuery ->
      window.BarChartComponent = new Namespace.ChartComponent("Bar")
      window.PieChartComponent = new Namespace.ChartComponent("Pie")
/...

資料

8
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
8