15

Jestem na wczesnym etapie próbowania napisania sensownego kodu Javascript. Chcę przestrzeni nazw w zasadzie wszystko pod nazwą mojej aplikacji, aby jak najbardziej unikać globali, ale nadal mam sposób na dostęp do funkcji zadeklarowanych wokół tego miejsca. Jednak nie chcę być super verbose w moich definicjach funkcji.Jak piszesz DRY, modularny coffeescript ze Sprockets w Rails 3.1?

Mój ideał coffeescript byłoby coś takiego:

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

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

uzyskać obraz. W ten sposób unikam konieczności pisania MyApp.Module.submoduleMethod = -> za każdym razem, gdy chcę poprawnie zdefiniować funkcję z wyświetlaniem nazw - używając @ i definiując rzeczy w ramach definicji klasy utrzymuję rzeczy ładne i krótkie.

Wszystko idzie dobrze, dopóki nie chcę podzielić mojej funkcjonalności na wiele plików CoffeeScript. To, czego naprawdę chcę, to coś takiego:

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

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

Nie wygląda na to, że Sprockets mogą to zrobić.

Czy istnieje rozsądny sposób na wymaganie moich plików CoffeeScript we właściwym miejscu w moich plikach kontenera? Lub inny sposób podejścia do pisania kodu modułowego, który jest podzielony na osobne pliki za pomocą CoffeeScript, Sprockets i Rails 3.1?

+1

Myślę, że to pytanie wymaga dalszych badań - poniższe odpowiedzi nie są wystarczająco dobre, szczególnie. odkąd twórca coffeescript usunął stronę "łatwych modułów" b/c technika jest słaba. – dmonopoly

Odpowiedz

3

mam rozwiązanie modułu, którego używam w moim kodu.

zdefiniować swoje moduły jak poniżej

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

Niesamowite jest dostępny jako

foo.bar.Amazing 

realizacja pomocnika @module jest

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

Jest napisany się na stronie internetowej coffeescript tutaj .

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

+1

Dzięki za link. Każdy pomysł, jak to rozszerzyć, aby działał ładnie w wielu plikach? – nfm

+0

Działa na wielu plikach. To jest najważniejsze. Co masz na myśli mówiąc ładnie? – bradgonesurfing

+0

Mam na myśli bez konieczności definiowania wszystkich modułów nadrzędnych w każdym pliku. To może być mniej irytujące, niż początkowo sądziłem. – nfm

4

Wystarczy zachować module1.js jak jest i uczynić application.js wyglądać następująco:

//= require 'module1' 

class @MyApp 
    ... 

    @Module1 = Module1 

to będzie działać, ponieważ po dokonaniu Module1 globalnym (deklarując class @Module1 jest równoważne formie pisemnej @Module1 = class Module1 i @ punktów do window w tym kontekście), a wewnątrz ciała , @ wskazuje na samą klasę.

Jeśli chcesz Module1 do tylko być właściwością globalnej MyApp klasy po jej załączeniu, można dodać linię

delete window.Module1 
+0

Dobry pomysł! Wciąż byłby problem, gdyby nazwy moich modułów zderzyły się z nazwami w innych skryptach na stronie, prawda? Jestem wybredny, ponieważ piszę kod, który prawdopodobnie zostanie wprowadzony na inne strony za pomocą skryptozakładki. – nfm

+0

Ah, w takim przypadku zdefiniowałbym jedną globalną, a następnie dołączę do niej wszystko inne. Aby to zrobić, odwróć kolejność zależności: w application.js, wymagaj 'module1.js', aw' module1.js', wymagaj 'myapp.js', aby globalny' MyApp' był zdefiniowany jako pierwszy. Możesz wtedy napisać 'class MyApp.Module' ... –

+0

Moja powyższa odpowiedź rozwiązuje problem kolizji nazwy. Używanie klasy jest fajne, ale nie jest tak jak w rubinach, gdzie można łatać małpy. Usunie wszelkie wcześniej zdefiniowane klasy. http://stackoverflow.com/questions/6815957/how-do-you-write-dry-modular-coffeescript-with-sprockets-in-rails-3-1/6826293#6826293 omija to – bradgonesurfing

1

Oto modułowy wzorzec używać do zarządzania coffeescript z zębatkami (współpracuje z Rails 4 a):

# 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 

Jeden disadavantage tego podejścia jest to, że naraża swoje obiekty w oknie . Dodanie modułu ładującego moduły lub przyjęcie nowej składni es wokół modułów może być fajną alternatywą w zależności od Twoich potrzeb.