add comet support for real-time chatting
authorCharles McGarvey <chazmcgarvey@brokenzipper.com>
Wed, 4 Jan 2012 02:38:03 +0000 (19:38 -0700)
committerCharles McGarvey <chazmcgarvey@brokenzipper.com>
Wed, 4 Jan 2012 02:38:03 +0000 (19:38 -0700)
db/schema.sql
lib/Chatty/Controller/Chat.pm
lib/Chatty/Form/MessageCreate.pm [deleted file]
lib/Chatty/Model/DB.pm
lib/Chatty/Schema.pm
lib/Chatty/Schema/Result/Account.pm
lib/Chatty/Schema/Result/Message.pm [deleted file]
lib/Chatty/Schema/Result/Room.pm
root/tt/chat/view.tt
root/tt/wrapper.tt

index 536b1f372cf74467248dd1c573a2f289676146b8..dfd06e3dafb911a794e4c48382ead1357ad657ba 100644 (file)
@@ -15,14 +15,3 @@ CREATE TABLE account (
        current_room    INTEGER REFERENCES room(id)
 );
 
-CREATE TABLE message (
-       id              INTEGER PRIMARY KEY,
-       posted          TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
-       author          INTEGER REFERENCES account(id),
-       room            INTEGER REFERENCES room(id),
-       content         TEXT
-);
-
-INSERT INTO account (username, password) VALUES ('chaz', 'mypass');
-INSERT INTO account (username, password) VALUES ('jdoe', 'foobar');
-
index 73fe2744e99c32ecfcfba61b6a222feabad8857c..911c127ed95b18229c059b5891e86599a57e9a6d 100644 (file)
@@ -7,7 +7,6 @@ BEGIN { extends 'Catalyst::Controller' }
 #__PACKAGE__->config(namespace => 'room');
 
 use Chatty::Form::RoomCreate;
