Method Call Syntax in CoffeeScript

13,120

Solution 1

Your method calling syntax is correct. The relevant rules for CoffeeScript are:

  • Parenthesis are optional for method calls invoked with arguments ie

    object.method 1,2 
    

    or

    object.method(1,2)
    
  • Parenthesis are required for method calls invoked with no arguments ie

    object.method()
    

To see how this works try running the following code on the 'Try CoffeeScript' editor on the CoffeeScript site:

class A
  method: ->
    console.log "A"

(new A()).method();

Since your method call syntax is correct it seems likely that the problem is that the @card variable is not an instance of the exports.Card class.

Solution 2

The problem is that pip isn't a property of the Card instance; it's a property of Card::defaults, so Backbone then makes it an attribute of the Card instance—not a property. You can access the pip attribute with

card.get 'pip'

or directly as

card.attributes.pip

The reason for this distinction is that, in JavaScript, there's no way to monitor a property for changes, which Backbone needs to do in order to dispatch events. (If you modify pip with card.set 'pip', then Backbone fires a "change" event, for instance.)

So, your code should work fine if you just change the last line of the rows method:

rows: ->
  rows =
    '4': [2, 0, 2]
  rows[@get 'pip']

(Note: Getters/setters are supported in some JS environments, which would allow you to map card.pip = ... to card.set 'pip', ... See John Resig's article on it here. Backbone doesn't use this approach because it aims to be compatible with all modern-ish browsers.)

Share:
13,120
mportiz08
Author by

mportiz08

Updated on June 12, 2022

Comments

  • mportiz08
    mportiz08 almost 2 years

    I'm new to CoffeeScript, and I seem to be having trouble with the syntax for calling methods.

    Here's the Card model:

    class exports.Card extends Backbone.Model
      defaults:
        pip:   '4'
        suit:  '♠'
        color: 'b'
    
      rows: ->
        rows =
          '4': [2, 0, 2]
        rows[@pip]
    

    And the relevant portion of the template:

    <ul class="col cols-<%= @card.rows()[0] %>">
    

    which is giving me the error Uncaught TypeError: Object #<Object> has no method 'rows'

    Specifically, I'm wondering if I'm using incorrect syntax for the rows method of Card or if I'm just misunderstanding something. Thanks in advance!

    Update:

    For some reason, @card.property always works fine, but @card.any_method() never does. I've gotten around this at the moment by using properties, but I'd love it if someone was able to explain this behavior. Thanks again!

    Update 2:

    I'm using http://brunchwithcoffee.com if it's a help to anyone, and here's the main.coffee file to show how the @card instance is being created and passed to the view.

    window.app = {}
    app.routers = {}
    app.models = {}
    app.collections = {}
    app.views = {}
    
    Card = require('models/card_model').Card
    MainRouter = require('routers/main_router').MainRouter
    HomeView = require('views/home_view').HomeView
    CardView = require('views/card_view').CardView
    
    # app bootstrapping on document ready
    $(document).ready ->
      app.initialize = ->
        app.routers.main = new MainRouter()
        app.views.home = new HomeView()
        app.views.card = new CardView(model: new Card(color: 'r', suit: '♥', pip: '7'))
        app.routers.main.navigate 'home', true if Backbone.history.getFragment() is ''
      app.initialize()
      Backbone.history.start()
    
  • mportiz08
    mportiz08 over 12 years
    hm, i'm really confused then--@card is definitely an instance of the Card class, as I'm able to safely to <%= @card.pip %> one of the previous lines in the view
  • mportiz08
    mportiz08 over 12 years
    thanks for the clarification on properties versus attributes, but i'm still getting the 'has no method' error when calling any method on @card
  • mportiz08
    mportiz08 over 12 years
    you were right--@card was actually the toJSON() equivalent of what I was thinking it was