jagger 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ # -*- ruby -*-
2
+ source 'http://rubygems.org'
3
+ gemspec
4
+
5
+ gem 'sprockets'
6
+ gem 'sinatra'
7
+ gem 'rack'
8
+ gem 'rake'
9
+
10
+ group :development do
11
+ gem 'rspec'
12
+ gem 'mocha'
13
+ gem 'rack-test'
14
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,54 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ jagger (0.0.1)
5
+ rack
6
+ sinatra
7
+ sprockets
8
+
9
+ GEM
10
+ remote: http://rubygems.org/
11
+ specs:
12
+ diff-lcs (1.1.3)
13
+ hike (1.2.1)
14
+ metaclass (0.0.1)
15
+ mocha (0.10.5)
16
+ metaclass (~> 0.0.1)
17
+ multi_json (1.2.0)
18
+ rack (1.4.1)
19
+ rack-protection (1.2.0)
20
+ rack
21
+ rack-test (0.6.1)
22
+ rack (>= 1.0)
23
+ rake (0.9.2.2)
24
+ rspec (2.9.0)
25
+ rspec-core (~> 2.9.0)
26
+ rspec-expectations (~> 2.9.0)
27
+ rspec-mocks (~> 2.9.0)
28
+ rspec-core (2.9.0)
29
+ rspec-expectations (2.9.0)
30
+ diff-lcs (~> 1.1.3)
31
+ rspec-mocks (2.9.0)
32
+ sinatra (1.3.2)
33
+ rack (~> 1.3, >= 1.3.6)
34
+ rack-protection (~> 1.2)
35
+ tilt (~> 1.3, >= 1.3.3)
36
+ sprockets (2.4.0)
37
+ hike (~> 1.2)
38
+ multi_json (~> 1.0)
39
+ rack (~> 1.0)
40
+ tilt (~> 1.1, != 1.3.0)
41
+ tilt (1.3.3)
42
+
43
+ PLATFORMS
44
+ ruby
45
+
46
+ DEPENDENCIES
47
+ jagger!
48
+ mocha
49
+ rack
50
+ rack-test
51
+ rake
52
+ rspec
53
+ sinatra
54
+ sprockets
data/README.md ADDED
@@ -0,0 +1,104 @@
1
+ # Jagger is your frontman!
2
+
3
+ ![Mick Jagger](http://i.imgur.com/xW8XW.jpg)
4
+
5
+ Jagger is a frontman for your frontend application. Mixing frontend and
6
+ backend in one Rails applicaiton sucks, let's say it stright! We have
7
+ bunch of unrelated things mixed together, why? With Jagger you gonna
8
+ rock your frontend application management!
9
+
10
+ ## Philosophy
11
+
12
+ Backend and frontend of web application are in fact two different
13
+ applications, ususaly utilizing different languages and tools.
14
+ The main point of Jagger's philosophy is to split backend and
15
+ frontend into separated applications.
16
+
17
+ **Frontend** - ususally a JavaScript (eg. Backbone) application
18
+ with set of templates and GUI integration tests.
19
+
20
+ **Backend** - an app written with Sinatra, Rails or whatever else,
21
+ which provices an unified API required by the _Frontend_ app.
22
+
23
+ ## Controversy
24
+
25
+ _Are you insane? I have to write two apps instead of one, and everytime
26
+ I change something in the backend then I have to adjust frontend one?_
27
+
28
+ Um... Well, you do the same every single day. You change something in
29
+ your Rails model, then you going to the view and editing it, then you
30
+ going to the (Java|Coffee)Script part and keep adjusting to the changes
31
+ you made in the model.
32
+
33
+ **The biggest advantages of this layout**:
34
+
35
+ * Frontend people can work on frontend without dealing with overwhelming
36
+ backend code.
37
+ * Backend people may don't give a shit about frontend stuff.
38
+ * Application has unified API which can be reused further by other
39
+ views (iPhone or Android app, external consumers, etc.)
40
+ * Frontend may be written totally without thinking about the databases
41
+ and other delivery methods. It can focus only on the look and feel
42
+ by accessing all the data from mocks.
43
+ * It's briliant for the designers, thus they don't need to install all
44
+ the development stuff (usually, you have to install it for them).
45
+ * After all, you can serve everything as one application anyway...
46
+
47
+ **This layout also have disadvantages**:
48
+
49
+ * It has no server side generated views - so it is not well suitable
50
+ for the applications which tend to be crawlable eg. by Googlebot.
51
+ * It requires good communication in your team in case of defining
52
+ and maintaining the API. Hmm, if you improve your communication thanks
53
+ to this then it may be considered as an advantage.
54
+ * It forces you to think different and abstract... some people don't like
55
+ this :P
56
+
57
+ ## Installation
58
+
59
+ Like always, via rubygems:
60
+
61
+ $ gem install jagger
62
+
63
+ Or by adding dependency to your gemfile:
64
+
65
+ gem 'jagger'
66
+
67
+ ## Usage
68
+
69
+ Jagger comes with set of conventions to make your life easier. Here's
70
+ the frontend app directory structure:
71
+
72
+ + your_frontend/
73
+ |-- lib/ - External, static JavaScript libraries (eg. jQuery).
74
+ |-+ src/ - Dynamic sources.
75
+ | |-- styles/ - Your CSS, SASS, LESS or God knows what styles.
76
+ | |-- sprites/ - Source images for your sprites.
77
+ | |-- main/ - Your application's (Java|Coffee)Script files.
78
+ | |-- test/ - Your GUI test files (i.a. QUnit, Selenium).
79
+ |-- static/ - Static images, javascripts, fonts, etc.
80
+ |-- templates/ - All the template files.
81
+ |-- config.ru - Rack configuration.
82
+
83
+ You can set ther up a Gemfile with `jagger` listed as a dependency and
84
+ add this code to `config.ru`
85
+
86
+ # *snip*
87
+
88
+ run Jagger::Builder.new
89
+
90
+ If you want to mount it within your backend application, no problem!
91
+ You can do it this way:
92
+
93
+ # *snip*
94
+
95
+ map '/api' do
96
+ run MyBackendApp.new
97
+ end
98
+
99
+ map '/' do
100
+ run Jagger::Builder.new
101
+ end
102
+
103
+ You can serve your frontend app simply like any other rack app using
104
+ `thin`, `rackup` or whatever you want.
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ # -*- ruby -*-
2
+ require 'rubygems'
3
+ require 'bundler/setup'
4
+ require 'rake'
5
+
6
+ require 'rspec/core/rake_task'
7
+ RSpec::Core::RakeTask.new(:spec) do |t|
8
+ t.rspec_opts = ENV['RSPEC_OPTS']
9
+ end
10
+
11
+ task :test => :spec
12
+ task :default => :test
13
+
14
+ desc "Opens console with loaded env."
15
+ task :console do
16
+ $LOAD_PATH.unshift("./lib")
17
+ require 'jagger'
18
+ require 'irb'
19
+ ARGV.clear
20
+ IRB.start
21
+ end
data/jagger.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # -*- ruby -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'jagger'
5
+ s.rubyforge_project = 'jagger'
6
+ s.version = '0.0.1'
7
+
8
+ s.authors = ['Chris Kowalik']
9
+ s.email = ['chris@nu7hat.ch']
10
+ s.homepage = 'http://github.com/nu7hatch/jagger'
11
+ s.summary = 'Jagger is your frontman!'
12
+ s.description = <<-END
13
+ Jagger an frontman for your applications. It serves dynamically
14
+ generated assets via sprockets pipeline, static files and all the
15
+ templates. All that makes your life much easier.'
16
+ END
17
+
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- {spec}/*`.split("\n")
20
+ s.require_paths = ['lib']
21
+
22
+ s.add_dependency 'sprockets'
23
+ s.add_dependency 'sinatra'
24
+ s.add_dependency 'rack'
25
+ s.add_development_dependency 'rspec'
26
+ s.add_development_dependency 'mocha'
27
+ end
data/lib/jagger.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'jagger/assets'
2
+ require 'jagger/app'
3
+ require 'jagger/builder'
data/lib/jagger/app.rb ADDED
@@ -0,0 +1,24 @@
1
+ require 'sinatra/base'
2
+
3
+ module Jagger
4
+ # Internal: App is a Sinatra application used to serve static
5
+ # files and index, and to keep Jagger's configuration.
6
+ class App < Sinatra::Application
7
+ set :asset_paths, %w(src/main/ src/test/ src/look/ lib/)
8
+ set :public_folder, 'static'
9
+ set :views, 'templates'
10
+ set :layout, false
11
+
12
+ helpers do
13
+ # Public: Returns whether requests' mocks should be skipped
14
+ # or not.
15
+ def mock_requests?
16
+ ENV['USE_REAL_REQUESTS'].to_i == 0
17
+ end
18
+ end
19
+
20
+ get '/' do
21
+ erb :index
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,29 @@
1
+ require 'sprockets'
2
+
3
+ module Jagger
4
+ # Internal: Assets serves all dynamically generated asssets
5
+ # through sprockets pipeline.
6
+ class Assets
7
+ # Public: Constructor. Initializes sprockets environment.
8
+ def initialize
9
+ @sprockets = Sprockets::Environment.new
10
+ end
11
+
12
+ # Public: Registers given load paths in sprockets' env.
13
+ #
14
+ # dir - The Array of dirs to register
15
+ #
16
+ def append_paths(dirs = [])
17
+ dirs.each { |dir| @sprockets.append_path(dir) }
18
+ end
19
+
20
+ # Public: Serves assets
21
+ #
22
+ # env - The Hash HTTP environment.
23
+ #
24
+ # Returns HTTP response data.
25
+ def call(env)
26
+ @sprockets.call(env)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,53 @@
1
+ module Jagger
2
+ # Public: Builder creates rack compatible application which gathers
3
+ # and serves static sinatra app and sprockets pipeline together.
4
+ #
5
+ # Example
6
+ #
7
+ # app = Jagger::Builder.new do
8
+ # set :asset_paths, %w(src/main/ src/test/ src/look/ lib/)
9
+ # set :views, 'templates'
10
+ # set :public_folder, 'static'
11
+ # end
12
+ #
13
+ # run app
14
+ #
15
+ # Configuration above is the default one, so in most of cases only
16
+ # the following declaration will be enough:
17
+ #
18
+ # run Jagger::Builder.new
19
+ #
20
+ class Builder
21
+ # Public: Constructor. Initializes application and the assets
22
+ # pipeline. Passed block accepts custom configuration.
23
+ def initialize(&block)
24
+ app.instance_eval(&block) if block_given?
25
+ assets.append_paths(app.asset_paths)
26
+ end
27
+
28
+ # Internal: Sinatra application used to serve static files and
29
+ # index page.
30
+ def app
31
+ @app ||= App
32
+ end
33
+
34
+ # Internal: Assets pipeline environment.
35
+ def assets
36
+ @assets ||= Assets.new
37
+ end
38
+
39
+ # Public: Serves the application and assets pipeline together
40
+ # as one rack application.
41
+ #
42
+ # env - The Hash with request environment.
43
+ #
44
+ def call(env)
45
+ map = {
46
+ '/assets' => assets,
47
+ '/' => app.new,
48
+ }
49
+ router = Rack::URLMap.new(map)
50
+ router.call(env)
51
+ end
52
+ end
53
+ end
data/spec/app_spec.rb ADDED
@@ -0,0 +1,36 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ describe Jagger::App do
4
+ describe "#mock_requests?" do
5
+ it "returns true when requests should be mocked" do
6
+ #ENV['USE_REAL_REQUESTS'] = '0'
7
+ #subject.should be_mock_requests
8
+ end
9
+
10
+ it "returns false when requests should not be mocked" do
11
+ #ENV['USE_REAL_REQUESTS'] = '1'
12
+ #subject.should_not be_mock_requests
13
+ end
14
+ end
15
+
16
+ it "has proper default configuration" do
17
+ app = Jagger::App
18
+ app.asset_paths == %w(src/main/ src/test/ src/look/ lib/)
19
+ app.public_folder.should == 'static'
20
+ app.views.should == 'templates'
21
+ app.layout.should_not be
22
+ end
23
+
24
+ describe "integration" do
25
+ let :app do
26
+ base = Class.new(Jagger::App)
27
+ base.set :views, File.expand_path('../fixtures/templates/', __FILE__)
28
+ base.new
29
+ end
30
+
31
+ it "serves index page" do
32
+ get '/'
33
+ last_response.body.should == 'Hello Jagger!'
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,21 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ describe Jagger::Assets do
4
+ describe "#append_paths" do
5
+ it "registers specified paths under the sprockets instance" do
6
+ Sprockets::Environment.any_instance.tap do |env|
7
+ env.expects(:append_path).with('foo/')
8
+ env.expects(:append_path).with('bar/')
9
+ end
10
+ subject.append_paths(%w(foo/ bar/))
11
+ end
12
+ end
13
+
14
+ describe "#call" do
15
+ it "serves assets via sprockets pipeline" do
16
+ env = { :hello => 'world' }
17
+ Sprockets::Environment.any_instance.expects(:call).with(env)
18
+ subject.call(env)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,35 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ describe Jagger::Builder do
4
+ describe "initialization" do
5
+ it "configures sinatra app" do
6
+ app = Jagger::Builder.new { set :public_folder, 'test' }
7
+ app.app.public_folder.should == 'test'
8
+ end
9
+
10
+ it "registers assets paths" do
11
+ paths = %w(test/)
12
+ Jagger::Assets.any_instance.expects(:append_paths).with(paths)
13
+ app = Jagger::Builder.new { set :asset_paths, paths }
14
+ end
15
+ end
16
+
17
+ describe "integration" do
18
+ let :app do
19
+ Jagger::Builder.new do
20
+ set :asset_paths, [File.expand_path('../fixtures/src/', __FILE__)]
21
+ set :views, File.expand_path('../fixtures/templates/', __FILE__)
22
+ end
23
+ end
24
+
25
+ it "serves index page" do
26
+ get '/'
27
+ last_response.body.should == 'Hello Jagger!'
28
+ end
29
+
30
+ it "serves assets" do
31
+ get '/assets/one.js'
32
+ last_response.body.strip.should == "alert('hello!');"
33
+ end
34
+ end
35
+ end
@@ -0,0 +1 @@
1
+ //= require two
@@ -0,0 +1 @@
1
+ alert('hello!');
@@ -0,0 +1 @@
1
+ Hello Jagger!
@@ -0,0 +1,10 @@
1
+ require 'rspec'
2
+ require 'mocha'
3
+ require 'rack/test'
4
+
5
+ require 'jagger'
6
+
7
+ RSpec.configure do |config|
8
+ config.mock_with :mocha
9
+ include Rack::Test::Methods
10
+ end
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jagger
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Chris Kowalik
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-03-30 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: sprockets
16
+ requirement: &19515340 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *19515340
25
+ - !ruby/object:Gem::Dependency
26
+ name: sinatra
27
+ requirement: &19514380 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *19514380
36
+ - !ruby/object:Gem::Dependency
37
+ name: rack
38
+ requirement: &19513580 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *19513580
47
+ - !ruby/object:Gem::Dependency
48
+ name: rspec
49
+ requirement: &19512840 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *19512840
58
+ - !ruby/object:Gem::Dependency
59
+ name: mocha
60
+ requirement: &19510360 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *19510360
69
+ description: ! "Jagger an frontman for your applications. It serves dynamically \ngenerated
70
+ assets via sprockets pipeline, static files and all the \ntemplates. All that makes
71
+ your life much easier.'\n"
72
+ email:
73
+ - chris@nu7hat.ch
74
+ executables: []
75
+ extensions: []
76
+ extra_rdoc_files: []
77
+ files:
78
+ - .rspec
79
+ - Gemfile
80
+ - Gemfile.lock
81
+ - README.md
82
+ - Rakefile
83
+ - jagger.gemspec
84
+ - lib/jagger.rb
85
+ - lib/jagger/app.rb
86
+ - lib/jagger/assets.rb
87
+ - lib/jagger/builder.rb
88
+ - spec/app_spec.rb
89
+ - spec/assets_spec.rb
90
+ - spec/builder_spec.rb
91
+ - spec/fixtures/src/one.js
92
+ - spec/fixtures/src/two.js
93
+ - spec/fixtures/templates/index.erb
94
+ - spec/spec_helper.rb
95
+ homepage: http://github.com/nu7hatch/jagger
96
+ licenses: []
97
+ post_install_message:
98
+ rdoc_options: []
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ none: false
103
+ requirements:
104
+ - - ! '>='
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ required_rubygems_version: !ruby/object:Gem::Requirement
108
+ none: false
109
+ requirements:
110
+ - - ! '>='
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ requirements: []
114
+ rubyforge_project: jagger
115
+ rubygems_version: 1.8.15
116
+ signing_key:
117
+ specification_version: 3
118
+ summary: Jagger is your frontman!
119
+ test_files: []