frontin 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -0,0 +1,10 @@
1
+ gemfiles:
2
+ - Gemfile
3
+ language: ruby
4
+ rvm:
5
+ - 1.9.2
6
+ - 1.9.3
7
+ language: node_js
8
+ node_js:
9
+ - 0.6
10
+ - 0.7
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in frontin.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Collin Schaafsma
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.
@@ -0,0 +1,98 @@
1
+ # Frontin
2
+
3
+ Give your frontend code some respect in Rails. Don't even front.
4
+
5
+ Frontin adds middleware to allow you to develop your frontend code in `Rails/root/frontend` and serve it in development mode.
6
+ Frontin takes any request for `assets/**js, assets/**css` or `app/**js` and maps those requests to `Rails/root/frontend` in development mode.
7
+ It also provides generators to easily setup the backbone-boilerplate using grunt so that you can easily build to `public/assets/` for production. Keeping your frontend source out of `public/`.
8
+
9
+ **Frontin is NOT designed to work with the asset pipeline.**
10
+ If that sounds pretty awesome to you, and you don't want your frontend code to get all mixed up in the Rails framework then frontin might be the kitties pj's for you.
11
+
12
+ Learn more about grunt https://github.com/cowboy/grunt, and the backbone-boilerplate https://github.com/backbone-boilerplate/grunt-bbb
13
+
14
+ [![Build Status](https://secure.travis-ci.org/collinschaafsma/frontin.png)](http://travis-ci.org/collinschaafsma/frontin)
15
+
16
+ Testing against: node 0.6, 0.7 / Ruby MRI 1.9.2, 1.9.3
17
+
18
+ ## Why
19
+
20
+ Frontin was developed out of frustration with the asset pipeline. Instead it uses grunt to compile frontend code to the `public/` directory where a web server like
21
+ nginx can make quick work out of it. Grunt gives you all the controll in the world over building your frontend code. We feel it's the right tool for the job and prefer to
22
+ use the Rails framework for what it's best at.
23
+
24
+
25
+ ## Installation
26
+
27
+ Add this line to your application's Gemfile:
28
+
29
+ gem 'frontin', :group => :development
30
+
31
+ And then execute:
32
+
33
+ $ bundle
34
+
35
+ Or install it yourself as:
36
+
37
+ $ gem install frontin
38
+
39
+ ## Dependencies
40
+
41
+ * Ruby ~> 1.9.2
42
+ * Node ~> 0.6
43
+
44
+ ## Usage
45
+
46
+ Frontin provides several generators to make life easy.
47
+
48
+ rails g frontin:install
49
+
50
+ This adds the `frontend/` directory to the root of your Rails project where you can start writing your frontend code.
51
+ In addition the node npm package grunt will be installed for building your assets with a sensible config.
52
+
53
+ Frontin also makes it easy to install the backbone-boilerplate into your `frontend` directory using
54
+ the node npm package bbb. If your looking to build your frontend using Backbone we highly suggest you give the backbone-boilerplate a spin.
55
+
56
+ rails g frontin:bbb
57
+
58
+ ## Disabling the asset pipeline
59
+
60
+ It's highly recommended that if you use frontin to disable the asset pipeline to avoid
61
+ any conflicts. Besides, at this point you don't need it anymore.
62
+
63
+ ### Greenfield project
64
+
65
+ rails new my_project -S
66
+
67
+ ### Existing project
68
+
69
+ config/application.rb
70
+
71
+ # comment out
72
+ require "sprockets/railtie"
73
+
74
+ # disable the asset pipeline
75
+ config.assets.enabled = false
76
+
77
+ # optionally disable the generators
78
+ config.generators.stylesheets = false
79
+ config.generators.javascripts = false
80
+
81
+ ## Example Rails app
82
+
83
+ https://github.com/collinschaafsma/frontin_rails_example
84
+
85
+ ## Thanks
86
+
87
+ * cowboy (Ben Alman) for writing grunt. https://github.com/cowboy/grunt
88
+ * tbranyen (Tim Branyen) for writing backbone-boilerplate. https://github.com/backbone-boilerplate/grunt-bbb
89
+ * wookiehangover (Sam Breed) and nicovalencia (Nico Valencia) for their inspiration and smarts
90
+ * All the other contributers to the projects that make frontin possible
91
+
92
+ ## Contributing
93
+
94
+ 1. Fork it
95
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
96
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
97
+ 4. Push to the branch (`git push origin my-new-feature`)
98
+ 5. Create new Pull Request
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require "rake/testtask"
4
+
5
+ task :default => :test
6
+
7
+ Rake::TestTask.new(:test) do |t|
8
+ t.libs << 'lib'
9
+ t.libs << 'test'
10
+ t.pattern = 'test/**/*_test.rb'
11
+ t.verbose = true
12
+ end
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/frontin/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Collin Schaafsma"]
6
+ gem.email = ["collin@quickleft.com"]
7
+ gem.description = %q{Give your frontend code some respect in Rails! Don't even front.}
8
+ gem.summary = %q{Frontin adds middleware to allow you to develop your frontend code in Rails/root/frontend. It also provides generators to easily setup the backbone boilerplate using Grunt so that you can easily build to public/ for production.}
9
+ gem.homepage = "https://github.com/collinschaafsma/frontin"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "frontin"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Frontin::VERSION
17
+ gem.rubyforge_project = "frontin"
18
+
19
+ gem.add_dependency("rails", "~> 3.2.0")
20
+ end
@@ -0,0 +1,2 @@
1
+ require "frontin/version"
2
+ require "frontin/middleware"
@@ -0,0 +1,24 @@
1
+ module Frontin
2
+ class Middleware
3
+ def initialize(app, options={})
4
+ @app = app
5
+ @paths = options[:paths]
6
+ root = options[:root] || "frontend"
7
+ @file_server = Rack::File.new(root)
8
+ end
9
+
10
+ def routable?(path)
11
+ @paths.kind_of?(Array) && @paths.any? { |p| path.index(p) == 0 }
12
+ end
13
+
14
+ def call(env)
15
+ path = env["PATH_INFO"]
16
+
17
+ if routable?(path)
18
+ @file_server.call(env)
19
+ else
20
+ @app.call(env)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,29 @@
1
+ module Frontin
2
+ module Util
3
+ def run_command(cmd)
4
+ output = nil
5
+ IO.popen(cmd) { |f| output = f.read }
6
+ output
7
+ end
8
+
9
+ def binary_installed?(binary)
10
+ if File.executable? binary
11
+ true
12
+ else
13
+ # Look through their $PATH env variable to see if we can find it
14
+ path = ENV['PATH'].split(File::PATH_SEPARATOR).find do |p|
15
+ full_path = File.join(p, binary)
16
+ File.executable?(full_path) && File.file?(full_path)
17
+ end
18
+ path && File.expand_path(binary, path)
19
+ end
20
+ end
21
+
22
+ def directory_trees
23
+ %w(frontend frontend/app frontend/assets frontend/assets/css
24
+ frontend/assets/js frontend/assets/js/libs frontend/test
25
+ public/assets public/assets/js/debug public/assets/js/release
26
+ public/assets/js/libs public/assets/css/release public/assets/img)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,3 @@
1
+ module Frontin
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,51 @@
1
+ require 'rails'
2
+ require 'frontin/util'
3
+
4
+ module Frontin
5
+ module Generators
6
+ class Base < Rails::Generators::Base
7
+ include Frontin::Util
8
+
9
+ def build_directories
10
+ say("Setting up a sensible directory structure in frontend/ and public/ to work with grunt config")
11
+
12
+ directory_trees.each do |path|
13
+ empty_directory path
14
+ end
15
+ end
16
+
17
+ # We could do this easily with a railtie using
18
+ # initializer "frontin.insert_middleware", however this gives the
19
+ # developer the ability to change the Middleware paramaters
20
+ def add_middleware_to_development_env
21
+ application(nil, :env => "development") do
22
+ "config.middleware.use(Frontin::Middleware, :paths => ['/assets', '/app'], :root => 'frontend')"
23
+ end
24
+ end
25
+
26
+ def install_grunt
27
+ if binary_installed?('npm')
28
+ if binary_installed?('grunt')
29
+ say("grunt detected on your system")
30
+ else
31
+ say("Invoking: npm install -g grunt")
32
+ run_command('npm install -g grunt')
33
+ end
34
+ else
35
+ say("We couldn't find npm on your system. Skipping grunt install.")
36
+ say("Install npm with: curl http://npmjs.org/install.sh | sh")
37
+ end
38
+ end
39
+
40
+ private
41
+ def install_grunt_config
42
+ if Rails.env.test?
43
+ create_file("frontend/grunt.js")
44
+ else
45
+ say("Installing sensible grunt configuration for your environment in frontend/ directory.")
46
+ get("https://raw.github.com/gist/2348189/3aa8f76e2f2d2aa47a803314b14c99396baf0321/rails-grunt.js", "frontend/grunt.js")
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,49 @@
1
+ require 'pty'
2
+ require 'expect'
3
+ require 'generators/base'
4
+
5
+ module Frontin
6
+ module Generators
7
+ class BbbGenerator < Frontin::Generators::Base
8
+
9
+ desc "Creates the frontend directory in the root of your Rails \n
10
+ app and installs grunt with the bbb plugin and a sensible config and directory structure."
11
+
12
+ def install_bbb
13
+ if binary_installed?('npm')
14
+ if binary_installed?('bbb')
15
+ say("bbb detected on your system")
16
+ else
17
+ say("Invoking: npm install -g bbb")
18
+ run_command('npm install -g bbb')
19
+ end
20
+ else
21
+ say("We couldn't find npm on your system. Skipping bbb install.")
22
+ say("Install npm with: curl http://npmjs.org/install.sh | sh")
23
+ end
24
+ end
25
+
26
+ def bbb_init
27
+ if binary_installed?('bbb')
28
+ say("Invoking: bbb init")
29
+ # Make sure this can run in test mode
30
+ bbb_namespace = Rails.env.test? ? 'myapp' : ask("Backbone project namespace?")
31
+ cmd = Rails.env.test? ? "cd test/generators/tmp/frontend; bbb init" : 'cd frontend; bbb init'
32
+
33
+ STDOUT.sync = true
34
+ STDERR.sync = true
35
+ $expect_verbose = false
36
+ PTY.spawn(cmd) do |output,input,pid|
37
+ input.sync = true
38
+ output.expect(/Project namespace/) { input.puts bbb_namespace }
39
+ output.expect(/Do you need to make any changes to the above before continuing/) { input.puts "N" }
40
+ end
41
+ end
42
+ end
43
+
44
+ def install_grunt_config
45
+ super
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,15 @@
1
+ require 'generators/base'
2
+
3
+ module Frontin
4
+ module Generators
5
+ class InstallGenerator < Frontin::Generators::Base
6
+
7
+ desc "Creates the frontend directory in the root of your Rails \n
8
+ app and installs grunt with a sensible config and directory structure."
9
+
10
+ def install_grunt_config
11
+ super
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1 @@
1
+ var fancy = "fancy";
@@ -0,0 +1,47 @@
1
+ require 'test_helper'
2
+ require 'rails/generators/test_case'
3
+ require 'generators/frontin/bbb_generator'
4
+
5
+ class BbbGeneratorTest < Rails::Generators::TestCase
6
+ include Frontin::Util
7
+
8
+ tests Frontin::Generators::BbbGenerator
9
+ destination File.expand_path("../tmp", File.dirname(__FILE__))
10
+
11
+ setup do
12
+ prepare_destination
13
+ stage_development_env
14
+ end
15
+
16
+ def stage_development_env
17
+ FileUtils.mkdir_p File.dirname(development_env)
18
+ File.open(development_env, 'w') {|f| f.write("FrontinTest::Application.configure do\n\nend") }
19
+ end
20
+
21
+ def development_env
22
+ @development_env ||= File.expand_path("config/environments/development.rb", destination_root)
23
+ end
24
+
25
+ def test_bbb_generator
26
+ run_generator
27
+
28
+ # This feels bad man, but we need to wait for the bbb init to finsh in the other
29
+ # process before we start looking for stuff it generated. At this point we don't
30
+ # mock this out because we want to know if things thange in bbb init.
31
+ sleep 1
32
+
33
+ directory_trees.each do |path|
34
+ assert_directory path
35
+ end
36
+
37
+ %w(frontend/grunt.js frontend/app/myapp.js frontend/app/main.js
38
+ frontend/app/config.js frontend/app/modules/example.js
39
+ frontend/app/templates/example.html).each do |file|
40
+ assert_file file
41
+ end
42
+
43
+ contents = File.read(development_env)
44
+ assert_match(/config.middleware.use\(Frontin::Middleware, :paths => \['\/assets', '\/app'\], :root => 'frontend'\)/m, contents)
45
+ end
46
+ end
47
+
@@ -0,0 +1,37 @@
1
+ require 'test_helper'
2
+ require 'rails/generators/test_case'
3
+ require 'generators/frontin/install_generator'
4
+
5
+ class InstallGeneratorTest < Rails::Generators::TestCase
6
+ include Frontin::Util
7
+
8
+ tests Frontin::Generators::InstallGenerator
9
+ destination File.expand_path("../tmp", File.dirname(__FILE__))
10
+
11
+ setup do
12
+ prepare_destination
13
+ stage_development_env
14
+ end
15
+
16
+ def stage_development_env
17
+ FileUtils.mkdir_p File.dirname(development_env)
18
+ File.open(development_env, 'w') {|f| f.write("FrontinTest::Application.configure do\n\nend") }
19
+ end
20
+
21
+ def development_env
22
+ @development_env ||= File.expand_path("config/environments/development.rb", destination_root)
23
+ end
24
+
25
+ def test_install_generator
26
+ run_generator
27
+
28
+ directory_trees.each do |path|
29
+ assert_directory path
30
+ end
31
+
32
+ assert_file 'frontend/grunt.js'
33
+
34
+ contents = File.read(development_env)
35
+ assert_match(/config.middleware.use\(Frontin::Middleware, :paths => \['\/assets', '\/app'\], :root => 'frontend'\)/m, contents)
36
+ end
37
+ end
@@ -0,0 +1,35 @@
1
+ require 'rack/test'
2
+ require 'rack/mock'
3
+ require 'frontin'
4
+
5
+ class MiddlewareTest < Test::Unit::TestCase
6
+ include Rack::Test::Methods
7
+
8
+ def default_app
9
+ lambda { |env|
10
+ headers = {'Content-Type' => "text/html"}
11
+ [200, headers, ["I'm the default app"]]
12
+ }
13
+ end
14
+
15
+ def app
16
+ @app ||= Frontin::Middleware.new(default_app, { :paths => ['/assets'], :root => File.expand_path(File.dirname(__FILE__)) })
17
+ end
18
+
19
+ def test_files_in_the_path_are_served
20
+ response = get("/assets/test.js")
21
+ assert_equal response.status, 200
22
+ assert_match /fancy/, response.body
23
+ end
24
+
25
+ def test_missing_files_in_the_path
26
+ response = get("/assets/not-here.js")
27
+ assert_equal response.status, 404
28
+ end
29
+
30
+ def test_request_without_the_path_falls_out
31
+ response = get("/not-assets/test.js")
32
+ assert_equal response.status, 200
33
+ assert_match /I'm the default app/, response.body
34
+ end
35
+ end
@@ -0,0 +1,2 @@
1
+ ENV["RAILS_ENV"] = "test"
2
+ require 'test/unit'
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: frontin
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Collin Schaafsma
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-11 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: &70360032997540 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 3.2.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70360032997540
25
+ description: Give your frontend code some respect in Rails! Don't even front.
26
+ email:
27
+ - collin@quickleft.com
28
+ executables: []
29
+ extensions: []
30
+ extra_rdoc_files: []
31
+ files:
32
+ - .gitignore
33
+ - .travis.yml
34
+ - Gemfile
35
+ - LICENSE
36
+ - README.md
37
+ - Rakefile
38
+ - frontin.gemspec
39
+ - lib/frontin.rb
40
+ - lib/frontin/middleware.rb
41
+ - lib/frontin/util.rb
42
+ - lib/frontin/version.rb
43
+ - lib/generators/base.rb
44
+ - lib/generators/frontin/bbb_generator.rb
45
+ - lib/generators/frontin/install_generator.rb
46
+ - test/assets/test.js
47
+ - test/generators/frontin/bbb_generator_test.rb
48
+ - test/generators/frontin/install_generator_test.rb
49
+ - test/middleware_test.rb
50
+ - test/test_helper.rb
51
+ homepage: https://github.com/collinschaafsma/frontin
52
+ licenses: []
53
+ post_install_message:
54
+ rdoc_options: []
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ requirements: []
70
+ rubyforge_project: frontin
71
+ rubygems_version: 1.8.11
72
+ signing_key:
73
+ specification_version: 3
74
+ summary: Frontin adds middleware to allow you to develop your frontend code in Rails/root/frontend.
75
+ It also provides generators to easily setup the backbone boilerplate using Grunt
76
+ so that you can easily build to public/ for production.
77
+ test_files:
78
+ - test/assets/test.js
79
+ - test/generators/frontin/bbb_generator_test.rb
80
+ - test/generators/frontin/install_generator_test.rb
81
+ - test/middleware_test.rb
82
+ - test/test_helper.rb