voltrb / volt

A Ruby web framework where your Ruby runs on both server and client
MIT License
3.22k stars 196 forks source link

Following todos tutorial update does not work #344

Open marcomd opened 8 years ago

marcomd commented 8 years ago

Hello,

I'm trying this new framework using the tutorial that shows how to create the first application Todos.

http://docs.voltframework.com/en/tutorial/todo_functionality.html

When I update a record (for example, clicking on the checkbox to complete a Todo) appears in the log:

[ERROR] task StoreTasks#save in 3.0ms
with args: "todos", ["todos", "[]"], {"name"=>"First", "completed"=>true, "id"=> "61dcdaba1249e010892ec1ce"}

{:error=>"E11000 duplicate key error collection: Todo_development.todos index: _id_ dup key: { : \"61dcdaba1249e010892ec1ce\" } (11000)"}
127.0.0.1 - - [14/Jan/2016 15:25:53] "GET /todos?index=0 HTTP/1.1" 200 - 0.6171

In the db there are:

> db.todos.find()
{ "_id" : "61dcdaba1249e010892ec1ce", "name" : "First" }
{ "_id" : "092ad7f1f6bc44980069a401", "name" : "Second" }

Is this a bug? The tutorial is obsolete? Or is it my mistake?

afaur commented 8 years ago

Hello @marcomd Sorry to hear that your having trouble with the todo example. I personally had not followed the tutorial however in an effort to try and help with your issue I found the github repo and cloned the project locally..

-> % git clone git@github.com:voltrb/todomvc.git
Cloning into 'todomvc'...
remote: Counting objects: 84, done.
remote: Total 84 (delta 0), reused 0 (delta 0), pack-reused 84
Receiving objects: 100% (84/84), 16.57 KiB | 0 bytes/s, done.
Resolving deltas: 100% (14/14), done.
Checking connectivity... done.

-> % rvm list

rvm rubies

   ruby-1.9.3-p551 [ x86_64 ]
=* ruby-2.1.5 [ x86_64 ]
   ruby-2.2.1 [ x86_64 ]

# => - current
# =* - current && default
#  * - default

-> % bundle install
Fetching gem metadata from https://rubygems.org/.........
Fetching additional metadata from https://rubygems.org/..
Installing bcrypt 3.1.10
Installing bson 1.9.2
Installing bson_ext 1.9.2
Installing mime-types 2.6.1
Using mini_portile 0.6.2
Using nokogiri 1.6.6.2
Installing rack 1.5.3
Using rack-test 0.6.3
Installing xpath 2.0.0
Installing capybara 2.4.4
Installing hitimes 1.2.2
Installing timers 4.0.1
Installing celluloid 0.16.0
Installing ffi 1.9.8
Installing childprocess 0.5.6
Installing chromedriver2-helper 0.0.8
Installing cliver 0.3.2
Using coderay 1.1.0
Installing ref 1.0.5
Installing concurrent-ruby 0.8.0
Installing concurrent-ruby-ext 0.8.0
Installing configurations 2.0.0
Installing execjs 2.5.2
Installing csso-rails 0.3.4
Installing daemons 1.2.2
Using diff-lcs 1.2.5
Installing eventmachine 1.0.7
Installing websocket-extensions 0.1.2
Installing websocket-driver 0.5.4
Installing faye-websocket 0.9.2
Using hike 1.2.3
Using json 1.8.3
Installing rb-fsevent 0.9.5
Using rb-inotify 0.9.5
Installing listen 2.8.6
Using method_source 0.8.2
Installing mongo 1.9.2
Using multi_json 1.11.0
Installing sourcemap 0.1.1
Using tilt 1.4.1
Using sprockets 2.12.3
Installing opal 0.7.2
Installing opal-rspec 0.4.2
Installing poltergeist 1.5.1
Using slop 3.6.0
Using pry 0.10.1
Installing rbnacl 3.2.0
Installing rbnacl-libsodium 1.0.3
Using rspec-support 3.2.2
Using rspec-core 3.2.3
Using rspec-expectations 3.2.1
Using rspec-mocks 3.2.1
Using rspec 3.2.0
Installing rubyzip 1.1.7
Installing sass 3.2.19
Installing websocket 1.2.2
Installing selenium-webdriver 2.43.0
Installing sprockets-sass 1.0.3
Installing thin 1.6.3
Using thor 0.19.1
Installing uglifier 2.7.1
Using bundler 1.7.6
Installing volt 0.9.3
Installing volt-mongo 0.1.0
Your bundle is complete!
Use `bundle show [gemname]` to see where a bundled gem is installed.

-> % ls
Gemfile      Gemfile.lock README.md    app          config       config.ru    spec

-> % cat README.md 
# Demo Todos App

