sudojs-rails 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in sudojs-rails.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 robrobbins
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,86 @@
1
+ # Sudojs::Rails
2
+
3
+ More than just making the currently released versions of sudo.js and sudo-x.js
4
+ available to your application, sudojs-rails is about a development pattern. A pattern that is
5
+ enforced, and made covenient, through the use of generators.
6
+
7
+ This highly opinionated workflow creates a global-level namespace for your code, a convenient
8
+ namespace-level observable model, and expects that you want new javascript class objects placed
9
+ into either the `app/assets/javascripts/application/` directory or, preferably, into an
10
+ `app/assets/javascripts/views/<controller_name>/` directory (more below).
11
+
12
+ Along with this, it is expected you will want a 'manifest' file created (or appended to if existing)
13
+ for the newly created Class Object. Manifests will named for controller actions (or the global `application`)
14
+ and should be loaded either globally (in the `application` case) or per controller (more on this below). This
15
+ allows for a degree of freedom when differentiating assets.
16
+
17
+ New Class Objects that you create can inherit from sudo.js defined types, or your own custom classes, and
18
+ be written in .js or .coffee
19
+
20
+ ## Installation
21
+
22
+ Add this line to your application's Gemfile:
23
+
24
+ gem 'sudojs-rails'
25
+
26
+ And then execute:
27
+
28
+ $ bundle
29
+
30
+ Or install it yourself as:
31
+
32
+ $ gem install sudojs-rails
33
+
34
+ ## Usage
35
+
36
+ ### Prepare Your Project
37
+
38
+ Before use, a few steps need to be followed to prepare your project for our preferred workflow.
39
+
40
+ + We place manifest files into an `app/assets/javascripts/manifests` directory. This means that your
41
+ `app/views/layouts/application.html.*` file needs to be adjusted to account for this:
42
+
43
+ <%= javascript_include_tag 'manifests/application.js' %>
44
+
45
+ Preferably, you will **not** place this in your `head` tag
46
+
47
+ + We assume that any Class Object not used more than once (i.e. is unique to a particular controller#action)
48
+ will not go into `application.js` but be placed into its own manifest for that controller. For this to function,
49
+ a helper method can be constructed:
50
+
51
+ # in app/helpers/application_helper.rb
52
+ def controller_javascript
53
+ controller_manifest = File.join('manifests', "#{self.controller_name}.js")
54
+ return '' if Rails.application.assets.find_asset(controller_manifest).nil?
55
+
56
+ return javascript_include_tag(controller_manifest)
57
+ end
58
+
59
+ This allows the following, combined with the previous include tag:
60
+
61
+ <%= javascript_include_tag 'manifests/application.js' %>
62
+ <%= controller_javascript %>
63
+
64
+ + When concatonating for `staging` and `production` environments the following code needs to have been inserted
65
+ into your `config/environments/staging` and `config/environments/production` .rb files:
66
+
67
+ # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
68
+ config.assets.precompile += %w( manifests/* )
69
+
70
+ ### In Practice
71
+
72
+ running the command `rails g` would reveal that a single `sudojs:install` command can be made. Execute the command
73
+ `rails g sudojs:install -h` to see the USAGE directives. Running `rails g sudojs:install Spam` will install the correct files
74
+ and directories (with your shiny new `Spam` namespace).
75
+
76
+ After installing a second generator becomes available, run `rails g` again and `sudojs:class` should now be an option.
77
+ The reason for this is that `:class` depends on a yaml file to be placed in `config/` to function. Execute the command
78
+ `rails g sudojs:class -h` for the directives there.
79
+
80
+ ## Contributing
81
+
82
+ 1. Fork it
83
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
84
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
85
+ 4. Push to the branch (`git push origin my-new-feature`)
86
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+
8
+ require 'bundler/gem_tasks'
9
+
10
+ namespace :sudojs do
11
+ desc "Download the latest released versions sudo.js"
12
+ task :download_latest do
13
+ files = {
14
+ 'sudo.js'=>'https://raw.github.com/robrobbins/sudo-js/jquery/build/debug/sudo.js',
15
+ 'sudo-x.js' => 'https://raw.github.com/robrobbins/sudo-js/jquery/build/debug/sudo-x.js'
16
+ }
17
+
18
+ vendor_dir = "vendor/assets/javascripts"
19
+
20
+ require 'open-uri'
21
+ files.each do |local,remote|
22
+ puts "Downloading #{local}"
23
+ File.open "#{vendor_dir}/#{local}", 'w' do |f|
24
+ f.write open(remote).read
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,47 @@
1
+ Description:
2
+ Create a skeletal sudo.js Class and place the files correctly for a given controller#name.
3
+
4
+ Example:
5
+ `rails g sudojs:class View foo#baz`
6
+
7
+ Where `View` is a Class Object that this new Object will inherit from. Sudo.js itself
8
+ will recognize 5 types:
9
+
10
+ 1. 'Base'
11
+ 2. 'Container'
12
+ 3. 'View'
13
+ 4. 'ViewController'
14
+ 5. 'Dataview'
15
+
16
+ The inheritance for any of these will be set as `_.<Name>` as we assume sudo has taken the
17
+ global `_` char as an alias. If the argument is any other string we assume you are inheriting
18
+ from a custom class and pass it through as is.
19
+
20
+
21
+ Where `foo#baz` *can* match a controller#action (like `home#show`) it does not
22
+ have to. The controller argument (`foo`) allows the generator to place the file correctly and
23
+ create/modify the correct manifest file. The name argument will be the proper name of the
24
+ Class Object itself
25
+
26
+ If a corresponding views/controller/name.html.* is found, a skeletal instantiation of the newly
27
+ created View will be placed there
28
+
29
+ This will create:
30
+ app/
31
+ assests/
32
+ javascripts/
33
+ manifests/
34
+ foo.js
35
+ views/
36
+ foo/
37
+ baz.js
38
+
39
+ And modify (if found):
40
+ app/
41
+ views/
42
+ foo/
43
+ baz.html.*
44
+
45
+ Note:
46
+ If the `route` is application level (application#baz) the file will be placed
47
+ in the application level directory and the manifests/application file will be modified
@@ -0,0 +1,107 @@
1
+ require 'generators/sudojs/helpers.rb'
2
+
3
+ module Sudojs
4
+ module Generators
5
+ class ClassGenerator < Rails::Generators::NamedBase
6
+ include Sudojs::Generators::Helpers
7
+ source_root File.expand_path('../templates', __FILE__)
8
+
9
+ # not really a route but passed in the form controller#name
10
+ argument :route, :type =>:string, :default => 'foo#bar'
11
+
12
+ def set_vars
13
+ # recognized sudo.js class objects. unrecognized names will
14
+ # be considered 'custom' classes
15
+ @class_names = {
16
+ 'Base' => '_.Base',
17
+ 'Container' => '_.Container',
18
+ 'DataView' => '_.DataView',
19
+ 'View' => '_.View',
20
+ 'ViewController' => '_.ViewController'
21
+ }
22
+ ary = route.split('#')
23
+ @c_name = ary[0]
24
+ @c_camel = camelize(@c_name)
25
+ # is this an application level object?
26
+ @is_application = @c_name == 'application'
27
+ # 'action' name not always applicable but thats ok
28
+ @a_name = ary[1]
29
+ @a_camel = camelize(@a_name)
30
+ # class invocations with `new` should always use a proper name
31
+ @a_pascal = @a_camel.capitalize
32
+ # either inherits from a sudo.js class or a custom one
33
+ @parent = @class_names[name] || name
34
+ # the arguments vary in the templates for class types
35
+ if @parent
36
+ if @parent == '_.Base' || @parent == '_.Container'
37
+ @args = 'data'
38
+ else
39
+ @args = 'el, data'
40
+ end
41
+ else
42
+ # cannot guess the args to a custom class
43
+ @args = '/* args */'
44
+ end
45
+ end
46
+
47
+ # expand the template to <destination>
48
+ def copy_class_template
49
+ if @is_application
50
+ path = "app/assets/javascripts/application"
51
+ @path_to_object = namespace
52
+ else
53
+ path = "app/assets/javascripts/views/#{@c_name}"
54
+ @path_to_object = [namespace, '.', @c_camel].join('')
55
+ # make sure the directory is present (create if not)
56
+ ensure_cname_dir(path)
57
+ end
58
+
59
+ if use_coffee?
60
+ template 'class.coffee.erb', "#{path}/#{@a_name}.js.coffee"
61
+ else
62
+ template 'class.js.erb', "#{path}/#{@a_name}.js"
63
+ end
64
+ end
65
+
66
+ def create_or_modify_manifest
67
+ filename = "app/assets/javascripts/manifests/#{@c_name}.js"
68
+ if @is_application
69
+ line = "//= require application/#{@a_name}"
70
+ else
71
+ line = "//= require views/#{@c_name}/#{@a_name}"
72
+ end
73
+
74
+ if File.exist? filename
75
+ # inject_into_file not needed here unless you were using a require tree
76
+ append_to_file filename, line
77
+ else
78
+ template 'manifest.js.erb', filename
79
+ end
80
+ end
81
+
82
+ def modify_view_if_exists
83
+ filename = "app/views/#{@c_name}/#{@a_name}.html.#{which_markup}"
84
+ if File.exist? filename
85
+ if use_coffee?
86
+ comment = '#'
87
+ else
88
+ comment = '//'
89
+ end
90
+ note = "#{comment} Optional invocation of your new Class.\n#{comment} Place this into a jQuery document ready block."
91
+ content = "\n#{note}\n#{comment} #{@path_to_object}.#{@a_camel} = new #{@path_to_object}.#{@a_pascal}(#{@args});"
92
+ append_to_file filename, content
93
+ end
94
+ end
95
+
96
+ private
97
+
98
+ def ensure_cname_dir(path)
99
+ # if exists we will assume a directory
100
+ unless File.exist? path
101
+ empty_directory(path)
102
+ end
103
+ end
104
+
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,13 @@
1
+ _.namespace '<%= @path_to_object %>'
2
+
3
+ class <%= @path_to_object %>.<%= @a_pascal %> extends <%= @parent %>
4
+ # the constructor can be deleted if not used (most actions can be done in the init)
5
+ # an obvious choice is when you need to do something `pre-constructor`
6
+ constructor: (<%= @args %>) ->
7
+ # perform any actions needed `pre-super` here
8
+ super <%= @args %>
9
+
10
+ # optional init for your new viewController, delete if unused
11
+ init: ->
12
+ # do stuff
13
+
@@ -0,0 +1,14 @@
1
+ _.namespace('<%= @path_to_object %>');
2
+
3
+ <%= @path_to_object %>.<%= @a_pascal %> = function(<%= @args %>) {
4
+ // perform any actions needed `pre-super` here
5
+ this.construct(<%= @args %>);
6
+ // perform any `post-super` actions here
7
+ // remember `init` will also be called `post-super` if present
8
+ };
9
+
10
+ <%= @path_to_object %>.<%= @a_pascal %>.prototype = Object.create(<%= @parent %>.prototype);
11
+
12
+ // optional init method for your new viewController, delete if unused
13
+ <%= @path_to_object %>.<%= @a_pascal %>.prototype.init = function init() {};
14
+
@@ -0,0 +1,5 @@
1
+ <% if @is_application %>
2
+ //= require application/<%= @a_name %>
3
+ <% else %>
4
+ //= require views/<%= @c_name %>/<%= @a_name %>
5
+ <% end %>
@@ -0,0 +1,44 @@
1
+ require 'yaml'
2
+
3
+ module Sudojs
4
+ module Generators
5
+ module Helpers
6
+
7
+ CFG = YAML.load_file('config/sudo_js.yml') unless defined? CFG
8
+
9
+ def namespace
10
+ CFG['js_namespace']
11
+ end
12
+
13
+ def which_sudo
14
+ CFG['which_sudo']
15
+ end
16
+
17
+ def which_markup
18
+ CFG['which_markup']
19
+ end
20
+
21
+ def use_coffee?
22
+ CFG['use_coffee']
23
+ end
24
+
25
+ def camelize(what)
26
+ if what.include? '_'
27
+ ary = what.split '_'
28
+ ary.each_with_index {|val, i|
29
+ val.capitalize! if i > 0
30
+ }
31
+ ary.join('')
32
+ else
33
+ what
34
+ end
35
+ end
36
+
37
+ def pascalize(what)
38
+ n = camelize(what)
39
+ n.capitalize
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,27 @@
1
+ Description:
2
+ Install sudo.js along with it's particular directory hierarchy.
3
+
4
+ Example:
5
+ rails g sudojs:install namespace [which_sudo] [which_markup] [use_coffee]
6
+
7
+ The only mandatory argument is the initial `namespace`.
8
+
9
+ The install generator uses these optional arguments to expand the values in the sudo_js.yml file:
10
+ 1. `which_sudo` => which version of sudo.js are you loading? As sudo.js can be rebuilt into any number
11
+ of custom configurations, indicate here what name should be placed into the application manifest.
12
+ Defaults to 'sudo-x' if omitted.
13
+ 2. `which_markup` => defaults to `erb`.
14
+ 3. `use_coffee` => defaults to `false` pass `true` if you are of the coffee persuasion.
15
+
16
+ This will create:
17
+ app/
18
+ assets/
19
+ javascripts/
20
+ application/
21
+ yourNamespace.js
22
+ model.js
23
+ manifests/
24
+ application.js
25
+ views/
26
+ config/
27
+ sudo_js.yml
@@ -0,0 +1,34 @@
1
+ module Sudojs
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::NamedBase
4
+ source_root File.expand_path('../templates', __FILE__)
5
+
6
+ argument :which_sudo_arg, :type => :string, :default => 'sudo-x'
7
+ argument :which_markup_arg, :type => :string, :default => 'erb'
8
+ argument :use_coffee_arg, :type => :string, :default => 'false'
9
+
10
+ def create_yaml
11
+ template 'sudo_js.erb.yml', 'config/sudo_js.yml'
12
+ end
13
+
14
+ def create_dir_structure
15
+ %W{application manifests views}.each do |dir|
16
+ empty_directory "app/assets/javascripts/#{dir}"
17
+ end
18
+ end
19
+
20
+ def place_install_files
21
+ template 'app_manifest.js.erb', 'app/assets/javascripts/manifests/application.js'
22
+
23
+ unless use_coffee_arg == 'false'
24
+ template 'namespace.coffee.erb', "app/assets/javascripts/application/#{name}.js.coffee"
25
+ template 'model.coffee.erb', 'app/assets/javascripts/application/model.js.coffee'
26
+ else
27
+ template 'namespace.js.erb', "app/assets/javascripts/application/#{name}.js"
28
+ template 'model.js.erb', 'app/assets/javascripts/application/model.js'
29
+ end
30
+ end
31
+
32
+ end
33
+ end
34
+ end