-use Chatty::Form::MessageCreate;
 
 has 'roomcreate_form' => (
        isa     => 'Chatty::Form::RoomCreate',
@@ -16,13 +15,6 @@ has 'roomcreate_form' => (
        default => sub { Chatty::Form::RoomCreate->new }
 );
 
-has 'messagecreate_form' => (
-       isa     => 'Chatty::Form::MessageCreate',
-       is      => 'rw',
-       lazy    => 1,
-       default => sub { Chatty::Form::MessageCreate->new }
-);
-
 =head1 NAME
 
 Chatty::Controller::Chat - Catalyst Controller
@@ -100,27 +92,17 @@ sub view :Chained(room) :PathPart('') :Args(1) {
        $c->stash(room => $c->model('DB::Room')->find($room));
        $c->detach('/missing') if !$c->stash->{room};
 
-       $c->stash(messages => [$c->model('DB::Message')->search(room => $room)]);
-
-       $c->stash(form => $self->messagecreate_form);
+       my $name = $c->user->obj->username;
 
-       my $new_message = $c->model('DB::Message')->new_result({
-               author => $c->user->obj->id,
-               room => $c->stash->{room}->id
-       });
-       $self->messagecreate_form->process(
-               item    => $new_message,
-               params  => $c->req->params
-       );
-
-       if (!$self->messagecreate_form->is_valid) {
-               if ($c->req->method eq 'POST') {
-                       $c->stash->{error} = "The form has a validation error. Try again...";
-               }
+       my $msg = $c->req->param('msg');
+       if ($msg) {
+               $c->model('Meteor')->addMessage($room, "$name: $msg");
+               $c->stash->{json} = \1;
+               $c->forward('View::JSON');
                return;
        }
 
-       $c->res->redirect($c->uri_for_action('/chat/view', $c->stash->{room}->id));
+       $c->model('Meteor')->addMessage($room, "** $name has entered **");
 }
 
 =head1 AUTHOR
diff --git a/lib/Chatty/Form/MessageCreate.pm b/lib/Chatty/Form/MessageCreate.pm
deleted file mode 100644 (file)
index 72b616e..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-package Chatty::Form::MessageCreate;
-
-use HTML::FormHandler::Moose;
-extends 'HTML::FormHandler::Model::DBIC';
-use namespace::autoclean;
-
-has '+item_class' => (default => 'Message');
-
-has_field 'content' => (input_class => 'validate[required]', label => 'Message', required => 1);
-has_field 'submit' => (type => 'Submit', value => 'Create');
-
-__PACKAGE__->meta->make_immutable;
-1;
index 91b1c19d8410f149b2d66c21d5647e98da0e60cb..82b4e943647a1c9a03d790faa3cbac8afd6f1648 100644 (file)
@@ -28,7 +28,7 @@ L<Catalyst::Model::DBIC::Schema> Model using schema L<Chatty::Schema>
 
 =head1 GENERATED BY
 
-Catalyst::Helper::Model::DBIC::Schema - 0.55
+Catalyst::Helper::Model::DBIC::Schema - 0.59
 
 =head1 AUTHOR
 
index 3d5ca2d0949a80b04c67a8f8d9dc05d7a5fc14a2..885c67b91d2b9851e50b71a4a232939af9dff2ca 100644 (file)
@@ -1,17 +1,18 @@
+use utf8;
 package Chatty::Schema;
 
 # Created by DBIx::Class::Schema::Loader
 # DO NOT MODIFY THE FIRST PART OF THIS FILE
 
 use Moose;
-use namespace::autoclean;
+use MooseX::MarkAsMethods autoclean => 1;
 extends 'DBIx::Class::Schema';
 
 __PACKAGE__->load_namespaces;
 
 
-# Created by DBIx::Class::Schema::Loader v0.07010 @ 2011-10-12 22:19:43
-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:cnsy0B+9E32Gp6UQcsNpuA
+# Created by DBIx::Class::Schema::Loader v0.07015 @ 2012-01-03 16:46:04
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:Kti71GT2ETr1GjBJljQ1Zg
 
 
 # You can replace this text with custom code or comments, and it will be preserved on regeneration
index 60b33b1826d7441833539f8384eeddd281e0b4b6..cedd0aece1c2ca680901176f61362b3e703076db 100644 (file)
@@ -1,21 +1,36 @@
+use utf8;
 package Chatty::Schema::Result::Account;
 
 # Created by DBIx::Class::Schema::Loader
 # DO NOT MODIFY THE FIRST PART OF THIS FILE
 
+=head1 NAME
+
+Chatty::Schema::Result::Account
+
+=cut
+
 use strict;
 use warnings;
 
 use Moose;
 use MooseX::NonMoose;
-use namespace::autoclean;
+use MooseX::MarkAsMethods autoclean => 1;
 extends 'DBIx::Class::Core';
 
-__PACKAGE__->load_components("InflateColumn::DateTime", "TimeStamp");
+=head1 COMPONENTS LOADED
 
-=head1 NAME
+=over 4
 
-Chatty::Schema::Result::Account
+=item * L<DBIx::Class::InflateColumn::DateTime>
+
+=back
+
+=cut
+
+__PACKAGE__->load_components("InflateColumn::DateTime");
+
+=head1 TABLE: C<account>
 
 =cut
 
@@ -29,11 +44,6 @@ __PACKAGE__->table("account");
   is_auto_increment: 1
   is_nullable: 0
 
-=head2 email
-
-  data_type: 'text'
-  is_nullable: 1
-
 =head2 username
 
   data_type: 'text'
@@ -61,8 +71,6 @@ __PACKAGE__->table("account");
 __PACKAGE__->add_columns(
   "id",
   { data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
-  "email",
-  { data_type => "text", is_nullable => 1 },
   "username",
   { data_type => "text", is_nullable => 1 },
   "password",
@@ -72,7 +80,31 @@ __PACKAGE__->add_columns(
   "current_room",
   { data_type => "integer", is_foreign_key => 1, is_nullable => 1 },
 );
+
+=head1 PRIMARY KEY
+
+=over 4
+
+=item * L</id>
+
+=back
+
+=cut
+
 __PACKAGE__->set_primary_key("id");
+
+=head1 UNIQUE CONSTRAINTS
+
+=head2 C<username_unique>
+
+=over 4
+
+=item * L</username>
+
+=back
+
+=cut
+
 __PACKAGE__->add_unique_constraint("username_unique", ["username"]);
 
 =head1 RELATIONS
@@ -97,24 +129,9 @@ __PACKAGE__->belongs_to(
   },
 );
 
-=head2 messages
-
-Type: has_many
-
-Related object: L<Chatty::Schema::Result::Message>
-
-=cut
-
-__PACKAGE__->has_many(
-  "messages",
-  "Chatty::Schema::Result::Message",
-  { "foreign.author" => "self.id" },
-  { cascade_copy => 0, cascade_delete => 0 },
-);
-
 
-# Created by DBIx::Class::Schema::Loader v0.07010 @ 2011-10-17 20:21:50
-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:jbeLiaDPsjHNHj5O11tPFA
+# Created by DBIx::Class::Schema::Loader v0.07015 @ 2012-01-03 16:58:35
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:vESFaWXuN0WYXW2Y18BfRg
 
 
 # You can replace this text with custom code or comments, and it will be preserved on regeneration
diff --git a/lib/Chatty/Schema/Result/Message.pm b/lib/Chatty/Schema/Result/Message.pm
deleted file mode 100644 (file)
index 78a7441..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-package Chatty::Schema::Result::Message;
-
-# Created by DBIx::Class::Schema::Loader
-# DO NOT MODIFY THE FIRST PART OF THIS FILE
-
-use strict;
-use warnings;
-
-use Moose;
-use MooseX::NonMoose;
-use namespace::autoclean;
-extends 'DBIx::Class::Core';
-
-__PACKAGE__->load_components("InflateColumn::DateTime", "TimeStamp");
-
-=head1 NAME
-
-Chatty::Schema::Result::Message
-
-=cut
-
-__PACKAGE__->table("message");
-
-=head1 ACCESSORS
-
-=head2 id
-
-  data_type: 'integer'
-  is_auto_increment: 1
-  is_nullable: 0
-
-=head2 posted
-
-  data_type: 'timestamp'
-  default_value: current_timestamp
-  is_nullable: 1
-
-=head2 author
-
-  data_type: 'integer'
-  is_foreign_key: 1
-  is_nullable: 1
-
-=head2 room
-
-  data_type: 'integer'
-  is_foreign_key: 1
-  is_nullable: 1
-
-=head2 content
-
-  data_type: 'text'
-  is_nullable: 1
-
-=cut
-
-__PACKAGE__->add_columns(
-  "id",
-  { data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
-  "posted",
-  {
-    data_type     => "timestamp",
-    default_value => \"current_timestamp",
-    is_nullable   => 1,
-  },
-  "author",
-  { data_type => "integer", is_foreign_key => 1, is_nullable => 1 },
-  "room",
-  { data_type => "integer", is_foreign_key => 1, is_nullable => 1 },
-  "content",
-  { data_type => "text", is_nullable => 1 },
-);
-__PACKAGE__->set_primary_key("id");
-
-=head1 RELATIONS
-
-=head2 room
-
-Type: belongs_to
-
-Related object: L<Chatty::Schema::Result::Room>
-
-=cut
-
-__PACKAGE__->belongs_to(
-  "room",
-  "Chatty::Schema::Result::Room",
-  { id => "room" },
-  {
-    is_deferrable => 1,
-    join_type     => "LEFT",
-    on_delete     => "CASCADE",
-    on_update     => "CASCADE",
-  },
-);
-
-=head2 author
-
-Type: belongs_to
-
-Related object: L<Chatty::Schema::Result::Account>
-
-=cut
-
-__PACKAGE__->belongs_to(
-  "author",
-  "Chatty::Schema::Result::Account",
-  { id => "author" },
-  {
-    is_deferrable => 1,
-    join_type     => "LEFT",
-    on_delete     => "CASCADE",
-    on_update     => "CASCADE",
-  },
-);
-
-
-# Created by DBIx::Class::Schema::Loader v0.07010 @ 2011-10-17 20:21:50
-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:R28y3tHGM5FZTILUAO/0XA
-
-
-# You can replace this text with custom code or comments, and it will be preserved on regeneration
-__PACKAGE__->meta->make_immutable;
-1;
index 53516f3050d20ddb1e57eccccf5e9242a8b4e73a..2ba86525548d7438a01664236b24ead563c1b822 100644 (file)
@@ -1,21 +1,36 @@
+use utf8;
 package Chatty::Schema::Result::Room;
 
 # Created by DBIx::Class::Schema::Loader
 # DO NOT MODIFY THE FIRST PART OF THIS FILE
 
+=head1 NAME
+
+Chatty::Schema::Result::Room
+
+=cut
+
 use strict;
 use warnings;
 
 use Moose;
 use MooseX::NonMoose;
-use namespace::autoclean;
+use MooseX::MarkAsMethods autoclean => 1;
 extends 'DBIx::Class::Core';
 
-__PACKAGE__->load_components("InflateColumn::DateTime", "TimeStamp");
+=head1 COMPONENTS LOADED
 
-=head1 NAME
+=over 4
 
-Chatty::Schema::Result::Room
+=item * L<DBIx::Class::InflateColumn::DateTime>
+
+=back
+
+=cut
+
+__PACKAGE__->load_components("InflateColumn::DateTime");
+
+=head1 TABLE: C<room>
 
 =cut
 
@@ -54,7 +69,31 @@ __PACKAGE__->add_columns(
     is_nullable   => 1,
   },
 );
+
+=head1 PRIMARY KEY
+
+=over 4
+
+=item * L</id>
+
+=back
+
+=cut
+
 __PACKAGE__->set_primary_key("id");
+
+=head1 UNIQUE CONSTRAINTS
+
+=head2 C<name_unique>
+
+=over 4
+
+=item * L</name>
+
+=back
+
+=cut
+
 __PACKAGE__->add_unique_constraint("name_unique", ["name"]);
 
 =head1 RELATIONS
@@ -74,24 +113,9 @@ __PACKAGE__->has_many(
   { cascade_copy => 0, cascade_delete => 0 },
 );
 
-=head2 messages
-
-Type: has_many
-
-Related object: L<Chatty::Schema::Result::Message>
-
-=cut
-
-__PACKAGE__->has_many(
-  "messages",
-  "Chatty::Schema::Result::Message",
-  { "foreign.room" => "self.id" },
-  { cascade_copy => 0, cascade_delete => 0 },
-);
-
 
-# Created by DBIx::Class::Schema::Loader v0.07010 @ 2011-10-17 20:21:50
-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:U0zHyxd2zFVEnATmgpd+Ag
+# Created by DBIx::Class::Schema::Loader v0.07015 @ 2012-01-03 16:46:51
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:36bNroQtVWZPWUMc+6yAQw
 
 
 # You can replace this text with custom code or comments, and it will be preserved on regeneration
index 19fe0c0d4c49d2e0ad9770f95e9d1d9b6b1ae83a..5804093d16a7506a8b7a03ccf722900104e8baea 100644 (file)
@@ -1,9 +1,42 @@
 [% META title = 'Live' -%]
+[% BLOCK js_include -%]
+  <script type="text/javascript" src="http://data.chatty.com/meteor.js"></script>
+[% END -%]
 [% BLOCK js -%]
-$('form').validationEngine();
+  Meteor.hostid = '' + Math.floor(999*Math.random());
+  Meteor.host = "data."+location.hostname;
+  Meteor.registerEventCallback("process", addMessage);
+  Meteor.registerEventCallback("eof", function() {
+    addMessage("** stream closed **");
+  });
+  Meteor.registerEventCallback("reset", function() {
+    addMessage("** stream reset **");
+  });
+  Meteor.registerEventCallback("changemode", function(mode) {
+    addMessage("** mode changed to "+mode+" **");
+  });
+  Meteor.joinChannel("[% room.id %]", 5);
+  Meteor.mode = 'stream';
+  Meteor.connect();
+
+  function addMessage(line) {
+    $("#chat").append("<p>"+line+"</p>");
+    $("#chat").stop().animate({scrollTop:$("#chat").prop("scrollHeight")}, 350);
+  };
+
+  $("#submit").click(function(e) {
+    $.getJSON("", {msg: $("#msg").val()},
+    function(data) {
+    });
+    $("#msg").val("");
+    e.preventDefault();
+  });
+  $("#msg").focus();
 [% END -%]
 <h1>Room: [% room.name %]</h1>
-[% FOREACH msg IN messages -%]
-<p>[% msg.author.username %] ([% msg.posted %]): [% msg.content %]</p>
-[% END -%]
-[% form.render -%]
+<div id="chat" style="height: 300px; overflow: auto"></div>
+<form id="chat_send">
+  <i>Say your thing:</i>
+  <input id="msg" type="input"></input>
+  <input id="submit" type="submit" value="Send"></input>
+<form>
index 87d510628de4799a1f458950054dd445a607bf23..82e3403d0bc870099694a85e76f57f66fcaccc73 100644 (file)
@@ -43,6 +43,7 @@
                <script type="text/javascript" src="http://cdn.jquerytools.org/1.2.6/full/jquery.tools.min.js"></script>
                <script type="text/javascript" src="[% c.uri_for('/static/js/jquery.validationEngine-2.2.1.min.js') %]"></script>
                <script type="text/javascript" src="[% c.uri_for('/static/js/jquery.validationEngine-en.js') %]"></script>
+[% TRY; INCLUDE js_include; CATCH; ''; END -%]
                <script type="text/javascript">
                        $(function () {
 [% IF error -%]
This page took 0.045747 seconds and 4 git commands to generate.