ember-rails 0.2.4 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,10 +1,10 @@
1
- # ember-rails [![Build Status](https://secure.travis-ci.org/keithpitt/ember-rails.png)](http://travis-ci.org/keithpitt/ember-rails)
1
+ # ember-rails [![Build Status](https://secure.travis-ci.org/keithpitt/ember-rails.png)](http://travis-ci.org/keithpitt/ember-rails) [![Dependency Status](https://gemnasium.com/emberjs/ember-rails.png)](https://gemnasium.com/emberjs/ember-rails)
2
2
 
3
- ember-rails allows you to include [Ember.JS](http://emberjs.com/) into your Rails 3.x application.
3
+ ember-rails allows you to include [Ember.JS](http://emberjs.com/) into your Rails 3.1+ application.
4
4
 
5
5
  The gem will also pre-compile your handlebars templates when building your asset pipeline. It includes development and production copies of Ember.
6
6
 
7
- You can see an example of how to use the gem [here](https://github.com/keithpitt/ember-rails-example)
7
+ You can see an example of how to use the gem [here](https://github.com/keithpitt/ember-rails-example). There is also a great tutorial by [Dan Gebhardt](https://twitter.com/#!/dgeb) called "[Beginning Ember.js on Rails](http://www.cerebris.com/blog/2012/01/24/beginning-ember-js-on-rails-part-1/)" which is a great read if your just starting out with Rails and Ember.js
8
8
 
9
9
  ## Getting started
10
10
 
@@ -12,23 +12,81 @@ Add the gem to your application Gemfile:
12
12
 
13
13
  gem "ember-rails"
14
14
 
15
- Run `bundle install` and add the following line to
16
- `app/assets/javascripts/application.js`:
15
+ Run `bundle install` and add the following line to `app/assets/javascripts/application.js`:
17
16
 
18
17
  //= require ember
19
18
 
20
19
  Ember-rails also provides a way to run Ember in development mode, you
21
- can switch out your require statements to use the dev copies like so:
20
+ can switch out your require statement `//= require ember` to use the
21
+ dev copies like so:
22
22
 
23
23
  //= require ember-dev
24
24
 
25
+ ## Architecture
26
+
27
+ Ember does not require an organized file structure. However, ember-rails allows you
28
+ to use `rails g ember:bootstrap` to create the following directory structure under `app/assets/javascripts/ember`:
29
+
30
+ controllers/
31
+ helpers/
32
+ models/
33
+ templates/
34
+ views/
35
+
36
+ Additionally, it will add the following lines to `app/assets/javascripts/application.js`.
37
+ By default, it uses the Rails Application's name and creates an `rails_app_name.js.coffee`
38
+ file to setup application namespace and initial requires:
39
+
40
+ //= require ember
41
+ //= require ember/app
42
+
43
+ *Example:*
44
+
45
+ rails g ember:bootstrap
46
+ insert app/assets/javascripts/application.js
47
+ create app/assets/javascripts/ember/models
48
+ create app/assets/javascripts/ember/models/.gitkeep
49
+ create app/assets/javascripts/ember/controllers
50
+ create app/assets/javascripts/ember/controllers/.gitkeep
51
+ create app/assets/javascripts/ember/views
52
+ create app/assets/javascripts/ember/views/.gitkeep
53
+ create app/assets/javascripts/ember/helpers
54
+ create app/assets/javascripts/ember/helpers/.gitkeep
55
+ create app/assets/javascripts/ember/templates
56
+ create app/assets/javascripts/ember/templates/.gitkeep
57
+ create app/assets/javascripts/ember/app.js.coffee
58
+
59
+ If you want to avoid `.gitkeep` files, use the `skip git` option like
60
+ this: `rails g ember:bootstrap -g`.
61
+
25
62
  Ask Rails to serve HandlebarsJS and pre-compile templates to Ember
26
- by putting each template in a dedicated ".js.hjs" or ".handlebars" file
63
+ by putting each template in a dedicated ".js.hjs", ".hbs" or ".handlebars" file
27
64
  (e.g. `app/assets/javascripts/templates/admin_panel.handlebars`)
28
65
  and including the assets in your layout:
29
66
 
30
67
  <%= javascript_include_tag "templates/admin_panel" %>
31
68
 
69
+ If you want to strip template root from template names, add `templates_root` option to your application configuration block :
70
+
71
+ config.handlebars.templates_root = 'templates'
72
+
73
+ The result will be like this :
74
+
75
+ Ember.TEMPLATES['admin_panel'] = "...";
76
+
77
+ If you want a different path separator in template names add `templates_path_separator` option to your application configuration block :
78
+
79
+ config.handlebars.templates_path_separator = '-'
80
+
81
+ The result will be like this :
82
+
83
+ Ember.TEMPLATES['templates-admin_panel'] = "...";
84
+
85
+ Default behavior for ember-rails is to precompile handlebars templates only in production environment.
86
+ If you don't want this behavior you can turn it off in your application configuration block :
87
+
88
+ config.handlebars.precompile = false
89
+
32
90
  Bundle all templates together thanks to Sprockets,
33
91
  e.g create `app/assets/javascripts/templates/all.js` with:
34
92
 
@@ -38,6 +96,17 @@ Now a single line in the layout loads everything:
38
96
 
39
97
  <%= javascript_include_tag "templates/all" %>
40
98
 
99
+ If you use Slim or Haml templates, you can use handlebars filter :
100
+
101
+ handlebars:
102
+ {{view Ember.Button}}OK{{/view}}
103
+
104
+ It will be translated as :
105
+
106
+ <script type="text/x-handlebars">
107
+ {{view Ember.Button}}OK{{/view}}
108
+ </script>
109
+
41
110
  ## Note on Patches/Pull Requests
42
111
 
43
112
  1. Fork the project.
data/lib/ember-rails.rb CHANGED
@@ -1,14 +1 @@
1
- require 'sprockets'
2
- require 'sprockets/engines'
3
- require 'ember-rails/hjs_template'
4
-
5
- module EmberRails
6
- class Engine < Rails::Engine
7
- end
8
-
9
- # Registers the HandlebarsJS template engine so that
10
- # an asset file having the extension ".hjs" is processed
11
- # by the asset pipeline and converted to javascript code.
12
- Sprockets.register_engine '.hjs', HjsTemplate
13
- Sprockets.register_engine '.handlebars', HjsTemplate
14
- end
1
+ require 'ember_rails'
@@ -0,0 +1,11 @@
1
+ module Haml
2
+ module Filters
3
+ module Handlebars
4
+ include Base
5
+ def render_with_options(text, options)
6
+ type = "type=#{options[:attr_wrapper]}text/x-handlebars#{options[:attr_wrapper]}"
7
+ "<script #{type}>\n#{text.rstrip}\n</script>"
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ module Slim
2
+ class EmbeddedEngine
3
+ register :handlebars, TagEngine, :tag => :script, :attributes => { :type => 'text/x-handlebars' }
4
+ end
5
+ end
@@ -15,7 +15,7 @@ console.log = console.info = console.warn = console.error = function(){};
15
15
  var jQuery = window.jQuery = function() { return jQuery };
16
16
  jQuery.ready = function() { return jQuery };
17
17
  jQuery.inArray = function() { return jQuery };
18
- jQuery.jquery = "1.7.1";
18
+ jQuery.jquery = "1.7.2";
19
19
  var $ = jQuery;
20
20
 
21
21
  // Precompiler
@@ -0,0 +1,48 @@
1
+ require 'execjs'
2
+
3
+ module Ember
4
+ module Handlebars
5
+ class Source
6
+ class << self
7
+ def precompiler_path
8
+ File.expand_path(File.join(__FILE__, '../assets/ember-precompiler.js'))
9
+ end
10
+
11
+ def vendor_path
12
+ path = ::Rails.root.nil? ? '' : ::Rails.root.join('vendor/assets/javascripts/ember.js')
13
+
14
+ if !File.exists?(path)
15
+ path = File.expand_path(File.join(__FILE__, '../../../../vendor/assets/javascripts/ember.js'))
16
+ end
17
+ end
18
+
19
+ def path
20
+ @path ||= ENV['EMBER_SOURCE_PATH'] || vendor_path
21
+ end
22
+
23
+ def contents
24
+ @contents ||= [File.read(precompiler_path), File.read(path)].join("\n")
25
+ end
26
+
27
+ def handlebars_version
28
+ @handlebars_version ||= contents[/^Handlebars.VERSION = "([^"]*)"/, 1]
29
+ end
30
+
31
+ def ember_version
32
+ @ember_version ||= contents[/^Ember.VERSION = '([^']*)'/, 1]
33
+ end
34
+
35
+ def context
36
+ @context ||= ExecJS.compile(contents)
37
+ end
38
+ end
39
+ end
40
+
41
+ class << self
42
+ def compile(template)
43
+ template = template.read if template.respond_to?(:read)
44
+ Source.context.call('EmberRails.precompile', template)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,54 @@
1
+ require 'ember/handlebars/source'
2
+
3
+ module Ember
4
+ module Handlebars
5
+ class Template < Tilt::Template
6
+ def self.default_mime_type
7
+ 'application/javascript'
8
+ end
9
+
10
+ def prepare; end
11
+
12
+ def evaluate(scope, locals, &block)
13
+ template = mustache_to_handlebars(scope, data)
14
+
15
+ if configuration.precompile
16
+ func = Ember::Handlebars.compile(template)
17
+ "Ember.TEMPLATES[#{template_path(scope.logical_path).inspect}] = Ember.Handlebars.template(#{func});\n"
18
+ else
19
+ "Ember.TEMPLATES[#{template_path(scope.logical_path).inspect}] = Ember.Handlebars.compile(#{indent(template).inspect});\n"
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def mustache_to_handlebars(scope, template)
26
+ if scope.pathname.to_s =~ /\.mustache\.(handlebars|hjs)/
27
+ template.gsub(/\{\{(\w[^\}\}]+)\}\}/){ |x| "{{unbound #{$1}}}" }
28
+ else
29
+ template
30
+ end
31
+ end
32
+
33
+ def template_path(path)
34
+ root = configuration.templates_root
35
+
36
+ unless root.blank?
37
+ path.gsub!(/^#{Regexp.quote(root)}\/?/, '')
38
+ end
39
+
40
+ path = path.split('/')
41
+
42
+ path.join(configuration.templates_path_separator)
43
+ end
44
+
45
+ def configuration
46
+ ::Rails.configuration.handlebars
47
+ end
48
+
49
+ def indent(string)
50
+ string.gsub(/$(.)/m, "\\1 ").strip
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,7 @@
1
+ require 'ember/handlebars/source'
2
+
3
+ module Ember
4
+ module Handlebars
5
+ VERSION = Ember::Handlebars::Source.handlebars_version
6
+ end
7
+ end
@@ -0,0 +1,18 @@
1
+ require 'ember/handlebars/template'
2
+
3
+ module Ember
4
+ module Rails
5
+ class Engine < ::Rails::Engine
6
+ config.handlebars = ActiveSupport::OrderedOptions.new
7
+ config.handlebars.precompile = ::Rails.env.production?
8
+ config.handlebars.templates_root = nil
9
+ config.handlebars.templates_path_separator = '/'
10
+
11
+ initializer :setup_ember_rails, :group => :all do |app|
12
+ app.assets.register_engine '.handlebars', Ember::Handlebars::Template
13
+ app.assets.register_engine '.hbs', Ember::Handlebars::Template
14
+ app.assets.register_engine '.hjs', Ember::Handlebars::Template
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,5 @@
1
+ module Ember
2
+ module Rails
3
+ VERSION = '0.3.1'
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ require 'ember/handlebars/source'
2
+
3
+ module Ember
4
+ VERSION = Ember::Handlebars::Source.ember_version
5
+ end
@@ -0,0 +1,10 @@
1
+ require 'sprockets'
2
+ require 'sprockets/engines'
3
+
4
+ require 'ember/rails/engine'
5
+
6
+ require 'ember/version'
7
+ require 'ember/handlebars/version'
8
+
9
+ require 'ember/filters/slim' if defined? Slim
10
+ require 'ember/filters/haml' if defined? Haml
@@ -0,0 +1,39 @@
1
+ require 'generators/ember/generator_helpers'
2
+
3
+ module Ember
4
+ module Generators
5
+ class BootstrapGenerator < ::Rails::Generators::Base
6
+ include Ember::Generators::GeneratorHelpers
7
+
8
+ source_root File.expand_path("../../templates", __FILE__)
9
+
10
+ desc "Creates a default Ember.js folder layout in app/assets/javascripts/ember"
11
+
12
+ class_option :skip_git, :type => :boolean, :aliases => "-g", :default => false, :desc => "Skip Git keeps"
13
+
14
+ def inject_ember
15
+ application_file = "app/assets/javascripts/application.js"
16
+ if File.exists? application_file
17
+ inject_into_file(application_file, :before => "//= require_tree") do
18
+ dependencies = [
19
+ "//= require ember",
20
+ "//= require ember/#{application_name.underscore}"
21
+ ]
22
+ dependencies.join("\n").concat("\n")
23
+ end
24
+ end
25
+ end
26
+
27
+ def create_dir_layout
28
+ %W{models controllers views helpers templates}.each do |dir|
29
+ empty_directory "#{ember_path}/#{dir}"
30
+ create_file "#{ember_path}/#{dir}/.gitkeep" unless options[:skip_git]
31
+ end
32
+ end
33
+
34
+ def create_app_file
35
+ template "app.js", "#{ember_path}/#{application_name.underscore}.js"
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,21 @@
1
+ require 'ember/version'
2
+
3
+ module Ember
4
+ module Generators
5
+ class ControllerGenerator < ::Rails::Generators::NamedBase
6
+ source_root File.expand_path("../../templates", __FILE__)
7
+
8
+ desc "Creates a new Ember.js controller"
9
+ class_option :array, :type => :boolean, :default => false, :desc => "Create an Ember.ArrayController to represent multiple objects"
10
+
11
+ def create_controller_files
12
+ file_path = File.join('app/assets/javascripts/ember/controllers', class_path, "#{file_name}_controller.js")
13
+ if options.array?
14
+ template 'array_controller.js', file_path
15
+ else
16
+ template 'controller.js', file_path
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ module Ember
2
+ module Generators
3
+ module GeneratorHelpers
4
+
5
+ def ember_path
6
+ "app/assets/javascripts/ember"
7
+ end
8
+
9
+ def application_name
10
+ if defined?(::Rails) && ::Rails.application
11
+ ::Rails.application.class.name.split('::').first
12
+ else
13
+ "app"
14
+ end
15
+ end
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,92 @@
1
+ require 'ember/version'
2
+
3
+ module Ember
4
+ module Generators
5
+ class InstallGenerator < ::Rails::Generators::Base
6
+
7
+ EMBER_FILES = [ "ember.js", "ember-dev.js" ]
8
+ RUNTIME_FILES = [ "ember-runtime.js", "ember-runtime-dev.js" ]
9
+ ALL_FILES = [ *EMBER_FILES, *RUNTIME_FILES ]
10
+
11
+ desc "Install Ember.js into your vendor folder"
12
+ class_option :head, :type => :boolean, :default => false, :desc => "Download latest Ember.js from GitHub and copy it into your project"
13
+ class_option :runtime, :type => :boolean, :default => false, :desc => "Include the Ember.js runtime only"
14
+
15
+ def remove_ember
16
+ ALL_FILES.each do |name|
17
+ file = "vendor/assets/javascripts/#{name}"
18
+ remove_file file if File.exist?(file)
19
+ end
20
+ end
21
+
22
+ def copy_ember
23
+ if options.head?
24
+
25
+ git_root = File.expand_path "~/.ember"
26
+ gem_file = File.join git_root, "Gemfile"
27
+
28
+ # If it doesn't exist yet
29
+ unless File.exist?(git_root)
30
+ command = %{git clone git://github.com/emberjs/ember.js.git "#{git_root}"}
31
+ say_status("downloading", command, :green)
32
+
33
+ cmd command
34
+ else
35
+ Dir.chdir git_root do
36
+ command = "git fetch --force --quiet --tags && git reset HEAD --hard"
37
+ say_status("updating", command, :green)
38
+
39
+ cmd command
40
+ end
41
+ end
42
+
43
+ Dir.chdir git_root do
44
+ say_status("building", "bundle && bundle exec rake", :green)
45
+ Bundler.with_clean_env do
46
+ cmd "bundle --gemfile #{gem_file}"
47
+ cmd %{BUNDLE_GEMFILE="#{gem_file}" bundle exec rake}
48
+ end
49
+ end
50
+
51
+ self.class.source_root File.join(git_root, "dist")
52
+
53
+ ember_files.each do |name|
54
+ source_file = if name.match /-dev/
55
+ name.gsub /-dev/, '.debug'
56
+ else
57
+ name.gsub /.js/, '.prod.js'
58
+ end
59
+
60
+ copy_file source_file, "vendor/assets/javascripts/#{name}"
61
+ end
62
+
63
+ else
64
+
65
+ self.class.source_root File.expand_path('../../../../../vendor/assets/javascripts', __FILE__)
66
+ say_status("copying", "Ember.js (#{Ember::VERSION})", :green)
67
+
68
+ ember_files.each do |name|
69
+ copy_file name, "vendor/assets/javascripts/#{name}"
70
+ end
71
+
72
+ end
73
+ end
74
+
75
+ private
76
+
77
+ def ember_files
78
+ options.runtime? ? RUNTIME_FILES : EMBER_FILES
79
+ end
80
+
81
+ def cmd(command)
82
+ out = `#{command}`
83
+
84
+ if $?.exitstatus != 0
85
+ raise "Command error: command `#{command}` in directory #{Dir.pwd} has failed."
86
+ end
87
+ out
88
+ end
89
+
90
+ end
91
+ end
92
+ end