Как написать сухой, модульный coffeescript со звездочками в 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 15

3 ответа:

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

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

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

Amazing доступен как

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 as-is и сделать заявку.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 вокруг модулей может быть хорошей альтернативой в зависимости от ваших потребностей.