Build a reactive multi-user spreadsheet web app with ActionCable and RethinkDB
This will allow us to grab that stream from the NoBrainer streams gem that we were just looking at in GitHub, so this is going to allow us to use that to stream stuff across ActionCable, so we'll be able to do that, and we'll paste that into app/channels/active_users_channel.rb. So it appears that the ActionCable stuff here, is basically when you subscribe, when you join, when you open a tab up and you've basically joined the ActionCable connection, you will subscribe. That will say: Let's just create a new user, it doesn't take any data, so this could be changed to use like current user, if you're doing something like Google Spreadsheets where you have accounts and your users are logging in. This is more of the anonymous user, so we're going that approach, and then, this is creating it in the database and then we're using the data to stream from, so this is saying: stream from the user's table for the most part, I'm not sure what include_initial does, but I'm sure we can look it up and
NoBrainer::Streams if we want to find out. I'm going to say that's probably not super important for us at the moment, so let's keep going with the tutorial, but this should set up our stream to RethinkDB automatically, so that's pretty cool. Let's refresh the page here, after I restart my rails server, and refreshing the page should connect to ActionCable, which would start the subscription on the channel, which should create a record in RethinkDB, so if we go to localhost:8080 where the admin console is, we now have one table, and we have 4 MB of disk space used, which is interesting, and so we have a user's table now. I don't know if we can see the records in here, this is probably about five documents, so I don't think that you can actually cd records directly. Maybe there's a way to do that, I'm not entirely sure.
There's about five documents, something like that, I think there's actually one, but this is more for an overview of your database as opposed to like a direct access to view it, so this is possibly saying: About 5 because it's less then 5, and if it's that, then we don't care. Maybe that's how that works, I'm not entirely sure. That did create user table and I'm sure included the record. We can probably also look at our logs and see, here we go at the yellow and the red, we can see that it created the spreadsheets_development in the database, and then the table_create created a user with a shard and a replica and a primary key, and it inserted an id, and yeah. It seems to have worked, and it seems to have created ActionRecord is loaded which we probably don't want, we can remove ActiveRecord.
This automatically created the database, it created the table, it created the record, which is all steps that you would have to do yourself with ActiveRecord because you have to create your database, you have to run your migrations, create the table, you have to do all that all yourself before you can insert a record, so this does it automatically. It's kind of one of the niceties of NoSQL or that style of database, because it's a lot more free flowing, which is nice. But there's not actually structure, so you can't count on every record being the same, because you could add in some extra fields in there, and if you don't write your code flexibly to be able to detect and use those, then your code is not going to get really any benefits from using NoSQL, because you really just wrote structured data in NoSQL, and it would probably be better in relational database.
Anyways, let's continue on with application and check this out.
subscribed lifecycle callback creates a new user,
unsubscribed deletes that user, so this will maintain that list of users in the database and make sure that we're not creating a bunch of users, and then they're disappearing. I'm curious, when you close the tab here, this should actually create that, as you saw, there's the red mark there, it jumped, which means that it did a write, and now we have zero documents, which means that we had one document before, we deleted it, and now we have zero documents, and we're able to watch that in real time. This admin is actually doing the watching for chainsets or whatever in order to get real time updates as well as the management console, that is neat as well.
Everything seems to be working fine, the unsubscribe happens automatically when you close the tab, the connection knows that it was disconnected, the
unsubscribe runs, deletes the user, and our database is kept clean, and we don't have hanging users in that table. That's pretty cool, let's go over into our
<section id="active_users"> <h2>Active Users</h2> <ul id="active_users_list"> </ul> </section>
console.log data in order to see what's coming across, so if we print that out, we should see this object. We have new_val, and so we can see that there's that new user, and I bet if we open up localhost:3000 again, we'll see another one, and we do, so we see new_val and old_val, but old_val was null here. The first one didn't include old_val, but these must be coming then from NoBrainer as part of that chainset or chain feed on the table. That's pretty cool.
App.spreadsheet is this file, so the channel is being receiving data, and basically it determines what it needs to do with that data, and if it's a new user, then it will go talk to the spreadsheet
App.spreadsheet and say: Add in this new user, and remove that user if it's time to remove one. This is just kind of delegating what to do with that data that's coming in, and the
App.spreadsheet is actually determining: We'll add this user, we'll remove this user and we'll re-render on the page. Let's see what we've got now in our application.
include_initial: true, you get the initial list of users in the database. For example, if we remove this, you don't get anything, and the reason for that is because you just added yourself to the database before you started streaming, and that does not include you, because this will only get changes since then, so you have to include the initial records in the database as you get started, so that you have a list of all the current users that were there before you, and if you don't do this, you will be a little bit out of sync because you won't see those people. That allows you to stay up to date with those pre existing users.
insertBefore of null, we can go to our application.js and we've got all this, we can also try application.html.erb and put the
<% content_for(:head) %>,
<%= yield :head %> and the section in the appropriate spots, so that that will all be working, and now the next step will be to strain field stream field selection .
Transcript written by Miguel
Hi Chris! Really loving this series so far :) Have you started on part 3 yet? I can recommend keeping the github repository as a reference on the side (perhaps using git log -p) so you're sure not to miss anything as the tutorial will be less and less detailed as the code gains weight because of managing views etc.
Sorry for missing the explanation on that 'yield'. I hope you weren't stuck on the missing table tag too long :)
Hey thanks! I did the whole thing together and just split up the video for consumption's sake and just posting one a day this week. I think I noticed that about halfway through that the tutorial didn't mention everything, so I started referencing the Github repo. :) I'm going to add that in the notes so people can check that out easily as well.
Had a lot of fun going through your tutorial. That was my first time checking out RethinkDB and I like it quite a lot. Please post some more! :D
anyone have any problems with this in Ubuntu 16.04?
After nobrainer.. i get this:
=> Booting Puma
=> Rails 188.8.131.52 application starting in development on http://localhost:3000
=> Run `rails server -h` for more startup options
/home/ivan/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/railties-184.108.40.206/lib/rails/railtie/configuration.rb:95:in `method_missing': undefined method `active_record' for #<rails::application::configuration:0x00559239d9e8f8> (NoMethodError)
active_record railte is commented out so. i don't understand what is going on.. can't find anything about it online
need to comment out line 18:
Rails.application.config.active_record.belongs_to_required_by_default = true
I didn't comment out ActiveRecord so that's why I never had that error.
Looks like you're missing part of disabling ActiveRecord in your config files or something. I'd go through one of those instruction sets again and see if you missed anything: http://stackoverflow.com/a/...