rail 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/Guardfile +10 -0
- data/README.md +10 -12
- data/Rakefile +4 -7
- data/bin/rail +1 -1
- data/lib/rail.rb +7 -21
- data/lib/rail/application.rb +10 -82
- data/lib/rail/browser.rb +6 -10
- data/lib/rail/generator.rb +13 -20
- data/lib/rail/pipeline.rb +13 -13
- data/lib/rail/precompiler.rb +58 -0
- data/lib/rail/processor/base.rb +1 -1
- data/lib/rail/processor/coffee_script.rb +1 -1
- data/lib/rail/processor/haml.rb +2 -2
- data/lib/rail/request.rb +12 -2
- data/lib/rail/tasks/assets.rake +1 -1
- data/lib/rail/version.rb +1 -1
- data/lib/support/generator.rb +76 -0
- data/lib/support/inflector.rb +16 -0
- data/lib/support/loader.rb +55 -0
- data/lib/support/query_string.rb +8 -0
- data/lib/support/query_struct.rb +10 -0
- data/rail.gemspec +5 -0
- data/spec/{coffee_spec.rb → features/coffee_spec.rb} +5 -7
- data/spec/{haml_spec.rb → features/haml_spec.rb} +6 -8
- data/spec/{sass_spec.rb → features/sass_spec.rb} +5 -7
- data/spec/{project → fixtures/project}/app/assets/javascripts/application.js.coffee +0 -0
- data/spec/{project → fixtures/project}/app/assets/javascripts/font.coffee +0 -0
- data/spec/{project → fixtures/project}/app/assets/javascripts/parser.js.coffee +0 -0
- data/spec/{project → fixtures/project}/app/assets/stylesheets/_reset.scss +0 -0
- data/spec/{project → fixtures/project}/app/assets/stylesheets/application.css.scss +0 -0
- data/spec/{project → fixtures/project}/app/helpers/application_helper.rb +0 -0
- data/spec/{project → fixtures/project}/app/views/articles/about.html.haml +0 -0
- data/spec/{project → fixtures/project}/app/views/layouts/application.html.haml +0 -0
- data/spec/{project → fixtures/project}/app/views/layouts/articles.html.haml +0 -0
- data/spec/{project → fixtures/project}/config/application.rb +0 -0
- data/spec/{project → fixtures/project}/controller.rb +0 -0
- data/spec/lib/rail/application_spec.rb +38 -0
- data/spec/lib/rail/generator_spec.rb +14 -0
- data/spec/lib/rail/precompiler_spec.rb +25 -0
- data/spec/lib/rail/request_spec.rb +16 -0
- data/spec/lib/support/inflector_spec.rb +18 -0
- data/spec/lib/support/loader_spec.rb +61 -0
- data/spec/lib/support/query_string_spec.rb +11 -0
- data/spec/lib/support/query_struct_spec.rb +28 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/support/common_helper.rb +5 -0
- metadata +99 -32
- data/lib/generator.rb +0 -73
- data/lib/rail/support.rb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ed960041649216cdcaeb74ef9689f4e95036b95b
|
4
|
+
data.tar.gz: 9f8d32c3ff9f03a87521958d217a0d12c9cde586
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1738d5b0b7a8725f7e9187edd6f6cc8c96815197167e9e2bf0d50245a27c8d2420807c01d211d0355bc14c98e67ddfccaf43d0dff2ccd93c20f8737cca10c759
|
7
|
+
data.tar.gz: 04cc3ad49ca4dbd80fd4144de9d6684b48a007c303bd1fc0e01ef3657fddb9d158871919d738ecacbf40b02129613bcdaae3c66f93ebd419252809eb951461cd
|
data/CHANGELOG.md
CHANGED
data/Guardfile
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
guard :rspec, cmd: 'bundle exec rspec' do
|
2
|
+
watch(%r{^lib/(.+)\.rb$}) do |match|
|
3
|
+
file = "spec/lib/#{match[1]}_spec.rb"
|
4
|
+
File.exist?(file) ? file : 'spec'
|
5
|
+
end
|
6
|
+
watch(%r{^spec/.*_spec\.rb$})
|
7
|
+
watch(%r{^spec/spec_helper\.rb$}) { 'spec' }
|
8
|
+
end
|
9
|
+
|
10
|
+
# vim: set ft=ruby
|
data/README.md
CHANGED
@@ -8,7 +8,9 @@ assets, and it includes the following components:
|
|
8
8
|
* [Haml](http://haml.info/) for HTML, and
|
9
9
|
* [Sass](http://sass-lang.com/) for CSS.
|
10
10
|
|
11
|
-
##
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
### Straightforward
|
12
14
|
|
13
15
|
Install the gem:
|
14
16
|
|
@@ -42,18 +44,14 @@ current directory called `my_project` and initializes a basic Rail project
|
|
42
44
|
inside that folder. In this case, `MyProject` is used as the class name of
|
43
45
|
the project. Feel free to replace `my_project` with the name of your project.
|
44
46
|
|
45
|
-
|
47
|
+
### Manual
|
46
48
|
|
47
|
-
|
49
|
+
Create a `Gemfile`:
|
48
50
|
|
49
51
|
```ruby
|
50
52
|
source 'https://rubygems.org'
|
51
53
|
|
52
|
-
gem 'rail'
|
53
|
-
|
54
|
-
# The rest is optional
|
55
|
-
gem 'redcarpet', '~> 3.1.2' # your favorit complement to Haml
|
56
|
-
gem 'thin', '~> 1.6.2' # your favorit Web server
|
54
|
+
gem 'rail'
|
57
55
|
```
|
58
56
|
|
59
57
|
Run [Bundler](http://bundler.io/):
|
@@ -122,15 +120,15 @@ As with Rails, Rail is configured inside `config/application.rb`:
|
|
122
120
|
```ruby
|
123
121
|
module MyProject
|
124
122
|
class Application < Rail::Application
|
125
|
-
#
|
126
|
-
config.gems << '
|
123
|
+
# Gems to look for additional assets
|
124
|
+
config.gems << 'googleplus-reader'
|
127
125
|
|
128
|
-
#
|
126
|
+
# Assets to precompile when running `rake assets`
|
129
127
|
config.precompile << 'application.css'
|
130
128
|
config.precompile << 'application.js'
|
131
129
|
config.precompile << 'index.html'
|
132
130
|
|
133
|
-
# Compress assets
|
131
|
+
# Compress assets when serving and precompiling
|
134
132
|
config.compress = true
|
135
133
|
end
|
136
134
|
end
|
data/Rakefile
CHANGED
@@ -1,10 +1,7 @@
|
|
1
1
|
require 'bundler/gem_tasks'
|
2
|
-
require '
|
2
|
+
require 'rspec/core/rake_task'
|
3
3
|
|
4
|
-
|
5
|
-
test.libs.push('lib')
|
6
|
-
test.test_files = FileList[ 'spec/*_spec.rb' ]
|
7
|
-
test.verbose = true
|
8
|
-
end
|
4
|
+
RSpec::Core::RakeTask.new(:spec)
|
9
5
|
|
10
|
-
task :default => :
|
6
|
+
task :default => :spec
|
7
|
+
task :test => :spec
|
data/bin/rail
CHANGED
data/lib/rail.rb
CHANGED
@@ -1,29 +1,30 @@
|
|
1
|
-
require 'ostruct'
|
2
1
|
require 'forwardable'
|
3
|
-
|
4
2
|
require 'rack'
|
5
|
-
|
6
3
|
require 'coffee-script'
|
7
4
|
require 'haml'
|
8
5
|
require 'sass'
|
9
|
-
|
10
6
|
require 'uglifier'
|
11
7
|
|
8
|
+
require_relative 'support/inflector'
|
9
|
+
require_relative 'support/loader'
|
10
|
+
require_relative 'support/query_string'
|
11
|
+
require_relative 'support/query_struct'
|
12
|
+
|
12
13
|
require_relative 'rail/application'
|
13
14
|
require_relative 'rail/browser'
|
14
15
|
require_relative 'rail/context'
|
15
16
|
require_relative 'rail/pipeline'
|
17
|
+
require_relative 'rail/precompiler'
|
16
18
|
require_relative 'rail/processor'
|
17
19
|
require_relative 'rail/request'
|
18
20
|
require_relative 'rail/server'
|
19
|
-
require_relative 'rail/support'
|
20
21
|
require_relative 'rail/version'
|
21
22
|
|
22
23
|
module Rail
|
23
24
|
NotFoundError = Class.new(StandardError)
|
24
25
|
|
25
26
|
def self.env
|
26
|
-
@env ||=
|
27
|
+
@env ||= Support::QueryString.new(ENV['RAIL_ENV'] || 'development')
|
27
28
|
end
|
28
29
|
|
29
30
|
def self.applications
|
@@ -31,19 +32,4 @@ module Rail
|
|
31
32
|
klass < Application
|
32
33
|
end
|
33
34
|
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
def self.build_env
|
38
|
-
string = ENV['RAIL_ENV'] ? ENV['RAIL_ENV'].dup : 'development'
|
39
|
-
|
40
|
-
string.singleton_class.class_eval do
|
41
|
-
define_method(:method_missing) do |name, *arguments, &block|
|
42
|
-
super unless name.to_s =~ /^(?<name>.+)\?$/
|
43
|
-
self == Regexp.last_match(:name)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
string
|
48
|
-
end
|
49
35
|
end
|
data/lib/rail/application.rb
CHANGED
@@ -1,16 +1,11 @@
|
|
1
1
|
module Rail
|
2
2
|
class Application
|
3
|
-
|
4
|
-
|
5
|
-
attr_reader :browser, :pipeline
|
6
|
-
def_delegators :config, :root, :gems, :compress?
|
3
|
+
attr_reader :config, :browser, :pipeline
|
7
4
|
|
8
5
|
def initialize
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
@browser = Browser.new(self)
|
13
|
-
@pipeline = Pipeline.new(self)
|
6
|
+
@config = self.class.config
|
7
|
+
@browser = Browser.new(config)
|
8
|
+
@pipeline = Pipeline.new(config)
|
14
9
|
end
|
15
10
|
|
16
11
|
def call(env)
|
@@ -18,95 +13,28 @@ module Rail
|
|
18
13
|
(browser.accept?(request) ? browser : pipeline).process(request)
|
19
14
|
end
|
20
15
|
|
21
|
-
def
|
22
|
-
|
16
|
+
def precompile
|
17
|
+
Precompiler.new(pipeline).process(config.precompile)
|
23
18
|
end
|
24
19
|
|
25
|
-
def
|
26
|
-
|
20
|
+
def self.inherited(klass)
|
21
|
+
klass.config.root = File.expand_path('../..', caller[0].sub(/:.*/, ''))
|
27
22
|
end
|
28
23
|
|
29
24
|
def self.config
|
30
|
-
@config ||=
|
25
|
+
@config ||= Support::QueryStruct.new(default_options)
|
31
26
|
end
|
32
27
|
|
33
28
|
def self.load_tasks
|
34
|
-
# Rakefile
|
35
|
-
config.root ||= find_root
|
36
|
-
|
37
29
|
Dir[File.join(File.dirname(__FILE__), 'tasks/*.rake')].each do |path|
|
38
30
|
Rake::load_rakefile(path)
|
39
31
|
end
|
40
32
|
end
|
41
33
|
|
42
|
-
def self.precompile
|
43
|
-
if config.precompile.empty?
|
44
|
-
puts 'Nothing to precompile.'
|
45
|
-
return
|
46
|
-
end
|
47
|
-
|
48
|
-
application = self.new
|
49
|
-
|
50
|
-
puts 'Precompiling assets...'
|
51
|
-
puts
|
52
|
-
|
53
|
-
config.precompile.each do |path|
|
54
|
-
file = File.join('public', path)
|
55
|
-
unless File.exist?(File.dirname(file))
|
56
|
-
FileUtils.mkdir_p(File.dirname(file))
|
57
|
-
end
|
58
|
-
|
59
|
-
puts "#{ path } -> #{ file }"
|
60
|
-
|
61
|
-
request = Request.new('REQUEST_METHOD' => 'GET', 'PATH_INFO' => path)
|
62
|
-
_, _, source = application.pipeline.process(request)
|
63
|
-
|
64
|
-
File.open(file, 'w') do |file|
|
65
|
-
source.each { |chunk| file.write(chunk) }
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
puts
|
70
|
-
puts 'Done.'
|
71
|
-
end
|
72
|
-
|
73
|
-
def self.find_root
|
74
|
-
File.expand_path('..', caller[1].sub(/:.*/, ''))
|
75
|
-
end
|
76
|
-
|
77
34
|
private
|
78
35
|
|
79
|
-
def load_helpers
|
80
|
-
Dir[File.join(root, 'app/helpers/*.rb')].map do |file|
|
81
|
-
require file
|
82
|
-
Support.constantize(File.basename(file, '.rb'))
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
36
|
def self.default_options
|
87
|
-
{
|
88
|
-
gems: [],
|
89
|
-
precompile: [],
|
90
|
-
compress: Rail.env.production?
|
91
|
-
}
|
37
|
+
{ gems: [], precompile: [], compress: Rail.env.production? }
|
92
38
|
end
|
93
|
-
|
94
|
-
def self.build_config
|
95
|
-
struct = OpenStruct.new
|
96
|
-
|
97
|
-
struct.singleton_class.class_eval do
|
98
|
-
define_method(:method_missing) do |name, *arguments, &block|
|
99
|
-
!!super(name.to_s.sub(/\?$/, '').to_sym, *arguments, &block)
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
default_options.each do |name, value|
|
104
|
-
struct.send("#{ name }=", value)
|
105
|
-
end
|
106
|
-
|
107
|
-
struct
|
108
|
-
end
|
109
|
-
|
110
|
-
private_class_method :default_options, :build_config
|
111
39
|
end
|
112
40
|
end
|
data/lib/rail/browser.rb
CHANGED
@@ -2,23 +2,19 @@ require 'rack'
|
|
2
2
|
|
3
3
|
module Rail
|
4
4
|
class Browser
|
5
|
-
|
5
|
+
attr_reader :root
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
def initialize(host)
|
11
|
-
@host = host
|
12
|
-
@directory ||= Rack::Directory.new(File.join(root, 'public'))
|
7
|
+
def initialize(config)
|
8
|
+
@root = File.join(config.root, 'public')
|
9
|
+
@directory = Rack::Directory.new(root)
|
13
10
|
end
|
14
11
|
|
15
12
|
def process(request)
|
16
|
-
call(request.env)
|
13
|
+
@directory.call(request.env)
|
17
14
|
end
|
18
15
|
|
19
16
|
def accept?(request)
|
20
|
-
|
21
|
-
!path.empty? && File.exist?(File.join(root, 'public', path))
|
17
|
+
File.exist?(File.join(root, request.path))
|
22
18
|
end
|
23
19
|
end
|
24
20
|
end
|
data/lib/rail/generator.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
|
-
require 'generator'
|
1
|
+
require 'support/generator'
|
2
|
+
require 'support/inflector'
|
2
3
|
|
3
4
|
module Rail
|
4
|
-
class Generator < ::Generator
|
5
|
-
Error = Class.new(StandardError)
|
6
|
-
|
5
|
+
class Generator < Support::Generator
|
7
6
|
FILES = [
|
8
7
|
'app/assets/javascripts/application.js.coffee',
|
9
8
|
'app/assets/stylesheets/application.css.scss',
|
@@ -17,31 +16,25 @@ module Rail
|
|
17
16
|
]
|
18
17
|
|
19
18
|
def initialize(options)
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
project_name = (root_dir.split('/').last || '')
|
24
|
-
.gsub(/^[^a-zA-Z]*/, '')
|
25
|
-
.gsub(/[^\w]/, '')
|
26
|
-
.gsub(/^\w|_\w/, &:upcase)
|
27
|
-
.gsub(/_+/, ' ')
|
19
|
+
destination = options.fetch(:destination)
|
20
|
+
source = File.expand_path('../templates', __FILE__)
|
28
21
|
|
22
|
+
directory = destination.split('/').last || ''
|
23
|
+
project_name = Support::Inflector.titelize(directory)
|
29
24
|
class_name = project_name.gsub(' ', '')
|
30
25
|
|
31
26
|
@locals = { class_name: class_name, project_name: project_name }
|
32
27
|
|
33
|
-
raise
|
28
|
+
raise ArgumentError, 'The project name is invalid.' if class_name.empty?
|
34
29
|
|
35
|
-
super(
|
30
|
+
super(destination: destination, source: source)
|
36
31
|
end
|
37
32
|
|
38
33
|
def run
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
def report(message)
|
44
|
-
puts "Creating '#{ message }'..."
|
34
|
+
if File.directory?(destination)
|
35
|
+
raise ArgumentError, 'The directory already exists.'
|
36
|
+
end
|
37
|
+
process(FILES, @locals)
|
45
38
|
end
|
46
39
|
end
|
47
40
|
end
|
data/lib/rail/pipeline.rb
CHANGED
@@ -2,14 +2,16 @@ module Rail
|
|
2
2
|
class Pipeline
|
3
3
|
extend Forwardable
|
4
4
|
|
5
|
-
|
5
|
+
attr_reader :config
|
6
|
+
def_delegators :config, :root, :gems, :compress?
|
6
7
|
|
7
|
-
def initialize(
|
8
|
-
@
|
8
|
+
def initialize(config)
|
9
|
+
@config = config
|
10
|
+
@loader = Support::Loader.new(File.join(root, 'app/helpers/*.rb'))
|
9
11
|
end
|
10
12
|
|
11
13
|
def process(request)
|
12
|
-
context = Context.new(locals: { request: request }, mixins:
|
14
|
+
context = Context.new(locals: { request: request }, mixins: loader.find)
|
13
15
|
|
14
16
|
asset = rewrite(request.path)
|
15
17
|
klass = Processor.find(asset) or raise NotFoundError
|
@@ -21,9 +23,9 @@ module Rail
|
|
21
23
|
|
22
24
|
headers = { 'Content-Type' => klass.mime_type }
|
23
25
|
|
24
|
-
[
|
26
|
+
[200, headers, Array(body)]
|
25
27
|
rescue NotFoundError
|
26
|
-
[
|
28
|
+
[404, {}, []]
|
27
29
|
end
|
28
30
|
|
29
31
|
def find(asset)
|
@@ -36,14 +38,12 @@ module Rail
|
|
36
38
|
|
37
39
|
private
|
38
40
|
|
41
|
+
attr_reader :loader
|
42
|
+
|
39
43
|
def rewrite(path)
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
"#{ path }.html"
|
44
|
-
else
|
45
|
-
path
|
46
|
-
end
|
44
|
+
path = path.sub(/^\//, '')
|
45
|
+
path = 'layouts/application.html' if path == 'index.html'
|
46
|
+
path
|
47
47
|
end
|
48
48
|
|
49
49
|
def paths
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Rail
|
2
|
+
class Precompiler
|
3
|
+
class Storage
|
4
|
+
attr_reader :root
|
5
|
+
|
6
|
+
def initialize(root = 'public')
|
7
|
+
@root = root
|
8
|
+
end
|
9
|
+
|
10
|
+
def write(file, stream)
|
11
|
+
file = File.join(root, file)
|
12
|
+
|
13
|
+
unless File.exist?(File.dirname(file))
|
14
|
+
FileUtils.mkdir_p(File.dirname(file))
|
15
|
+
end
|
16
|
+
|
17
|
+
File.open(file, 'w') do |file|
|
18
|
+
stream.each { |chunk| file.write(chunk) }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(pipeline, storage = nil)
|
24
|
+
@pipeline = pipeline
|
25
|
+
@storage = storage || Storage.new
|
26
|
+
end
|
27
|
+
|
28
|
+
def process(paths)
|
29
|
+
if paths.empty?
|
30
|
+
report('Nothing to precompile.')
|
31
|
+
return
|
32
|
+
end
|
33
|
+
|
34
|
+
report('Precompiling assets...')
|
35
|
+
|
36
|
+
paths.each_with_index do |path, i|
|
37
|
+
report('%4d. %s' % [i + 1, path])
|
38
|
+
storage.write(path, read(path))
|
39
|
+
end
|
40
|
+
|
41
|
+
report('Done.')
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
attr_reader :pipeline, :storage
|
47
|
+
|
48
|
+
def read(path)
|
49
|
+
request = Request.new('REQUEST_METHOD' => 'GET', 'PATH_INFO' => path)
|
50
|
+
_, _, source = pipeline.process(request)
|
51
|
+
source
|
52
|
+
end
|
53
|
+
|
54
|
+
def report(message)
|
55
|
+
puts message
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|