Compare commits
24 Commits
Author | SHA1 | Date |
---|---|---|
John Bintz | 7ff9dc5ff9 | |
John Bintz | 0ba8019c64 | |
John Bintz | 134f93be86 | |
John Bintz | 81bd5c176c | |
John Bintz | 1ab4d353fa | |
John Bintz | b7d0e181d8 | |
John Bintz | b0a8425617 | |
John Bintz | 6b31491da7 | |
John Bintz | 8aea97569e | |
John Bintz | 755ffdb6c0 | |
John Bintz | d7a77e672b | |
John Bintz | 429549027f | |
John Bintz | a37de3c20c | |
John Bintz | 3b1f15f9ab | |
John Bintz | 5c2e078c02 | |
John Bintz | ed9a824c37 | |
John Bintz | 97efc633de | |
John Bintz | 14a2f3f714 | |
John Bintz | 2919235390 | |
John Bintz | 8fbe5628ff | |
John Bintz | b9c2f64d95 | |
John Bintz | adf18ae119 | |
John Bintz | a22177ba54 | |
John Bintz | 1e9213f653 |
|
@ -2,4 +2,12 @@ Autotest.add_hook(:initialize) do |at|
|
|||
at.add_mapping(%r{bin/(.*)}, true) do |filename, matches|
|
||||
at.files_matching(%r{spec/bin/#{matches[1]}_spec\.rb})
|
||||
end
|
||||
|
||||
at.add_mapping(%r{spec/(.*)}, true) do |filename, matches|
|
||||
at.files_matching(%r{#{filename}})
|
||||
end
|
||||
|
||||
at.add_mapping(%r{templates/.*}, true) do |filename, matches|
|
||||
at.files_matching(%r{spec/bin/.*_spec\.rb})
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,15 +7,36 @@ require 'thor/group'
|
|||
class BackboneGenerator < Thor
|
||||
include Thor::Actions
|
||||
|
||||
class_option :coffee, :type => :boolean, :desc => 'Generate CoffeeScript instead of JavaScript'
|
||||
def self.source_root
|
||||
File.expand_path('../../templates', __FILE__)
|
||||
end
|
||||
|
||||
no_tasks do
|
||||
def extension
|
||||
options[:coffee] ? 'coffee' : 'js'
|
||||
end
|
||||
|
||||
def script_target
|
||||
options[:coffee] ? 'app/assets/javascripts' : 'public/javascripts'
|
||||
end
|
||||
|
||||
def view_target
|
||||
'app/views'
|
||||
end
|
||||
|
||||
def test_target
|
||||
'spec/javascripts'
|
||||
end
|
||||
|
||||
def underscore_name
|
||||
singularize(Thor::Util.snake_case(@name.gsub("::", "/")))
|
||||
end
|
||||
|
||||
def css_class_name
|
||||
underscore_name.gsub(%r{[^a-z0-9_]}, '-')
|
||||
end
|
||||
|
||||
def plural_underscore_name
|
||||
pluralize(underscore_name)
|
||||
end
|
||||
|
@ -29,25 +50,25 @@ class BackboneGenerator < Thor
|
|||
end
|
||||
|
||||
def generate_model
|
||||
template('model.js.erb', "public/javascripts/models/#{underscore_name}.js")
|
||||
template('model_spec.js.erb', "spec/javascripts/models/#{underscore_name}_spec.js")
|
||||
template("model.#{extension}.erb", File.join(script_target, "models", "#{underscore_name}.#{extension}"))
|
||||
template("model_spec.#{extension}.erb", File.join(test_target, "models", "#{underscore_name}_spec.#{extension}"))
|
||||
end
|
||||
|
||||
def generate_view
|
||||
template('view.js.erb', "public/javascripts/views/#{underscore_name}_view.js")
|
||||
template('view.jst.erb', "app/views/#{underscore_name}s/view.jst")
|
||||
template('view_spec.js.erb', "spec/javascripts/views/#{underscore_name}_view_spec.js")
|
||||
template("view.#{extension}.erb", File.join(script_target, "views", "#{underscore_name}_view.#{extension}"))
|
||||
template("view.jst.erb", File.join(view_target, "#{underscore_name}s/view.jst"))
|
||||
template("view_spec.#{extension}.erb", File.join(test_target, "views", "#{underscore_name}_view_spec.#{extension}"))
|
||||
end
|
||||
|
||||
def generate_collection
|
||||
template('collection.js.erb', "public/javascripts/collections/#{plural_underscore_name}.js")
|
||||
template('collection_spec.js.erb', "spec/javascripts/collections/#{plural_underscore_name}_spec.js")
|
||||
template("collection.#{extension}.erb", File.join(script_target, "collections", "#{plural_underscore_name}.#{extension}"))
|
||||
template("collection_spec.#{extension}.erb", File.join(test_target, "collections", "#{plural_underscore_name}_spec.#{extension}"))
|
||||
end
|
||||
|
||||
def generate_collection_view
|
||||
template('collection_view.js.erb', "public/javascripts/views/#{plural_underscore_name}_view.js")
|
||||
template('collection_view.jst.erb', "app/views/#{plural_underscore_name}/list.jst")
|
||||
template('collection_view_spec.js.erb', "spec/javascripts/views/#{plural_underscore_name}_view_spec.js")
|
||||
template("collection_view.#{extension}.erb", File.join(script_target, 'views', "#{plural_underscore_name}_view.#{extension}"))
|
||||
template("collection_view.jst.erb", File.join(view_target, "#{plural_underscore_name}/list.jst"))
|
||||
template("collection_view_spec.#{extension}.erb", File.join(test_target, "views", "#{plural_underscore_name}_view_spec.#{extension}"))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -83,7 +104,20 @@ class BackboneGenerator < Thor
|
|||
|
||||
desc 'spec-helper', "Generate a spec helper for Backbone things"
|
||||
def spec_helper
|
||||
template('spec_helper.js.erb', 'spec/javascripts/helpers/backbone_spec_helper.js')
|
||||
template("spec_helper.#{extension}.erb", File.join(test_target, "helpers", "backbone_spec_helper.#{extension}"))
|
||||
end
|
||||
|
||||
desc "app-helper", "Generate an application helper for useful Backbone things"
|
||||
def app_helper
|
||||
template("app_helper.#{extension}.erb", File.join(script_target, "application", "backbone_helper.#{extension}"))
|
||||
end
|
||||
|
||||
desc "app-scaffold", "Generate an application scaffold"
|
||||
def app_scaffold
|
||||
template("app_view.#{extension}.erb", File.join(script_target, "application", "app_view.#{extension}"))
|
||||
template("app_view.jst.erb", File.join(view_target, "application", "app_view.jst"))
|
||||
template("controller.#{extension}.erb", File.join(script_target, "application", "controller.#{extension}"))
|
||||
template("app_view_spec.#{extension}.erb", File.join(test_target, "application", "app_view_spec.#{extension}"))
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -8,9 +8,128 @@ describe 'backbone-generator' do
|
|||
FileUtils.rm_rf 'app'
|
||||
end
|
||||
|
||||
def run(*opts)
|
||||
system %{bin/backbone-generator #{opts.join(' ')}}
|
||||
end
|
||||
|
||||
before { clean! }
|
||||
after { clean! }
|
||||
|
||||
describe 'coffeescript' do
|
||||
def should_generate_model
|
||||
File.file?(model = 'app/assets/javascripts/models/section/model.coffee').should be_true
|
||||
File.file?(spec = 'spec/javascripts/models/section/model_spec.coffee').should be_true
|
||||
|
||||
File.read(model).should match(/SectionModel/)
|
||||
File.read(spec).should match(/SectionModel/)
|
||||
end
|
||||
|
||||
def should_generate_view
|
||||
File.file?(view = 'app/assets/javascripts/views/section/model_view.coffee').should be_true
|
||||
File.file?(spec = 'spec/javascripts/views/section/model_view_spec.coffee').should be_true
|
||||
File.file?(template = 'app/views/section/models/view.jst').should be_true
|
||||
|
||||
File.read(view).should match(/SectionModel/)
|
||||
File.read(view).should match(%r{template: JST\['section/models/view'\]})
|
||||
File.read(spec).should match(/SectionModel/)
|
||||
end
|
||||
|
||||
def should_generate_collection
|
||||
File.file?(collection = 'app/assets/javascripts/collections/section/models.coffee').should be_true
|
||||
File.file?(spec = 'spec/javascripts/collections/section/models_spec.coffee').should be_true
|
||||
|
||||
File.read(collection).should match(/SectionModels/)
|
||||
File.read(collection).should_not match(/SectionModelss/)
|
||||
File.read(collection).should match(%r{section/model})
|
||||
File.read(spec).should match(/SectionModels/)
|
||||
File.read(spec).should_not match(/SectionModelss/)
|
||||
end
|
||||
|
||||
def should_generate_collection_view
|
||||
File.file?(view = 'app/assets/javascripts/views/section/models_view.coffee').should be_true
|
||||
File.file?(spec = 'spec/javascripts/views/section/models_view_spec.coffee').should be_true
|
||||
File.file?(template = 'app/views/section/models/list.jst').should be_true
|
||||
|
||||
File.read(view).should match(/SectionModelsView/)
|
||||
File.read(view).should_not match(/SectionModelssView/)
|
||||
File.read(view).should match(/SectionModelView/)
|
||||
File.read(view).should match(%r{template: JST\['section/models/list'\]})
|
||||
File.read(spec).should match(/SectionModelsView/)
|
||||
File.read(spec).should_not match(/SectionModelssView/)
|
||||
end
|
||||
|
||||
describe 'model' do
|
||||
it "should generate the model files" do
|
||||
run "model", "Section::Model", '--coffee'
|
||||
|
||||
should_generate_model
|
||||
end
|
||||
end
|
||||
|
||||
describe 'view' do
|
||||
it "should generate the model files" do
|
||||
run "view", "Section::Model", '--coffee'
|
||||
|
||||
should_generate_view
|
||||
end
|
||||
end
|
||||
|
||||
describe 'collection view' do
|
||||
it "should generate the collection view files" do
|
||||
run "collection-view", "Section::Model", '--coffee'
|
||||
|
||||
should_generate_collection_view
|
||||
end
|
||||
end
|
||||
|
||||
describe 'collection' do
|
||||
it "should generate the collection files" do
|
||||
run "collection", "Section::Model", '--coffee'
|
||||
|
||||
should_generate_collection
|
||||
end
|
||||
end
|
||||
|
||||
describe 'scaffold' do
|
||||
it "should generate everything!" do
|
||||
run "scaffold", "Section::Model", '--coffee'
|
||||
|
||||
should_generate_model
|
||||
should_generate_view
|
||||
should_generate_collection
|
||||
should_generate_collection_view
|
||||
end
|
||||
end
|
||||
|
||||
describe 'spec helper' do
|
||||
it "should generate a spec helper" do
|
||||
run "spec-helper", '--coffee'
|
||||
|
||||
File.file?(collection = 'spec/javascripts/helpers/backbone_spec_helper.coffee').should be_true
|
||||
end
|
||||
end
|
||||
|
||||
describe 'app helper' do
|
||||
it "should generate an app helper" do
|
||||
run "app-helper", '--coffee'
|
||||
|
||||
File.file?(collection = 'app/assets/javascripts/application/backbone_helper.coffee').should be_true
|
||||
end
|
||||
end
|
||||
|
||||
describe 'application scaffold' do
|
||||
it "should generate an application scaffold" do
|
||||
run "app-scaffold", '--coffee'
|
||||
|
||||
File.file?(app = 'app/assets/javascripts/application/app_view.coffee').should be_true
|
||||
File.file?(app_view = 'app/views/application/app_view.jst').should be_true
|
||||
File.file?(controller = 'app/assets/javascripts/application/controller.coffee').should be_true
|
||||
File.file?(spec = 'spec/javascripts/application/app_view_spec.coffee').should be_true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'javascript' do
|
||||
def should_generate_model
|
||||
File.file?(model = 'public/javascripts/models/section/model.js').should be_true
|
||||
File.file?(spec = 'spec/javascripts/models/section/model_spec.js').should be_true
|
||||
|
@ -57,7 +176,7 @@ describe 'backbone-generator' do
|
|||
|
||||
describe 'model' do
|
||||
it "should generate the model files" do
|
||||
system %{bin/backbone-generator model Section::Model}
|
||||
run "model", "Section::Model"
|
||||
|
||||
should_generate_model
|
||||
end
|
||||
|
@ -65,7 +184,7 @@ describe 'backbone-generator' do
|
|||
|
||||
describe 'view' do
|
||||
it "should generate the view files" do
|
||||
system %{bin/backbone-generator view Section::Model}
|
||||
run "view", "Section::Model"
|
||||
|
||||
should_generate_view
|
||||
end
|
||||
|
@ -74,7 +193,7 @@ describe 'backbone-generator' do
|
|||
describe 'collection view' do
|
||||
context 'without trailing s' do
|
||||
it "should generate the collection view files" do
|
||||
system %{bin/backbone-generator collection-view Section::Model}
|
||||
run "collection-view", "Section::Model"
|
||||
|
||||
should_generate_collection_view
|
||||
end
|
||||
|
@ -82,7 +201,7 @@ describe 'backbone-generator' do
|
|||
|
||||
context 'with trailing s' do
|
||||
it "should generate the collection view files" do
|
||||
system %{bin/backbone-generator collection-view Section::Models}
|
||||
run "collection-view", "Section::Models"
|
||||
|
||||
should_generate_collection_view
|
||||
end
|
||||
|
@ -92,7 +211,7 @@ describe 'backbone-generator' do
|
|||
describe 'collection' do
|
||||
context 'without trailing s' do
|
||||
it "should generate the collection files" do
|
||||
system %{bin/backbone-generator collection Section::Model}
|
||||
run "collection", "Section::Model"
|
||||
|
||||
should_generate_collection
|
||||
end
|
||||
|
@ -100,7 +219,7 @@ describe 'backbone-generator' do
|
|||
|
||||
context 'with trailing s' do
|
||||
it "should generate the collection files" do
|
||||
system %{bin/backbone-generator collection Section::Models}
|
||||
run "collection", "Section::Models"
|
||||
|
||||
should_generate_collection
|
||||
end
|
||||
|
@ -109,7 +228,7 @@ describe 'backbone-generator' do
|
|||
|
||||
describe 'scaffold' do
|
||||
it "should generate everything!" do
|
||||
system %{bin/backbone-generator scaffold Section::Model}
|
||||
run "scaffold", "Section::Model"
|
||||
|
||||
should_generate_model
|
||||
should_generate_view
|
||||
|
@ -120,9 +239,29 @@ describe 'backbone-generator' do
|
|||
|
||||
describe 'spec helper' do
|
||||
it "should generate a spec helper" do
|
||||
system %{bin/backbone-generator spec-helper}
|
||||
run "spec-helper"
|
||||
|
||||
File.file?(collection = 'spec/javascripts/helpers/backbone_spec_helper.js').should be_true
|
||||
end
|
||||
end
|
||||
|
||||
describe 'app helper' do
|
||||
it "should generate an app helper" do
|
||||
run "app-helper"
|
||||
|
||||
File.file?(collection = 'public/javascripts/application/backbone_helper.js').should be_true
|
||||
end
|
||||
end
|
||||
|
||||
describe 'application scaffold' do
|
||||
it "should generate an application scaffold" do
|
||||
run "app-scaffold"
|
||||
|
||||
File.file?(app = 'public/javascripts/application/app_view.js').should be_true
|
||||
File.file?(app_view = 'app/views/application/app_view.jst').should be_true
|
||||
File.file?(controller = 'public/javascripts/application/controller.js').should be_true
|
||||
File.file?(spec = 'spec/javascripts/application/app_view_spec.js').should be_true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
Backbone.Collection.prototype.ensureFetched = (callback) ->
|
||||
if !@_alreadyEnsureFetched
|
||||
_refresher = null
|
||||
_refresher =>
|
||||
this.unbind('refresh', _refresher)
|
||||
callback.apply(this)
|
||||
@_alreadyEnsureFetched = true
|
||||
this.bind('refresh', _refresher)
|
||||
this.fetch()
|
||||
else
|
||||
callback.apply(this)
|
||||
|
||||
Backbone.View.prototype.attributes = ->
|
||||
attrs = {}
|
||||
for field in @attributeFields
|
||||
do (field) =>
|
||||
attrs[field] = this.$("input[name='#{field}']").val()
|
||||
attrs
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/* Ensure a Collection is fetched and has entries before running a block of code. */
|
||||
|
||||
_.extend(Backbone.Collection.prototype, {
|
||||
ensureFetched: function(callback) {
|
||||
if (this._alreadyEnsureFetched) {
|
||||
var _this = this;
|
||||
var _refresher = function() {
|
||||
_this.unbind('refresh', _refresher);
|
||||
callback.apply(_this);
|
||||
_this._alreadyEnsureFetched = true;
|
||||
};
|
||||
this.bind('refresh', _refresher);
|
||||
this.fetch();
|
||||
} else {
|
||||
callback.apply(this);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
_.extend(Backbone.View.prototype, {
|
||||
attributes: function() {
|
||||
var attrs = {};
|
||||
var _this = this;
|
||||
_.each(this.attributeFields, function(field) {
|
||||
attrs[field] = _this.$('input[name="' + field + '"]').val();
|
||||
});
|
||||
return attrs;
|
||||
}
|
||||
});
|
|
@ -0,0 +1,10 @@
|
|||
class window.AppView extends Backbone.View
|
||||
el: '#application'
|
||||
template: JST['application/app_view']
|
||||
initialize: ->
|
||||
controller = new Controller({app: this})
|
||||
Backbone.history.start()
|
||||
render: =>
|
||||
$(@el).html(@template())
|
||||
this
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
var AppView = Backbone.View.extend({
|
||||
el: '#application',
|
||||
template: JST['application/app_view'],
|
||||
initialize: function() {
|
||||
_.bindAll(this, 'render');
|
||||
|
||||
var controller = new Controller({app: this});
|
||||
|
||||
Backbone.history.start();
|
||||
},
|
||||
render: function() {
|
||||
$(this.el).html(this.template());
|
||||
return this;
|
||||
},
|
||||
});
|
||||
|
|
@ -0,0 +1 @@
|
|||
<!-- application view goes here -->
|
|
@ -0,0 +1,9 @@
|
|||
describe 'AppView', ->
|
||||
appView = null
|
||||
|
||||
beforeEach, ->
|
||||
appView = new AppView()
|
||||
|
||||
it 'should render', ->
|
||||
expect($(appView.render().el)).toContain('.something')
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
describe('AppView', function() {
|
||||
var app_view;
|
||||
|
||||
beforeEach(function() {
|
||||
app_view = new AppView();
|
||||
});
|
||||
|
||||
it('should render', function() {
|
||||
expect($(app_view.render().el)).toContain('.something');
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
class window.<%= plural_object_name %> extends Backbone.Collection
|
||||
url: '/<%= plural_underscore_name %>'
|
||||
model: <%= object_name %>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
describe '<%= plural_object_name %>', ->
|
||||
collection = null
|
||||
|
||||
withServer()
|
||||
|
||||
it 'should fetch records from the API', ->
|
||||
collection = new <%= plural_object_name %>()
|
||||
|
||||
@server.respondWith('GET', '/<%= plural_underscore_name %>', @validJSONResponse([{id: 1}]))
|
||||
collection.fetch()
|
||||
@server.respond()
|
||||
|
||||
expect(collection.length).toEqual(1)
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
class window.<%= plural_object_name %>View extends Backbone.View
|
||||
events: {
|
||||
'click button.new': 'addNew'
|
||||
}
|
||||
template: JST['<%= plural_underscore_name %>/list']
|
||||
initialize: ->
|
||||
@collection.bind('refresh', this.addAll)
|
||||
render: =>
|
||||
$(this.el).html(this.template())
|
||||
this.addAll()
|
||||
this
|
||||
addOne: (model) =>
|
||||
view = new <%= object_name %>View({model: model})
|
||||
this.$('.list').append(view.render().el)
|
||||
addAll: =>
|
||||
@collection.each(this.addOne)
|
||||
addNew: =>
|
||||
object = new <%= object_name %>()
|
||||
@collection.add(object)
|
||||
this.addOne(object)
|
||||
|
|
@ -1,9 +1,11 @@
|
|||
var <%= plural_object_name %>View = Backbone.View.extend({
|
||||
events: {
|
||||
'click button.new': 'addNew'
|
||||
},
|
||||
template: JST['<%= plural_underscore_name %>/list'],
|
||||
initialize: function(collection) {
|
||||
_.bindAll(this, 'render', 'addOne', 'addAll');
|
||||
initialize: function() {
|
||||
_.bindAll(this, 'render', 'addOne', 'addAll', 'addNew');
|
||||
|
||||
this.collection = collection;
|
||||
this.collection.bind('refresh', this.addAll);
|
||||
|
||||
this.render();
|
||||
|
@ -19,5 +21,11 @@ var <%= plural_object_name %>View = Backbone.View.extend({
|
|||
},
|
||||
addAll: function() {
|
||||
this.collection.each(this.addOne);
|
||||
},
|
||||
addNew: function() {
|
||||
var object = new <%= object_name %>();
|
||||
this.collection.add(object);
|
||||
|
||||
this.addOne(object);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1 +1,3 @@
|
|||
<div class="list"></div>
|
||||
<button class="new">Create</button>
|
||||
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
describe '<%= plural_object_name %>View', ->
|
||||
view = collection = null
|
||||
|
||||
beforeEach ->
|
||||
collection = new <%= plural_object_name %>()
|
||||
view = new <%= plural_object_name %>View({collection: collection})
|
||||
view.render()
|
||||
|
||||
it 'should render', ->
|
||||
expect($(view.el)).toContain('.list')
|
||||
expect($(view.el)).toContain('button.new')
|
||||
|
||||
it 'should add a new model when new is clicked', ->
|
||||
view.$('button.new').trigger('click')
|
||||
|
||||
expect(view.$('.list')).toContain('.<%= css_class_name %>')
|
||||
expect(collection.length).toEqual(1)
|
||||
|
||||
it 'should render the models when re-rendered', ->
|
||||
expect(view.$('.list')).not.toContain('.<%= css_class_name %>')
|
||||
|
||||
model = new <%= object_name %>({id: 1})
|
||||
collection.add(model)
|
||||
view.render()
|
||||
|
||||
expect(view.$('.list')).toContain('.<%= css_class_name %>')
|
|
@ -6,9 +6,17 @@ describe('<%= plural_object_name %>View', function() {
|
|||
});
|
||||
|
||||
it('should render', function() {
|
||||
view = new <%= plural_object_name %>View(collection);
|
||||
view = new <%= plural_object_name %>View({collection: collection});
|
||||
view.render();
|
||||
|
||||
expect($(view.el)).toContain('.list');
|
||||
expect($(view.el)).toContain('button.new');
|
||||
});
|
||||
|
||||
it('should add a new model when new is clicked', function() {
|
||||
view.$('button.new').trigger('click');
|
||||
|
||||
expect(view.$('.list')).toContain('.<%= underscore_name %>');
|
||||
expect(collection.length).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
class window.Controller extends Backbone.Controller
|
||||
routes: {
|
||||
'index': 'index'
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
var Controller = Backbone.Controller.extend({
|
||||
routes: {
|
||||
'index': 'index'
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1 @@
|
|||
class window.<%= object_name %> extends Backbone.Model
|
|
@ -0,0 +1,8 @@
|
|||
describe '<%= object_name %>', ->
|
||||
model = null
|
||||
|
||||
it 'should have some tests', ->
|
||||
model = new <%= object_name %>()
|
||||
|
||||
expect(true).toEqual(false)
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
window.withServer ->
|
||||
jasmine.getEnv().withServer()
|
||||
|
||||
jasmine.Env.prototype.withServer ->
|
||||
@currentSuite.beforeEach ->
|
||||
@server = sinon.fakeServer.create()
|
||||
|
||||
@currentSuite.afterEach ->
|
||||
@server.restore()
|
||||
|
||||
beforeEach ->
|
||||
@validJSONResponse = (data) ->
|
||||
[ 200, { 'Content-type': 'application/json' }, JSON.stringify(data) ]
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
class window.<%= object_name %>View extends Backbone.View
|
||||
events: {
|
||||
'click button.save': 'save',
|
||||
'click button.delete': 'destroy'
|
||||
}
|
||||
attributeFields: []
|
||||
template: JST['<%= underscore_name %>s/view']
|
||||
className: '<%= css_class_name %>'
|
||||
initialize: ->
|
||||
_.bindAll(this, 'remove')
|
||||
|
||||
@model.bind('change', this.render)
|
||||
@model.bind('remove', this.remove)
|
||||
@model.view = this
|
||||
render: =>
|
||||
$(@el).html(this.template(@model.toJSON()))
|
||||
this.$('button.save').text(if @model.isNew() then 'Create' else 'Update')
|
||||
this.$('button.delete')[if @model.isNew() then 'hide' else 'show']();
|
||||
this
|
||||
save: =>
|
||||
@model.save(this.attributes())
|
||||
destroy: =>
|
||||
if confirm("Are you sure?")
|
||||
@model.destroy()
|
||||
|
|
@ -1,11 +1,31 @@
|
|||
var <%= object_name %>View = Backbone.View.extend({
|
||||
events: {
|
||||
'click button.save': 'save',
|
||||
'click button.delete': 'destroy'
|
||||
},
|
||||
attributeFields: [],
|
||||
template: JST['<%= underscore_name %>s/view'],
|
||||
className: '<%= underscore_name %>',
|
||||
initialize: function() {
|
||||
_.bindAll(this, 'render');
|
||||
_.bindAll(this, 'render', 'save', 'destroy', 'remove');
|
||||
|
||||
this.model.bind('change', this.render);
|
||||
this.model.bind('remove', this.remove);
|
||||
this.model.view = this;
|
||||
},
|
||||
render: function() {
|
||||
$(this.el).html(this.template());
|
||||
$(this.el).html(this.template(this.model.toJSON()));
|
||||
this.$('button.save').text(this.model.isNew() ? 'Create' : 'Update');
|
||||
this.$('button.delete')[this.model.isNew() ? 'hide' : 'show']();
|
||||
return this;
|
||||
},
|
||||
save: function() {
|
||||
this.model.save(this.attributes(), { success: function(model) { model.view.render(); } });
|
||||
},
|
||||
destroy: function() {
|
||||
if (confirm("Are you sure?")) {
|
||||
this.model.destroy();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
<!-- your <%= object_name %>View template goes here -->
|
||||
<!-- your <%= object_name %>View template fields go here -->
|
||||
<button class="save" /><button class="delete">Delete</button>
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
describe '<%= object_name %>View', ->
|
||||
view = model = null
|
||||
|
||||
describe 'new record', ->
|
||||
beforeEach ->
|
||||
model = new <%= object_name %>
|
||||
|
||||
it 'should render with a create button', ->
|
||||
view = new <%= object_name %>View({model: model})
|
||||
view.render()
|
||||
|
||||
expect(view.$('button.save')).toHaveText('Create')
|
||||
|
||||
describe 'existing record', ->
|
||||
beforeEach ->
|
||||
model = new <%= object_name %>({id: 1})
|
||||
setFixtures('<div id="container" />')
|
||||
|
||||
view = new <%= object_name %>View({model: model})
|
||||
view.render()
|
||||
|
||||
it 'should render with an update button', ->
|
||||
expect(view.$('button.save')).toHaveText('Update')
|
||||
|
||||
it 'should destroy the model', ->
|
||||
spyOn(window, 'confirm').andReturn(true)
|
||||
spyOn(model, 'destroy')
|
||||
|
||||
$('#container').append(view.el)
|
||||
view.$('button.delete').trigger('click')
|
||||
|
||||
expect(model.destroy).toHaveBeenCalled()
|
||||
expect(window.confirm).toHaveBeenCalled()
|
||||
|
||||
it 'should remove the view when the model is destroyed', ->
|
||||
$('#container').append(view.render().el)
|
||||
|
||||
expect($('button.save')).toExist()
|
||||
model.trigger('remove')
|
||||
expect($('button.save')).not.toExist()
|
||||
|
|
@ -1,10 +1,50 @@
|
|||
describe('<%= object_name %>View', function() {
|
||||
var view;
|
||||
var view, model;
|
||||
|
||||
it('should render', function() {
|
||||
view = new <%= object_name %>View();
|
||||
describe('new record', function() {
|
||||
beforeEach(function() {
|
||||
model = new <%= object_name %>();
|
||||
});
|
||||
|
||||
it('should render with a create button', function() {
|
||||
view = new <%= object_name %>View({model: model});
|
||||
view.render();
|
||||
|
||||
expect($(view.el)).toContain('.something');
|
||||
expect(view.$('button.save')).toHaveText('Create');
|
||||
});
|
||||
});
|
||||
|
||||
describe('existing record', function() {
|
||||
beforeEach(function() {
|
||||
model = new <%= object_name %>({id: 1});
|
||||
setFixtures('<div id="container" />');
|
||||
|
||||
view = new <%= object_name %>View({model: model});
|
||||
});
|
||||
|
||||
it('should render with an update button', function() {
|
||||
view.render();
|
||||
|
||||
expect(view.$('button.save')).toHaveText('Update');
|
||||
});
|
||||
|
||||
it('should destroy the model', function() {
|
||||
spyOn(window, 'confirm').andReturn(true);
|
||||
spyOn(model, 'destroy');
|
||||
|
||||
$('#container').append(view.el);
|
||||
view.$('button.delete').trigger('click');
|
||||
|
||||
expect(model.destroy).toHaveBeenCalled();
|
||||
expect(window.confirm).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should remove the view when the model is destroyed', function() {
|
||||
$('#container').append(view.render().el);
|
||||
|
||||
expect($('button.save')).toExist();
|
||||
model.trigger('remove');
|
||||
expect($('button.save')).not.toExist();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue