Как вы пишете СУХОЙ, модульный coffeescript с помощью Sprockets в Rails 3.1?

Я нахожусь на ранних стадиях попыток написать какой-нибудь разумный Javascript. Я хочу, чтобы в основном все пространство имен содержалось под именем моего приложения, чтобы максимально избежать глобальных переменных, но все же дать мне возможность доступа к функциям, объявленным повсеместно. Однако я не хочу быть супер многословным в своих определениях функций.

Мой идеальный CoffeeScript был бы примерно таким:

class @MyApp
  @myClassMethod = ->
    console.log 'This is MyApp.myClassMethod()'

  class @Module1
    @moduleMethod = ->
      console.log 'This is MyApp.Module1.moduleMethod()'

Вы получаете картину. Таким образом, я избегаю писать MyApp.Module.submoduleMethod = -> каждый раз, когда я хочу правильно определить функцию пространства имен - используя @ и определение вещей в пределах моего определения класса делает вещи красивыми и короткими.

Все идет хорошо, пока я не хочу разделить свою функциональность на несколько файлов CoffeeScript. Тогда я действительно хочу что-то вроде этого:

// application.js
class @MyApp
  //= require 'module1'
  //= require 'module2'

// module1.js
class @Module1
  @moduleMethod = ->
    console.log 'This is STILL MyApp.Module1.moduleMethod()'

Не похоже, что Звездочки могут сделать это.

Есть ли разумный способ требовать, чтобы мои файлы CoffeeScript находились в нужном месте в моих файлах-контейнерах? Или другой подход к написанию модульного кода, который разделен на отдельные файлы с использованием CoffeeScript, Sprockets и Rails 3.1?

3 ответа

Решение

У меня есть модульное решение, которое я использую в своем коде.

Я определяю свои модули, как показано ниже

@module "foo", ->
    @module "bar", ->
        class @Amazing
            toString: "ain't it"

Удивительно доступно как

foo.bar.Amazing

реализация помощника @module

window.module = (name, fn)->
  if not @[name]?
    this[name] = {}
  if not @[name].module?
    @[name].module = window.module
  fn.apply(this[name], [])

Это написано на веб-сайте coffeescript здесь.

https://github.com/jashkenas/coffee-script/wiki/Easy-modules-with-coffeescript

Просто сохраните module1.js как есть и заставьте application.js выглядеть примерно так:

//= require 'module1'

class @MyApp
  ...

  @Module1 = Module1

Это будет работать, потому что вы сделали Module1 глобальный (декларирующий class @Module1 эквивалентно письму @Module1 = class Module1, а также @ указывает на window в этом контексте) и в рамках class @MyApp тело, @ указывает на сам класс.

Если ты хочешь Module1 быть только собственностью глобального MyApp класс после того, как он прикреплен, вы можете добавить строку

delete window.Module1

Вот модульный шаблон, который я использую для управления coffeescript с помощью звездочек (также работает с Rails 4):

  # utils.js.coffee

  class Utils
    constructor: ->

    foo: ->
      alert('bar!!!')

    # private methods should be prefixed with an underscore
    _privateFoo: ->
      alert('private methods should not be exposed')

  instance = new Utils()

  # only expose the methods you need to.
  # because this is outside of the class,
  # you can use coffee's sugar to define on window

  @utils = foo: instance.foo

  # otherscript.js.coffee 

  //= require utils
  class OtherScript
    constructor: ->
      @utils.foo()         # alerts bar!!!
      @utils._privateFoo() # undefined method error

Одним из недостатков этого подхода является то, что вы выставляете свои объекты на окне. Добавление загрузчика модулей или принятие нового синтаксиса es вокруг модулей может быть хорошей альтернативой в зависимости от ваших потребностей.

Другие вопросы по тегам