Skip to content

Commit

Permalink
Merge branch 'hyperarchy'
Browse files Browse the repository at this point in the history
Conflicts:
	.gitignore
	client/lib/monarch/http/command_batch.js
	client/lib/monarch/model/record.js
  • Loading branch information
Nathan Sobo committed Jan 6, 2010
2 parents 02ec1fb + 3f83133 commit d8088b0
Show file tree
Hide file tree
Showing 62 changed files with 1,282 additions and 125 deletions.
1 change: 1 addition & 0 deletions client/lib/monarch/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//= require "http/create_command"
//= require "http/update_command"
//= require "http/destroy_command"
//= require "http/comet_client"
//= require "http/command_batch"

})(Monarch);
26 changes: 26 additions & 0 deletions client/lib/monarch/http/comet_client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
(function(Monarch) {

Monarch.constructor("Monarch.Http.CometClient", {
connect: function() {
var self = this;
var len = 0
session_id = "fake_client_id";

var xhr = jQuery.ajax({
type: "post",
url: "/comet",
data: { comet_client_id: window.COMET_CLIENT_ID, transport: "xhr_stream" },
complete: function() { self.connect() }
});

xhr.onreadystatechange = function() {
if (xhr.readyState == 3) {
var data = xhr.responseText.slice(len);
len = xhr.responseText.length;
if (data.length > 0) console.debug(data);
}
}
}
});

})(Monarch);
2 changes: 1 addition & 1 deletion client/lib/monarch/http/command_batch.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Monarch.constructor("Monarch.Http.CommandBatch", {
this.future = new Monarch.Http.RepositoryUpdateFuture();

if (this.commands.length > 0) {
this.server.post(Repository.origin_url, { operations: this.wire_representation() })
this.server.post(Repository.origin_url + "/mutate", { operations: this.wire_representation() })
.on_success(function(response_data) {
self.handle_successful_response(response_data);
})
Expand Down
31 changes: 23 additions & 8 deletions client/lib/monarch/http/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ Monarch.constructor("Monarch.Http.Server", {
fetch: function(relations) {
var fetch_future = new Monarch.Http.RepositoryUpdateFuture();

start = new Date().getTime();

this.get(Repository.origin_url, {
this.get(Repository.origin_url + "/fetch", {
relations: Monarch.Util.map(relations, function(relation) {
return relation.wire_representation();
})
Expand All @@ -26,6 +24,18 @@ Monarch.constructor("Monarch.Http.Server", {
return fetch_future;
},

subscribe: function(relations) {
if (!this.comet_client) {
this.comet_client = new Monarch.Http.CometClient();
this.comet_client.connect();
}
return this.post(Repository.origin_url + "/subscribe", {
relations: Monarch.Util.map(relations, function(relation) {
return relation.wire_representation();
})
});
},

save: function() {
var commands = Monarch.Util.map(this.extract_dirty_records(arguments), function(dirty_record) {
return this.build_appropriate_command(dirty_record);
Expand All @@ -35,24 +45,28 @@ Monarch.constructor("Monarch.Http.Server", {
},

post: function(url, data) {
return this.request('POST', url, data);
return this.request('POST', url, this.add_comet_id(data));
},

get: function(url, data) {
return this.request('GET', url, data);
return this.request('GET', url, this.add_comet_id(data));
},

put: function(url, data) {
return this.request('PUT', url, data);
return this.request('PUT', url, this.add_comet_id(data));
},

delete_: function(url, data) {
var url_encoded_data = jQuery.param(this.stringify_json_data(data));
var url_encoded_data = jQuery.param(this.stringify_json_data(this.add_comet_id(data)));
return this.request('DELETE', url + "?" + url_encoded_data);
},

// private

add_comet_id: function(data) {
return Monarch.Util.extend({ comet_client_id: window.COMET_CLIENT_ID }, data);
},

extract_dirty_records: function(records_or_relations) {
var dirty_records = []
Monarch.Util.each(records_or_relations, function(arg) {
Expand Down Expand Up @@ -81,7 +95,7 @@ Monarch.constructor("Monarch.Http.Server", {
url: url,
type: type,
dataType: 'json',
data: data ? this.stringify_json_data(data) : null,
data: this.stringify_json_data(data),
success: function(response) {
future.handle_response(response);
}
Expand All @@ -90,6 +104,7 @@ Monarch.constructor("Monarch.Http.Server", {
},

stringify_json_data: function(data) {
if (!data) return null;
var stringified_data = {};
Monarch.Util.each(data, function(key, value) {
if (typeof value != "string") value = JSON.stringify(value);
Expand Down
4 changes: 4 additions & 0 deletions client/lib/monarch/model/relations/relation.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,10 @@ Monarch.constructor("Monarch.Model.Relations.Relation", {
return Server.fetch([this]);
},

subscribe: function() {
return Server.subscribe([this]);
},

memoize_tuples: function() {
this._tuples = this.tuples();
},
Expand Down
4 changes: 3 additions & 1 deletion client/lib/monarch/model/relations/table.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,10 @@ Monarch.constructor("Monarch.Model.Relations.Table", Monarch.Model.Relations.Rel
if (typeof predicate_or_id === "string") {
var record = this.tuples_by_id[predicate_or_id]
return (record && record.locally_destroyed) ? null : record;
} else {
} else if (predicate_or_id) {
return this.where(predicate_or_id).first();
} else {
throw new Error("You called find with null id");
}
},

Expand Down
8 changes: 4 additions & 4 deletions client/lib/monarch/view/template.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Monarch.constructor("Monarch.View.Template", Monarch.Xml.Template, {
field_values: function() {
var values = {};
this.find("input,select").each(function() {
var elt = $(this);
var elt = jQuery(this);
var name = elt.attr('name');
if (!name) return;
if (elt.is(':checkbox')) {
Expand Down Expand Up @@ -132,7 +132,7 @@ Monarch.constructor("Monarch.View.Template", Monarch.Xml.Template, {
var self = this;
var model = this.model();
this.find("input:text").each(function() {
var elt = $(this);
var elt = jQuery(this);
var field_name = elt.attr('name');
if (model[field_name]) {
elt.val(model[field_name].call(model) || "");
Expand All @@ -146,7 +146,7 @@ Monarch.constructor("Monarch.View.Template", Monarch.Xml.Template, {
var self = this;
var model = this.model();
this.find("input:checkbox").each(function() {
var elt = $(this);
var elt = jQuery(this);
var field_name = elt.attr('name');
if (model[field_name]) {
self.populate_checkbox_field(elt, model[field_name].call(model));
Expand All @@ -164,7 +164,7 @@ Monarch.constructor("Monarch.View.Template", Monarch.Xml.Template, {
var self = this;
var model = this.model();
this.find("select").each(function() {
var elt = $(this);
var elt = jQuery(this);
var field_name = elt.attr('name');
if (model[field_name]) {
elt.val(model[field_name].call(model) || "");
Expand Down
53 changes: 37 additions & 16 deletions client/spec/monarch/http/server_spec.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

//= require "../../monarch_spec_helper"

Screw.Unit(function(c) { with(c) {
Expand All @@ -8,7 +9,7 @@ Screw.Unit(function(c) { with(c) {
server = new Monarch.Http.Server();
});

describe("#fetch and #save", function() {
describe("#fetch, #save, and #subscribe", function() {
before(function() {
// use the fake server implementation of basic request functions (only testing higher levels of abstraction)
server.posts = [];
Expand All @@ -18,6 +19,7 @@ Screw.Unit(function(c) { with(c) {
server.request = FakeServer.prototype.request;
server.add_request = FakeServer.prototype.add_request;
server.remove_request = FakeServer.prototype.remove_request;
Repository.origin_url = "/repository"
});

describe("#fetch(relations)", function() {
Expand All @@ -30,12 +32,11 @@ Screw.Unit(function(c) { with(c) {
});


it("performs a GET to Repository.origin_url with the json to fetch the given Relations, then merges the results into the Repository with the delta events sandwiched by before_events and after_events callback triggers on the returned future", function() {
Repository.origin_url = "/users/steph/repository"
it("performs a GET to {Repository.origin_url}/fetch with the json to fetch the given relations, then merges the results into the Repository with the delta events sandwiched by before_events and after_events callback triggers on the returned future", function() {
var future = server.fetch([Blog.table, User.table]);

expect(server.gets).to(have_length, 1);
expect(server.last_get.url).to(equal, "/users/steph/repository");
expect(server.last_get.url).to(equal, "/repository/fetch");
expect(server.last_get.data).to(equal, {
relations: [Blog.table.wire_representation(), User.table.wire_representation()]
});
Expand Down Expand Up @@ -101,13 +102,32 @@ Screw.Unit(function(c) { with(c) {
});
});

describe("#save(records_or_relations...)", function() {
use_local_fixtures();
describe("#subscribe(relations)", function() {
use_example_domain_model();

before(function() {
Repository.origin_url = "/repo";
it("if there is no comet client, initializes one and connects it", function() {
mock(Monarch.Http.CometClient.prototype, 'connect');
expect(server.comet_client).to(be_null);
server.subscribe([Blog.table, BlogPost.table]);
expect(server.comet_client).to_not(be_null);
expect(server.comet_client.connect).to(have_been_called);
});

it("performs a POST to {Repository.origin_url}/subscribe with the json representation of the given relations", function() {
server.subscribe([Blog.table, BlogPost.table]);

expect(server.posts.length).to(equal, 1);

expect(server.last_post.type).to(equal, "post");
expect(server.last_post.url).to(equal, Repository.origin_url + "/subscribe");
expect(server.last_post.data).to(equal, {
relations: [Blog.table.wire_representation(), BlogPost.table.wire_representation()]
});
});
});

describe("#save(records_or_relations...)", function() {
use_local_fixtures();

context("when given a locally-created record", function() {
var record, table_insert_callback, table_update_callback, table_remove_callback,
Expand All @@ -128,12 +148,12 @@ Screw.Unit(function(c) { with(c) {
record.after_remote_create = mock_function("optional after create hook");
});

it("sends a create command", function() {
it("sends a create command to {Repository.origin_url}/mutate", function() {
var record = User.local_create({full_name: "Jesus Chang"});
server.save(record);

expect(server.posts.length).to(equal, 1);
expect(server.last_post.url).to(equal, Repository.origin_url);
expect(server.last_post.url).to(equal, "/repository/mutate");
expect(server.last_post.data).to(equal, {
operations: [['create', 'users', record.dirty_wire_representation()]]
});
Expand Down Expand Up @@ -220,12 +240,12 @@ Screw.Unit(function(c) { with(c) {
record.after_remote_update = mock_function("optional record on update method");
});

it("sends an update command", function() {
it("sends an update command to {Repository.origin_url}/mutate", function() {
record.name("Bad Bad Children");
server.save(record);

expect(server.posts.length).to(equal, 1);
expect(server.last_post.url).to(equal, Repository.origin_url);
expect(server.last_post.url).to(equal, "/repository/mutate");
expect(server.last_post.data).to(equal, {
operations: [['update', 'blogs', 'recipes', record.dirty_wire_representation()]]
});
Expand Down Expand Up @@ -366,12 +386,12 @@ Screw.Unit(function(c) { with(c) {
record.after_remote_destroy = mock_function("optional after_remote_destroy method");
});

it("sends a destroy command", function() {
it("sends a destroy command to {Repository.origin_url}/mutate", function() {
record.local_destroy();
server.save(record);

expect(server.posts.length).to(equal, 1);
expect(server.last_post.url).to(equal, Repository.origin_url);
expect(server.last_post.url).to(equal, "/repository/mutate");
expect(server.last_post.data).to(equal, {
operations: [['destroy', 'blogs', 'recipes']]
});
Expand Down Expand Up @@ -457,7 +477,7 @@ Screw.Unit(function(c) { with(c) {

expect(server.posts.length).to(equal, 1);

expect(server.last_post.url).to(equal, Repository.origin_url);
expect(server.last_post.url).to(equal, "/repository/mutate");
expect(server.last_post.data).to(equal, {
operations: [
['create', 'users', locally_created.dirty_wire_representation()],
Expand Down Expand Up @@ -599,7 +619,8 @@ Screw.Unit(function(c) { with(c) {

// data is url-encoded and appended as params for delete requests
if (request_method == "delete_") {
expect(ajax_options.url).to(equal, '/users?' + jQuery.param(server.stringify_json_data(data)));
var expected_data = Monarch.Util.extend({comet_client_id: window.COMET_CLIENT_ID}, data)
expect(ajax_options.url).to(equal, '/users?' + jQuery.param(server.stringify_json_data(expected_data)));
expect(ajax_options.data).to(be_null);
} else {
expect(ajax_options.url).to(equal, '/users');
Expand Down
1 change: 1 addition & 0 deletions client/spec/monarch_spec_helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
Screw.Unit(function(c) {
c.init(function() {
c.use_fake_server();
window.COMET_CLIENT_ID = "fake-comet-client-id-from-monarch-spec-helper";
});
});
13 changes: 8 additions & 5 deletions server/lib/monarch.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
dir = File.dirname(__FILE__)
MONARCH_SERVER_ROOT = File.expand_path(File.join(dir, '..', '..'))
MONARCH_CLIENT_SERVER_ROOT = File.expand_path(File.join(MONARCH_SERVER_ROOT, 'client'))
MONARCH_SERVER_SERVER_ROOT = File.expand_path(File.join(MONARCH_SERVER_ROOT, 'server'))
MONARCH_ROOT = File.expand_path(File.join(dir, '..', '..'))
MONARCH_CLIENT_ROOT = File.expand_path(File.join(MONARCH_ROOT, 'client'))
MONARCH_SERVER_ROOT = File.expand_path(File.join(MONARCH_ROOT, 'server'))

require "rubygems"
require "thin"
require "sequel"
require "sequel/extensions/inflector"
require "guid"
require "json"

$:.push("#{MONARCH_SERVER_ROOT}/vendor/pusher/lib")
require "pusher"
require "active_support/ordered_hash"
require "active_support/core_ext/module/delegation"
require "active_support/core_ext/hash/keys"
Expand Down Expand Up @@ -37,5 +40,5 @@ class Numeric
Origin = Model::RemoteRepository.new

MONARCH_ASSET_PREFIX = "" unless defined?(MONARCH_ASSET_PREFIX)
Util::AssetManager.add_js_location("#{MONARCH_ASSET_PREFIX}/monarch/lib", "#{MONARCH_CLIENT_SERVER_ROOT}/lib")
Util::AssetManager.add_js_location("#{MONARCH_ASSET_PREFIX}/monarch/vendor", "#{MONARCH_CLIENT_SERVER_ROOT}/vendor")
Util::AssetManager.add_js_location("#{MONARCH_ASSET_PREFIX}/monarch/lib", "#{MONARCH_CLIENT_ROOT}/lib")
Util::AssetManager.add_js_location("#{MONARCH_ASSET_PREFIX}/monarch/vendor", "#{MONARCH_CLIENT_ROOT}/vendor")
3 changes: 3 additions & 0 deletions server/lib/monarch/http.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
require "#{dir}/http/dispatcher"
require "#{dir}/http/request"
require "#{dir}/http/resource"
require "#{dir}/http/subresource"
require "#{dir}/http/response"
require "#{dir}/http/server"
require "#{dir}/http/asset_service"
require "#{dir}/http/sessioning_service"
require "#{dir}/http/comet_hub"
require "#{dir}/http/comet_client"
Loading

0 comments on commit d8088b0

Please sign in to comment.