backbonify 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +22 -0
- data/README.md +52 -0
- data/Rakefile +2 -0
- data/lib/assets/javascripts/backbone.filter.js +66 -0
- data/lib/assets/javascripts/backbone.grid.js +295 -0
- data/lib/assets/javascripts/backbone.js +1290 -0
- data/lib/assets/javascripts/backbone_datalink.js +21 -0
- data/lib/assets/javascripts/backbone_rails_sync.js +68 -0
- data/lib/assets/javascripts/jquery-ui.js +783 -0
- data/lib/assets/javascripts/jquery.js +9266 -0
- data/lib/assets/javascripts/jquery.notice.js +79 -0
- data/lib/assets/javascripts/json2.js +480 -0
- data/lib/assets/javascripts/underscore.js +999 -0
- data/lib/backbonify.rb +4 -0
- data/lib/backbonify/engine.rb +5 -0
- data/lib/backbonify/version.rb +3 -0
- data/lib/generators/backbonify/USAGE +8 -0
- data/lib/generators/backbonify/hbs/hbs_generator.rb +29 -0
- data/lib/generators/backbonify/hbs/templates/_form.haml +6 -0
- data/lib/generators/backbonify/hbs/templates/_row.haml +4 -0
- data/lib/generators/backbonify/hbs/templates/edit.haml +1 -0
- data/lib/generators/backbonify/hbs/templates/index.haml +13 -0
- data/lib/generators/backbonify/hbs/templates/new.haml +1 -0
- data/lib/generators/backbonify/hbs/templates/page.haml +6 -0
- data/lib/generators/backbonify/hbs/templates/show.haml +1 -0
- data/lib/generators/backbonify/install/install_generator.rb +57 -0
- data/lib/generators/backbonify/install/templates/app.js +47 -0
- data/lib/generators/backbonify/model/model_generator.rb +20 -0
- data/lib/generators/backbonify/model/templates/model.js +35 -0
- data/lib/generators/backbonify/resource_helpers.rb +63 -0
- data/lib/generators/backbonify/router/router_generator.rb +44 -0
- data/lib/generators/backbonify/router/templates/router.js +24 -0
- data/lib/generators/backbonify/router/templates/template.jst +2 -0
- data/lib/generators/backbonify/router/templates/view.coffee +8 -0
- data/lib/generators/backbonify/scaffold/scaffold_generator.rb +26 -0
- data/lib/generators/backbonify/views/templates/edit_view.js +34 -0
- data/lib/generators/backbonify/views/templates/filter_view.js +36 -0
- data/lib/generators/backbonify/views/templates/index_view.js +15 -0
- data/lib/generators/backbonify/views/templates/new_view.js +22 -0
- data/lib/generators/backbonify/views/templates/page_view.js +30 -0
- data/lib/generators/backbonify/views/templates/show_view.js +18 -0
- data/lib/generators/backbonify/views/views_generator.rb +21 -0
- metadata +122 -0
data/lib/backbonify.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'generators/backbonify/resource_helpers'
|
2
|
+
|
3
|
+
module Backbonify
|
4
|
+
module Generators
|
5
|
+
class HbsGenerator < Rails::Generators::NamedBase
|
6
|
+
include Backbonify::Generators::ResourceHelpers
|
7
|
+
|
8
|
+
source_root File.expand_path("../templates", __FILE__)
|
9
|
+
desc "This generator creates a set of Handlebars templates for a model"
|
10
|
+
|
11
|
+
argument :attributes, :type => :array, :default => [], :banner => "field:type field:type"
|
12
|
+
|
13
|
+
|
14
|
+
def create_templates
|
15
|
+
%w(page index show new edit).each do |view|
|
16
|
+
template "#{view}.haml", File.join(backbone_path, "templates", plural_name, "#{view}.jst.hbs.haml")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def create_partials
|
21
|
+
%w(_row _form).each do |view|
|
22
|
+
template "#{view}.haml", File.join(backbone_path, "templates", plural_name, "_#{singular_name}#{view}.jst.hbs.haml")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
{{> <%= singular_name %>_row}}
|
@@ -0,0 +1 @@
|
|
1
|
+
{{> <%= singular_name %>_form}}
|
@@ -0,0 +1 @@
|
|
1
|
+
{{> <%= singular_name %>_row}}
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'generators/backbonify/resource_helpers'
|
2
|
+
|
3
|
+
module Backbonify
|
4
|
+
module Generators
|
5
|
+
class InstallGenerator < Rails::Generators::Base
|
6
|
+
include Backbonify::Generators::ResourceHelpers
|
7
|
+
|
8
|
+
source_root File.expand_path("../templates", __FILE__)
|
9
|
+
desc "This generator installs backbone.js with a default folder layout in app/assets/javascripts/backbone"
|
10
|
+
class_option :skip_git, :type => :boolean, :aliases => "-G", :default => true,
|
11
|
+
:desc => "Skip Git ignores and keeps"
|
12
|
+
class_option :skip_require, :type => :boolean, :aliases => "-R", :default => true,
|
13
|
+
:desc => "Skip injection of requires in app.js (-R), useful for updates"
|
14
|
+
|
15
|
+
def copy_javascripts_libs_to_vendor
|
16
|
+
directory("../../../../../lib/assets/javascripts/", "vendor/assets/javascripts/", :recursive => true)
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
def inject_backbone
|
21
|
+
return if options[:skip_requires]
|
22
|
+
inject_into_file "app/assets/javascripts/application.js", :before => "//= require_tree" do
|
23
|
+
a = %{
|
24
|
+
//= require json2
|
25
|
+
//= require jquery
|
26
|
+
//= require jquery-ui
|
27
|
+
//= require jquery.notice
|
28
|
+
//= require handlebars.runtime
|
29
|
+
//= require underscore
|
30
|
+
//= require backbone
|
31
|
+
// require backbone_rails_sync
|
32
|
+
//= require backbone_datalink
|
33
|
+
//= require backbone.grid
|
34
|
+
//= require #{application_name.underscore}
|
35
|
+
|
36
|
+
$(function(){
|
37
|
+
window.app = #{application_name}.init()
|
38
|
+
});
|
39
|
+
|
40
|
+
}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def create_dir_layout
|
45
|
+
%W{routers models views templates}.each do |dir|
|
46
|
+
empty_directory "app/assets/javascripts/#{dir}"
|
47
|
+
create_file "app/assets/javascripts/#{dir}/.gitkeep" unless options[:skip_git]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def create_app_file
|
52
|
+
template "app.js", "app/assets/javascripts/#{application_name.underscore}.js"
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
//= require_self
|
2
|
+
//= require_tree ./templates
|
3
|
+
//= require_tree ./models
|
4
|
+
//= require_tree ./views
|
5
|
+
//= require_tree ./routers
|
6
|
+
|
7
|
+
var <%= js_app_name %> = (function(){
|
8
|
+
|
9
|
+
|
10
|
+
var initialize = function(){
|
11
|
+
initializeCollections();
|
12
|
+
startListening();
|
13
|
+
|
14
|
+
//new <%= js_app_name %>.Routers.SomeRouter;
|
15
|
+
Backbone.history.start();
|
16
|
+
}
|
17
|
+
|
18
|
+
var initializeCollections = function() {
|
19
|
+
//app.collection = new <%= js_app_name %>.Collections.SomeCollection;
|
20
|
+
}
|
21
|
+
|
22
|
+
var startListening = function() {
|
23
|
+
//app.collection.on("sync", notifySync)
|
24
|
+
//app.collection.on("error", notifyError)
|
25
|
+
}
|
26
|
+
|
27
|
+
var notifySync = function(collection) {
|
28
|
+
$.noticeAdd({text: "Succesfully saved, Yo!"})
|
29
|
+
}
|
30
|
+
|
31
|
+
var notifyError = function(collection) {
|
32
|
+
//_.delay(function() {self.$("input[type='submit']").prop("disabled", false)}, 3000)
|
33
|
+
$.noticeAdd({text: "Error yo, put a date or a film or something"})
|
34
|
+
}
|
35
|
+
|
36
|
+
var app = {
|
37
|
+
init : initialize,
|
38
|
+
Models: {},
|
39
|
+
Collections: {},
|
40
|
+
Routers: {},
|
41
|
+
Views: {}
|
42
|
+
};
|
43
|
+
|
44
|
+
|
45
|
+
return app;
|
46
|
+
|
47
|
+
})()
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'generators/backbonify/resource_helpers'
|
2
|
+
|
3
|
+
module Backbonify
|
4
|
+
module Generators
|
5
|
+
class ModelGenerator < Rails::Generators::NamedBase
|
6
|
+
include Backbonify::Generators::ResourceHelpers
|
7
|
+
|
8
|
+
source_root File.expand_path("../templates", __FILE__)
|
9
|
+
desc "This generator creates a backbone model"
|
10
|
+
|
11
|
+
argument :attributes, :type => :array, :default => [], :banner => "field:type field:type"
|
12
|
+
|
13
|
+
def create_backbone_model
|
14
|
+
template "model.js", "#{backbone_path}/models/#{file_name}.js"
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
//
|
2
|
+
// MODEL
|
3
|
+
//
|
4
|
+
<%= model_namespace %> = Backbone.Model.extend({
|
5
|
+
paramRoot: '<%= singular_table_name %>',
|
6
|
+
urlRoot: '<%= route_url %>',
|
7
|
+
|
8
|
+
defaults: {
|
9
|
+
<% attributes.each do |attribute| -%>
|
10
|
+
<%= attribute.name %>: null,
|
11
|
+
<% end -%>
|
12
|
+
noop:null
|
13
|
+
}
|
14
|
+
|
15
|
+
})
|
16
|
+
|
17
|
+
<%= collection_namespace %> = Backbone.Collection.extend({
|
18
|
+
model: <%= model_namespace %>,
|
19
|
+
url: '<%= route_url %>',
|
20
|
+
|
21
|
+
// A small decorator for 'fetch' to retain last data passed to it
|
22
|
+
fetch: function(options) {
|
23
|
+
this.fetchOptions = options || {};
|
24
|
+
Backbone.Collection.prototype.fetch.call(this, options);
|
25
|
+
},
|
26
|
+
|
27
|
+
// default_fetch uses the last data past to fetch to reload accordingly
|
28
|
+
default_fetch: function() {
|
29
|
+
this.fetch(this.fetchOptions)
|
30
|
+
}
|
31
|
+
|
32
|
+
})
|
33
|
+
|
34
|
+
_.extend(<%= collection_namespace %>.prototype, Filter);
|
35
|
+
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Backbonify
|
2
|
+
module Generators
|
3
|
+
module ResourceHelpers
|
4
|
+
|
5
|
+
def backbone_path
|
6
|
+
"app/assets/javascripts"
|
7
|
+
end
|
8
|
+
|
9
|
+
# => Perf.Models.Performance
|
10
|
+
def model_namespace
|
11
|
+
[js_app_name, "Models", class_name].join(".")
|
12
|
+
end
|
13
|
+
|
14
|
+
# => performance
|
15
|
+
def singular_model_name
|
16
|
+
uncapitalize singular_name.camelize
|
17
|
+
end
|
18
|
+
|
19
|
+
# => performances
|
20
|
+
def plural_model_name
|
21
|
+
uncapitalize(plural_name.camelize)
|
22
|
+
end
|
23
|
+
|
24
|
+
# => Perf.Collections.Performances
|
25
|
+
def collection_namespace
|
26
|
+
[js_app_name, "Collections", plural_name.camelize].join(".")
|
27
|
+
end
|
28
|
+
|
29
|
+
# => Perf.Views.Performances
|
30
|
+
def view_namespace
|
31
|
+
[js_app_name, "Views", plural_name.camelize].join(".")
|
32
|
+
end
|
33
|
+
|
34
|
+
# => Perf.Routers.Performances
|
35
|
+
def router_namespace
|
36
|
+
[js_app_name, "Routers", plural_name.camelize].join(".")
|
37
|
+
end
|
38
|
+
|
39
|
+
def jst(action)
|
40
|
+
"templates/#{plural_name}/#{action}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def js_app_name
|
44
|
+
application_name.camelize
|
45
|
+
end
|
46
|
+
|
47
|
+
# TODO : Add an option so "App" is default
|
48
|
+
def application_name
|
49
|
+
if defined?(Rails) && Rails.application
|
50
|
+
Rails.application.class.name.split('::').first
|
51
|
+
else
|
52
|
+
"application"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# uncapitalize("ABC") => aBC
|
57
|
+
def uncapitalize(str)
|
58
|
+
str[0, 1].downcase << str[1..-1]
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'generators/backbonify/resource_helpers'
|
2
|
+
|
3
|
+
module Backbonify
|
4
|
+
module Generators
|
5
|
+
class RouterGenerator < Rails::Generators::NamedBase
|
6
|
+
include Backbonify::Generators::ResourceHelpers
|
7
|
+
|
8
|
+
source_root File.expand_path("../templates", __FILE__)
|
9
|
+
desc "This generator creates a backbone router (NOT with views and templates for the provided actions)"
|
10
|
+
|
11
|
+
argument :actions, :type => :array, :default => [], :banner => "action action"
|
12
|
+
|
13
|
+
RESERVED_JS_WORDS = %W{
|
14
|
+
break case catch continue debugger default delete do else finally for
|
15
|
+
function if in instanceof new return switch this throw try typeof var void while with
|
16
|
+
}
|
17
|
+
|
18
|
+
def validate_no_reserved_words
|
19
|
+
actions.each do |action|
|
20
|
+
if RESERVED_JS_WORDS.include? action
|
21
|
+
raise Thor::Error, "The name '#{action}' is reserved by javascript " <<
|
22
|
+
"Please choose an alternative action name and run this generator again."
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def create_router_files
|
28
|
+
template 'router.js', File.join(backbone_path, "routers", class_path, "#{file_name}_router.js")
|
29
|
+
end
|
30
|
+
|
31
|
+
#def create_view_files
|
32
|
+
# actions.each do |action|
|
33
|
+
# @action = action
|
34
|
+
# @view_path = File.join(backbone_path, "views", plural_name, "#{action}_view.js.coffee")
|
35
|
+
# @jst_path = File.join(backbone_path,"templates", plural_name, "#{action}.jst.ejs")
|
36
|
+
#
|
37
|
+
# template "view.coffee", @view_path
|
38
|
+
# template "template.jst", @jst_path
|
39
|
+
# end
|
40
|
+
#end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
//
|
2
|
+
// Router
|
3
|
+
//
|
4
|
+
<%= router_namespace %>Router = Backbone.Router.extend({
|
5
|
+
routes : {
|
6
|
+
"<%= plural_name %>" : "index",
|
7
|
+
"<%= plural_name %>/:id" : "show"
|
8
|
+
},
|
9
|
+
|
10
|
+
page: null,
|
11
|
+
|
12
|
+
initialize : function() {
|
13
|
+
this.page = new <%= "#{view_namespace}.#{'page'.camelize}View()" %>
|
14
|
+
this.page.display();
|
15
|
+
},
|
16
|
+
|
17
|
+
index : function(){
|
18
|
+
$("#orchestraPage, #contractPage").hide()
|
19
|
+
this.page.slide()
|
20
|
+
},
|
21
|
+
|
22
|
+
show : function(id) {}
|
23
|
+
|
24
|
+
});
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'generators/backbonify/resource_helpers'
|
2
|
+
|
3
|
+
module Backbonify
|
4
|
+
module Generators
|
5
|
+
class ScaffoldGenerator < Rails::Generators::NamedBase
|
6
|
+
include Backbonify::Generators::ResourceHelpers
|
7
|
+
|
8
|
+
source_root File.expand_path("../templates", __FILE__)
|
9
|
+
desc "This generator creates the client side crud scaffolding"
|
10
|
+
|
11
|
+
|
12
|
+
class_option :model, :default => true, :type => :string
|
13
|
+
hook_for :model
|
14
|
+
|
15
|
+
class_option :router, :default => true, :type => :string
|
16
|
+
hook_for :router
|
17
|
+
|
18
|
+
class_option :views, :default => true, :type => :string
|
19
|
+
hook_for :views
|
20
|
+
|
21
|
+
class_option :js_template, :default => "hbs", :type => :string
|
22
|
+
hook_for :js_template
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
//
|
2
|
+
// EDIT : <%= singular_name.capitalize %>
|
3
|
+
//
|
4
|
+
<%= view_namespace %> = <%= view_namespace %> || {};
|
5
|
+
|
6
|
+
<%= view_namespace %>.EditView = Grid.EditView.extend({
|
7
|
+
tagName : "tr",
|
8
|
+
className : "new_<%= singular_name %>",
|
9
|
+
template : JST["templates/<%= plural_name %>/show"],
|
10
|
+
cell : null,
|
11
|
+
attribute : null,
|
12
|
+
inputTag : null,
|
13
|
+
|
14
|
+
initialize : function() {
|
15
|
+
var self = this;
|
16
|
+
this.model.bind("sync", this.renderRow, this);
|
17
|
+
//this.slowSaving = _.debounce(function(){ self.model.save() }, 1100);
|
18
|
+
},
|
19
|
+
|
20
|
+
|
21
|
+
_createInputTemplate : function() {
|
22
|
+
if( this.cell.hasClass('address') ) {
|
23
|
+
return "<textarea style='height:25px' name='address'><%%="+ this.attribute+"%></textarea>"
|
24
|
+
} else {
|
25
|
+
return '<input id="<%= singular_name %>_' + this.attribute +
|
26
|
+
'" value="<%%=' + this.attribute +
|
27
|
+
'%>" name="' + this.attribute + '" />'
|
28
|
+
}
|
29
|
+
},
|
30
|
+
|
31
|
+
noop:null
|
32
|
+
});
|
33
|
+
|
34
|
+
//_.extend(<%= view_namespace %>.EditView.prototype, <%= js_app_name %>.FormHelpers);
|