This app is an example using the [TodoMVC project](http://todomvc.com/)

NOTE: I threw this together in 5 minutes just to say we had a TODOMVC example.

To Run, start mongodb in one terminal:

    mongod

Then run the project:

    bundle install
    bundle exec volt server   

-> % bundle exec volt server
Volt 0.9.3
                             ,--,           ,----, 
                ,----..   ,---.'|         ,/   .`| 
               /   /   \  |   | :       ,`   .'  : 
       ,---.  /   .     : :   : |     ;    ;     / 
      /__./| .   /   ;.  \|   ' :   .'___,/    ,'  
 ,---.;  ; |.   ;   /  ` ;;   ; '   |    :     |   
/___/ \  | |;   |  ; \ ; |'   | |__ ;    |.';  ;   
\   ;  \ ' ||   :  | ; | '|   | :.'|`----'  |  |   
 \   \  \: |.   |  ' ' ' :'   :    ;    '   :  ;   
  ;   \  ' .'   ;  \; /  ||   |  ./     |   |  '   
   \   \   ' \   \  ',  / ;   : ;       '   :  |   
    \   `  ;  ;   :    /  |   ,/        ;   |.'    
     :   \ |   \   \ .'   '---'         '---'      
      '---"     `---`                              

Thin web server (v1.6.3 codename Protein Powder)
Maximum connections set to 500
Listening on 0.0.0.0:3000, CTRL+C to stop
127.0.0.1 - - [16/Jan/2016 16:02:41] "GET / HTTP/1.1" 200 - 0.0034

[INFO] task QueryTasks#add_listener in 8.082ms
with args: "todos", [["find"]]

[INFO] task StoreTasks#save in 23.393ms
with args: "todos", ["todos", "[]"], {"label"=>"test", "id"=>"7dc12c4cce80ebb3f99ab528"}

[INFO] task StoreTasks#save in 4.661ms
with args: "todos", ["todos", "[]"], {"label"=>"test2", "id"=>"735c3dc8acd9ba407eff7f44"}

[INFO] task StoreTasks#save in 6.678ms
with args: "todos", ["todos", "[]"], {"label"=>"test", "id"=>"7dc12c4cce80ebb3f99ab528", "completed"=>true}

Looking closer at the code inside of the main_controller.rb file I noticed that the logic for marking something completed does not look exactly the same as the logic contained in the tutorial making me think that the tutorial is probably just out of date..

-> % cat app/main/controllers/main_controller.rb 
# The MainController is responsible for showing the individual Todos and listing
# things like how many are checked.
module Main
  class MainController < Volt::ModelController
    model :store

    # Use the route to filter which todos we're showing
    def filtered_todos
      query = store.todos
      case params._filter
      when 'completed'
        query = query.where(completed: true)
      when 'active'
        query = query.where({'$or' => [{completed: false}, {completed: nil}]})
      end

      query
    end

    def complete
      todos.count(&:completed)
    end

    def incomplete
      Promise.when(todos.size, complete).then do |size, complete|
        size - complete
      end
    end

    # Remove all completed
    def clear_completed
      todos.all.reverse.select(&:completed).each(&:destroy)
    end

    # Binding for if the all complete checkbox should be checked.
    def all_complete
      # incomplete returns a promise, so we check if its zero inside of a .then
      # block.
      incomplete.then { |val| val == 0 }
    end

    # Called when the complete all checkbox is checked, change the state of all
    # todos to val (true or false)
    def all_complete=(val)
      todos.all.each {|todo| todo._completed = val }
    end

    # Return true if there are any todos
    def any_todos?
      todos.size.then {|s| s > 0 }
    end

    # return true if any todos are complete
    def any_complete?
      complete.then {|c| c > 0 }
    end

    private

    # The main template contains a #template binding that shows another
    # template.  This is the path to that template.  It may change based
    # on the params._component, params._controller, and params._action values.
    def main_path
      "#{params._component || 'main'}/#{params._controller || 'main'}/#{params._action || 'index'}"
    end

    # Determine if the current nav component is the active one by looking
    # at the first part of the url against the href attribute.
    def active_tab?
      url.path.split('/')[1] == attrs.href.split('/')[1]
    end
  end
end

I would probably suggest you clone the repo located at git@github.com:voltrb/todomvc.git and see if you could get it to work by following the readme.

If you have any suggestions for fixing the tutorial please add a new issue to help the maintainers locate the issue that might have made it become out of sync.

marcomd commented 8 years ago

@afaur Hello Adam and thx for the answer. I started a new todo project using that example but i have the same problem. It could also be that this happens only on windows, I'll take a look on a *nix system as soon as i can.

maclarensg commented 8 years ago

Hi,

I've encounter the same issue as well. I'm using Volt 0.9.6, whereas from @afaur answer, where he took a github was on volt 0.9.3. I've tried the github's example, it worked but for my simple code

<:Title>
  Todo

<:Body>
  <h1>{{ _todos.size }} Todo</h1>
  <button e-click="complete_all" class="btn btn-success" >Complete {{ incomplete }} Tasks</button>
  <button e-click="clear_completed" class="btn btn-default" >Clear Completed</button>
  <table class='table'>
      {{ _todos.each do |todo| }}
        <tr>
            <td><input type="checkbox" checked="{{ todo._completed }}" /></td>
            <td class="{{if todo._completed}}complete{{end}}">
                {{ todo._label }}
            </td>
            <td><button e-click="todo.destroy">X</button></td>
        </tr>
      {{end}}
  </table>

  <form e-submit="add_todo" role="form">
    <input value="{{ page._new_todo }}"></input>
  </form>

The following line, does not work <td><input type="checkbox" checked="{{ todo._completed }}" /></td>

koffeinfrei commented 7 years ago

I created a fix for this: https://github.com/koffeinfrei/volt-mongo/commit/1fa06cb32c6063164385e823188552cba5ec3652. This probably broke in newer mongo versions.

You can try to use gem 'volt-mongo', github: 'koffeinfrei/volt-mongo'