If you move most of the application client side, you could use something like jsdom to test it. That's obviously not going to get you the same level of confidence that a full stack test in a real browser would though. Maybe a combination of the two?
HN user
jnicklas
1) I don't really see how it introduces any abstractions. The only thing we're doing is moving where event bindings are declared from the controller (or Backbone View) to the template. Other than that it's really pretty much the same.
4) I did a very dirty quick benmark. See http://pastie.org/3296683. This just inserts 1000 words into a <ul> in three different ways. With jQuery, by appending each item separately, with jQuery through string concatenation, and with Serenade. I tested this repeatedly with different numbers of words, in different orders and on different browsers.
jQuery with append is around 5x SLOWER than Serenade jQuery with an entire template is around an order of magnitude FASTER than Serenade
In other words, the difference in how jQuery is used is way bigger than the difference to using Serenade.
I then did another dirty benchmark: http://pastie.org/3296747. I've only added a primitive event binding so that clicking the <li>s pops open an alert. A really interesting thing happens. In IE (7,8,9), the difference shrinks to around a factor 5. So jQuery is 5x faster. In all other browsers I tested however, Serenade outperforms even the full string concatenation jQuery example by a slight margin.
I don't think this proves that Serenade is fast, but it's at least not deficiently slow.
1) Smalltalk 80 style design
The advantage is that the controller knows nothing about the DOM, so it is usable and testable without the DOM. And while I agree that it's a single line to add a binding, that quickly becomes a single line for every single event you ever want to listen to. It ends up being a sizable amount of code. Aside from that, it seems clear that binding data is best done in the view, not in the model or controller, why are events different?
2) Using normal JavaScript objects
You don't have to extend the objects with Serenade.Properties. The downside is that data in the view isn't automatically updated. But as in the first examples in the README, it's perfectly acceptable to send in "JSON" directly to the view.
In the example right after the one you posted, I show how to add properties to the prototype. The intent is not to sidestep prototypal inheritance, but since multiple inheritance or mixins aren't available in JavaScript, copying over the functions is as close as we can get.
3) Break out
I just realized that it's not documented in the README, I'll have to fix that, but it's possible to add custom instructions. Any function added to `Serenade.Helpers` is available as an instruction in the view. This is very similar to handlebar's registerHelper. See the spec here: https://github.com/elabs/serenade.js/blob/master/spec/integr...
4) Performance
I have not done any benchmarks, so honestly I can't say how it compares performance wise. I'm not terribly worried about IE7. At the moment, we don't even support it, and it'll be dead soon. We could possible use document fragments to speed up the rendering, but I'm unsure if it actually makes a difference. I would argue that Rails is slow, Ruby is slow, PHP is slow, Java is slow, C is slow, etc..
That's a very cool framework, I hadn't seen it. Thanks for the tip. Feels like they have a lot of similar ideas to mine. Not really sure what Serenade has to do with CoffeeScript though?
You can use Serenade pretty much as a static template engine if you want to. It's quite small (9k), so not a huge dependency.
It can, kind of. Though you will probably have to re-render on the client to get all the events to attach. See the section about express.js support at the bottom of the README (I haven't pushed it to npm yet, so you won't be able to install it, fyi). Other web frameworks aren't currently supported. Theoretically it's possible, though not very convenient.
It doesn't really push towards classes and classical inheritance, you're free to use any object with the framework that you with, which is not the case with most other frameworks that I've seen. It does use them internally, but that's only because I like it that way, I don't want to push that view onto users of this framework.
Thank you :) Glad you like it!
I actually wrote a todo list app as an example (https://github.com/elabs/serenade_todomvc), I'm going to go hide now ;)
I went kind of the opposite way and rewrote the initial example in JavaScript. I'd really prefer if people didn't get hung up on the fact that it's CoffeeScript, I don't think it should matter too much to people using the framework what language the internals are written in.
I really love CoffeeScript. I hope you don't mind I… borrowed… some parts. It was hugely helpful, especially since I'm quite new to writing parsers and lexers. I put attribution in the README and the license file, in case you missed it.
I am not entirely sure what you mean, but adding or removing methods from Ruby classes is extremely simple and there are a number of hooks in place that allow you to play with the class definition on inheritance. But here is another example of the power of Ruby metaprogramming. The example is sort of nuts, but something similar is actually used in the Camping microwebframework.
Blah = {
:foo => proc { puts "foo" },
:bar => proc { puts "bar" },
:baz => proc { puts "baz" }
}
def Monkey(method)
klass = Class.new
klass.class_eval do
define_method :shout do
Blah[method].call
end
end
return klass
end
class Chimp < Monkey(:foo)
end
class Gorilla < Monkey(:bar)
end
a = Chimp.new
a.shout # => "foo"
b = Gorilla.new
b.shout # => "bar"
Blah[:foo] = proc { puts "I have changed" }
a.shout # => "I have changed"