Hybrid View
-
15 Nov 2011 8:57 PM #1
Rails 3.1 & ExtJS 4 (MVC)
Rails 3.1 & ExtJS 4 (MVC)
Following Drew Neil's Sencha Touch example from SenchaCon 2011, I set out to create a basic Rails 3.1 application w/ an Ext JS 4 (MVC) front-end.
As Drew suggested, I structured the application like this.
All of the Ext JS code is written in CoffeeScript and managed by Rails' Asset Pipeline -- new in Rails 3.1.Code:app/ models/ views/ controllers/ assets/ javascripts/ app/ controllers/ models/ stores/ views/ vendor/ assets/ javascripts/ ext-4.0.7/
Just in case you're not familiar with Asset Pipeline...
<%= javascript_include_tag "application" %>
In development mode assets are served as separate files.
But in production mode assets are precompiled/minimized and served as static assets with a fingerprint.Code:<script src="/assets/app/app.js?body=1" type="text/javascript"></script> <script src="/assets/app/MyController.js?body=1" type="text/javascript"></script> <script src="/assets/app/MyView.js?body=1" type="text/javascript"></script>
In development mode, life is good -- the helper includes ext.js and app.js. From there, Ext.Loader loads framework & and application classes as needed.Code:<script src="/assets/application-908e25f4bf641868d8683022a5b62f54.js" type="text/javascript"></script>
But in production mode, the helper includes ext.js and all application files (minimized with fingerprint). For some reason, Ext.Loader still tries to load classes dynamically, even though they're included in the minimized file. If I disable Ext.Loader, the "requires" properties in my views complain.
Along the same lines, using ext.js in production is probably a bad idea too. It sounds like I need to tie into the assets:precompile task, using Sencha Tools to build the library.
Any other Rails 3.1 users out there?
Thanks!
-
20 Nov 2011 1:48 PM #2
I ended up just writing a Rake task, since I'm a Ruby n00b.
Let me know if you come up with something better.
Thanks,
J
Code:require 'coffee-script' require 'find' namespace :sencha do desc 'Compiles Ext JS application CoffeeScript and performs JSB3 build and create.' task :compile do tmp_js = "#{File.dirname(__FILE__)}/../../tmp/sencha" src_app = "#{File.dirname(__FILE__)}/../../app/assets/javascripts/app" tmp_app = File.expand_path("#{tmp_js}/assets/app") FileUtils.rm_rf tmp_js Find.find(src_app) do |f| if File.extname(f) == '.coffee' js_file = "#{tmp_app}#{f.gsub(src_app, "")}".chomp('.coffee') js_dir = File.dirname(js_file) js = CoffeeScript.compile File.read(f) FileUtils.mkdir_p js_dir if !File.exists?(js_dir) open js_file, 'w' do |f| f.puts js end end end # Moves app.js to top-level. FileUtils.mv "#{tmp_app}/app.js", "#{tmp_js}/app.js" # Copies template app.html needed for Sencha SDK Tools. FileUtils.cp "#{File.dirname(__FILE__)}/../assets/app.html", "#{tmp_js}/app.html" ## Create Ext JS library symlink. ext = "#{File.dirname(__FILE__)}/../../public/ext" ext_symlink = "#{tmp_js}/ext" File.symlink(ext, ext_symlink) # Create JSB3 file for Docs app system("sencha", "create", "jsb", "-a", "#{tmp_js}/app.html", "-p", "#{tmp_js}/app.jsb3") # Update JSB3 meta-data. jsb3 = File.read("#{tmp_js}/app.jsb3") jsb3 = jsb3.gsub("Project Name", "My Project") jsb3 = jsb3.gsub("Company Name", "My Company") File.open("#{tmp_js}/app.jsb3", "w") do |f| f.write jsb3 end system("sencha", "build", "-p", "#{tmp_js}/app.jsb3", "-d", tmp_js) end end
-
8 Jun 2012 9:11 AM #3
Some fixes
Some fixes
Hey, thanks for that code, I made some changes to make it work on my environment:
Code:require 'coffee-script' require 'find' namespace :sencha do desc 'Compiles Ext JS application CoffeeScript and performs JSB3 build and create.' task :compile do tmp_js = "#{File.dirname(__FILE__)}/../../tmp/sencha" src_app = "#{File.dirname(__FILE__)}/../../app/assets/javascripts" tmp_app = File.expand_path("#{tmp_js}/assets") FileUtils.rm_rf tmp_js Find.find(src_app) do |f| if File.extname(f) == '.coffee' js_file = "#{tmp_app}#{f.gsub(src_app, "")}".chomp('.coffee') js_dir = File.dirname(js_file) js = CoffeeScript.compile File.read(f) FileUtils.mkdir_p js_dir if !File.exists?(js_dir) open js_file, 'w' do |f| f.puts js end end end # Moves app.js to top-level. FileUtils.mv "#{tmp_app}/app.js", "#{tmp_js}/app.js" ## Create Ext JS library symlink. ext = "#{File.dirname(__FILE__)}/../../vendor/assets/javascripts/ext/" ext_symlink = "#{tmp_app}/ext" File.symlink(ext, ext_symlink) # Create JSB3 file for Docs app # requires the server up and running system("sencha", "create", "jsb", "-a", "http://localhost:3000", "-p", "#{tmp_js}/app.jsb3") # Update JSB3 meta-data. jsb3 = File.read("#{tmp_js}/app.jsb3") jsb3 = jsb3.gsub("Project Name", "My Project") jsb3 = jsb3.gsub("Company Name", "My Company") File.open("#{tmp_js}/app.jsb3", "w") do |f| f.write jsb3 end system("sencha", "build", "-p", "#{tmp_js}/app.jsb3", "-d", tmp_js) FileUtils.mv "#{tmp_js}/all-classes.js", "#{File.dirname(__FILE__)}/../../app/assets/javascripts/all-classes.js" FileUtils.mv "#{tmp_js}/app-all.js", "#{File.dirname(__FILE__)}/../../app/assets/javascripts/app-all.js" end end
-
31 Jan 2013 2:23 PM #4
Hi atwoodjw,
I'm attempting to do something similar but running into trouble with how I can add extjs to the pipeline and still have dynamic loading work correctly. Seeing a lot of Ext.Loader is not enabled when I attempt to dynamically load classes like:
as a result of adding mixins like Draggable:Code:Error: Ext.Loader is not enabled, so dependencies cannot be resolved dynamically. Missing required class: Ext.util.Draggable
Error: Ext.Loader is not enabled, so dependencies cannot be resolved dynamically. Missing required class: Keystone.MyWindow[IMG]chrome://firebug/content/blank.gif[/IMG] slice.call( docElem.childNodes, 0 )[0].nodeType;application.js (line 114738) [IMG]chrome://firebug/content/blank.gif[/IMG] 1) ? "es" : "") + ": " + classNames.join(', '));" class="errorSourceCode ">... required class" + ((classNames.length > 1) ? "es" : "") + ": " + classNames.joi...
Code:Ext.define('Keystone.MyWindow', { extend: 'Ext.Panel', requires: ['Ext.util.MixedCollection'], mixins: { draggable: 'Ext.util.Draggable' } });
Any chance you could share how to hooked extjs into ruby pipeline with the structure you listed above?
Thanks,
-M


Reply With Quote