towerjs

Towerjs model finders - variable scopes


I want do query on model, and next depend on resaults do someting else

The problem:

  exists = false
  App.User.where(email: "example@domain.com").exists (error, exists) =>      
    console.log exists #=> true
  console.log exists #=> false

Example why I want this:

class App.User extends Tower.Model
  newUser: ->
    exists = false
    App.User.where(email: "some@email.com").exists (error, exists) =>   

    unless exists                 # here is always: exists = false
      @.create
        email: "some@email.com"   # so user is created

I also tried something like this:

class App.User extends Tower.Model
  newUser: ->
    @.where(email: "some@email.com").exists (error, exists) =>
      unless exists                         # statement works 
        @.create                            # but I can't create an user
          email: "some@email.com"  

        App.User.create                     # also doesn't work
          email: "some@email.com"  

        user = new App.User                 # this also fails
        user.set "email", "some@email.com"
        user.save()

Solution

  • Queries to the database are asynchronous, which means any code you need to run after the data comes back have to be inside the callback. So in your first example, that unless exists is actually going to run before the database query completes. I think if you indent it and the code that comes after it by two spaces, that will place it inside the callback and it will run as intended. Try:

    class App.User extends Tower.Model
      newUser: ->
        exists = false
        App.User.where(email: "some@email.com").exists (error, exists) =>   
    
          unless exists                 
            @.create
              email: "some@email.com"
    

    If the uniqueness validation was working correctly, you could get the same result more easily by just placing a uniqueness validation on your model. So in your model you would have something like:

    class App.User extends Tower.Model
      @field "email", type: "String"
      @field "firstName", type: "String"
      @field "lastName", type: "String"
    
      @hasMany "posts"
    
      @validates 'email', uniqueness: true
    
      @timestamps()
    

    Unfortunately, based on some recent experiments, there's a small bug in uniqueness causing it to fail. I posted the bug on tower's issues list and I'm also looking into it myself, so hopefully it will be working properly soon.

    Hope this helps.

    Edit: Thought I would mention, I'm not entirely sure why the second example fails, since it looks a lot like my suggestion, unless either I'm wrong or the context (the value of @) is changing because of using @ in the database query instead of App.User.