railz_lite 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.rubocop.yml +13 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +43 -0
- data/Rakefile +12 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/exe/railz_lite +4 -0
- data/exe/railz_lite.rb~ +3 -0
- data/lib/railz_lite.rb +10 -0
- data/lib/railz_lite/cli.rb +17 -0
- data/lib/railz_lite/controllers/controller_base.rb +101 -0
- data/lib/railz_lite/controllers/flash.rb +22 -0
- data/lib/railz_lite/controllers/router.rb +68 -0
- data/lib/railz_lite/controllers/session.rb +30 -0
- data/lib/railz_lite/controllers/show_exceptions.rb +56 -0
- data/lib/railz_lite/controllers/static.rb +66 -0
- data/lib/railz_lite/controllers/templates/rescue.html.erb +53 -0
- data/lib/railz_lite/controllers/templates/rescue.html.erb~ +0 -0
- data/lib/railz_lite/generators/project.rb +33 -0
- data/lib/railz_lite/generators/project.rb~ +33 -0
- data/lib/railz_lite/generators/templates/application_controller.rb~ +0 -0
- data/lib/railz_lite/generators/templates/routes.rb +0 -0
- data/lib/railz_lite/generators/templates/server.rb +27 -0
- data/lib/railz_lite/models/associatable.rb +79 -0
- data/lib/railz_lite/models/associatable.rb~ +79 -0
- data/lib/railz_lite/models/associatable2.rb +35 -0
- data/lib/railz_lite/models/associatable2.rb~ +35 -0
- data/lib/railz_lite/models/attr_accessor_object.rb +13 -0
- data/lib/railz_lite/models/db_connection.rb +60 -0
- data/lib/railz_lite/models/searchable.rb +21 -0
- data/lib/railz_lite/models/searchable.rb~ +21 -0
- data/lib/railz_lite/models/sql_object.rb +109 -0
- data/lib/railz_lite/models/validatable.rb +15 -0
- data/lib/railz_lite/version.rb +5 -0
- data/railz_lite.gemspec +46 -0
- metadata +215 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'byebug'
|
3
|
+
|
4
|
+
class Session
|
5
|
+
# find the cookie for this app
|
6
|
+
# deserialize the cookie into a hash
|
7
|
+
def initialize(req)
|
8
|
+
cookie = req.cookies['_rails_lite_app']
|
9
|
+
@data = cookie.present? ? JSON.parse(cookie) : {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def [](key)
|
13
|
+
@data[key]
|
14
|
+
end
|
15
|
+
|
16
|
+
def []=(key, val)
|
17
|
+
@data[key] = val
|
18
|
+
end
|
19
|
+
|
20
|
+
# serialize the hash into json and save in a cookie
|
21
|
+
# add to the responses cookies
|
22
|
+
def store_session(res)
|
23
|
+
res.set_cookie(
|
24
|
+
'_rails_lite_app',
|
25
|
+
{ path: '/',
|
26
|
+
value: @data.to_json
|
27
|
+
}
|
28
|
+
)
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'byebug'
|
3
|
+
|
4
|
+
class ShowExceptions
|
5
|
+
attr_reader :app
|
6
|
+
|
7
|
+
def initialize(app)
|
8
|
+
@app = app
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
app.call(env)
|
13
|
+
rescue Exception => e
|
14
|
+
render_exception(e)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def render_exception(e)
|
20
|
+
dir_path = File.dirname(__FILE__)
|
21
|
+
template_fname = File.join(dir_path, 'templates', 'rescue.html.erb')
|
22
|
+
template = File.read(template_fname)
|
23
|
+
body = ERB.new(template).result(binding)
|
24
|
+
|
25
|
+
['500', {'Content-type' => 'text/html'}, [body]]
|
26
|
+
end
|
27
|
+
|
28
|
+
def error_source_file(e)
|
29
|
+
stack_trace_top(e).first
|
30
|
+
end
|
31
|
+
|
32
|
+
def stack_trace_top(e)
|
33
|
+
e.backtrace.first.split(':')
|
34
|
+
end
|
35
|
+
|
36
|
+
def source_line_num(e)
|
37
|
+
stack_trace_top(e)[1].to_i
|
38
|
+
end
|
39
|
+
|
40
|
+
def extract_formatted_source(e)
|
41
|
+
source_file_name = error_source_file(e)
|
42
|
+
source_line_num = source_line_num(e)
|
43
|
+
source_lines = extract_source(source_file_name)
|
44
|
+
format_source(source_lines, source_line_num)
|
45
|
+
end
|
46
|
+
|
47
|
+
def extract_source(file)
|
48
|
+
File.open(file, 'r').readlines
|
49
|
+
end
|
50
|
+
|
51
|
+
def format_source(source_lines, source_line_num)
|
52
|
+
start = [0, source_line_num - 3].max
|
53
|
+
lines = source_lines[start..(start+5)]
|
54
|
+
Hash[*(start+1..(lines.count+start)).zip(lines).flatten]
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'byebug'
|
2
|
+
class Static
|
3
|
+
attr_reader :app, :file_server, :root
|
4
|
+
|
5
|
+
def initialize(app)
|
6
|
+
@app = app
|
7
|
+
@root = 'public'
|
8
|
+
@file_server = FileServer.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
req = Rack::Request.new(env)
|
13
|
+
path = req.path
|
14
|
+
|
15
|
+
if can_match?(path)
|
16
|
+
file_server.call(env)
|
17
|
+
else
|
18
|
+
app.call(env)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def can_match?(path)
|
25
|
+
path.index("/#{root}")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
class FileServer
|
31
|
+
MIME_TYPES = {
|
32
|
+
'.txt' => 'text/plain',
|
33
|
+
'.jpg' => 'image/jpeg',
|
34
|
+
'.zip' => 'application/zip'
|
35
|
+
}
|
36
|
+
|
37
|
+
def call(env)
|
38
|
+
res = Rack::Response.new
|
39
|
+
file_name = requested_file_name(env)
|
40
|
+
|
41
|
+
if File.exist?(file_name)
|
42
|
+
serve_file(file_name, res)
|
43
|
+
else
|
44
|
+
res.status = 404
|
45
|
+
res.write('File not found')
|
46
|
+
end
|
47
|
+
[res.status, res.headers, res.body]
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def serve_file(file_name, res)
|
53
|
+
extension = File.extname(file_name)
|
54
|
+
content_type = MIME_TYPES[extension]
|
55
|
+
file = File.read(file_name)
|
56
|
+
res['Content-type'] = content_type
|
57
|
+
res.write(file)
|
58
|
+
end
|
59
|
+
|
60
|
+
def requested_file_name(env)
|
61
|
+
req = Rack::Request.new(env)
|
62
|
+
path = req.path
|
63
|
+
dir = File.dirname(__FILE__)
|
64
|
+
File.join(dir, '..', path)
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
<head>
|
2
|
+
<style>
|
3
|
+
.header {
|
4
|
+
background: red;
|
5
|
+
}
|
6
|
+
|
7
|
+
.source-view {
|
8
|
+
border: 10px solid lightgray;
|
9
|
+
width: 800px;
|
10
|
+
}
|
11
|
+
|
12
|
+
.line {
|
13
|
+
white-space: pre-wrap;
|
14
|
+
}
|
15
|
+
|
16
|
+
.line-num {
|
17
|
+
background: lightgray
|
18
|
+
}
|
19
|
+
|
20
|
+
.line.error {
|
21
|
+
background: red;
|
22
|
+
}
|
23
|
+
</style>
|
24
|
+
</head>
|
25
|
+
|
26
|
+
<body>
|
27
|
+
<h2 class='header'><%=e.class%>: <%=e.message%></h2>
|
28
|
+
|
29
|
+
<h4>Extracted source (around line <b><%=source_line_num(e)%></b>):</h4>
|
30
|
+
|
31
|
+
<div class='source-view'>
|
32
|
+
<table cellpadding="0" cellspacing="0">
|
33
|
+
<% extract_formatted_source(e).each do |line_num, line| %>
|
34
|
+
<tr>
|
35
|
+
<td>
|
36
|
+
<pre class='line-num'><%=line_num %></pre>
|
37
|
+
</td>
|
38
|
+
<td>
|
39
|
+
<pre class='line
|
40
|
+
<%= 'error' if line_num == source_line_num(e)%>'><%= line %></pre>
|
41
|
+
</td>
|
42
|
+
</tr>
|
43
|
+
<% end %>
|
44
|
+
</table>
|
45
|
+
</div>
|
46
|
+
<h5><%= File.expand_path(error_source_file(e)) %></h5>
|
47
|
+
|
48
|
+
<h3>Stack trace</h3>
|
49
|
+
<% e.backtrace.each do |stack_line| %>
|
50
|
+
<%= stack_line %>
|
51
|
+
<br>
|
52
|
+
<% end %>
|
53
|
+
</body>
|
File without changes
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'thor/group'
|
2
|
+
|
3
|
+
module RailzLite
|
4
|
+
module Generators
|
5
|
+
class Project < Thor::Group
|
6
|
+
include Thor::Actions
|
7
|
+
|
8
|
+
def self.source_root
|
9
|
+
File.dirname(__FILE__) + "/templates"
|
10
|
+
end
|
11
|
+
|
12
|
+
def add_controllers
|
13
|
+
empty_directory("/controllers")
|
14
|
+
end
|
15
|
+
|
16
|
+
def add_models
|
17
|
+
empty_directory("/models")
|
18
|
+
end
|
19
|
+
|
20
|
+
def add_server
|
21
|
+
template("server.rb", "/config/server.rb")
|
22
|
+
end
|
23
|
+
|
24
|
+
def add_views
|
25
|
+
empty_directory("/views")
|
26
|
+
end
|
27
|
+
|
28
|
+
def add_public
|
29
|
+
empty_directory("/public")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'thor/group'
|
2
|
+
|
3
|
+
module RailzLite
|
4
|
+
module Generators
|
5
|
+
class Project < Thor::Group
|
6
|
+
argument :project_name, :type => :string
|
7
|
+
include Thor::Actions
|
8
|
+
|
9
|
+
def self.source_root
|
10
|
+
File.dirname(__FILE__) + "/templates"
|
11
|
+
end
|
12
|
+
|
13
|
+
def create_project
|
14
|
+
empty_directory(project_name)
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_controllers
|
18
|
+
template("application_controller.rb", "#{project_name}/application_controller.rb")
|
19
|
+
end
|
20
|
+
def add_controllers
|
21
|
+
template("application_model.rb", "#{project_name}/application_model.rb")
|
22
|
+
end
|
23
|
+
|
24
|
+
def add_views
|
25
|
+
empty_directory("#{project_name}/views")
|
26
|
+
end
|
27
|
+
|
28
|
+
def add_public
|
29
|
+
empty_directory("#{project_name}/public")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
File without changes
|
File without changes
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rack'
|
2
|
+
require 'railz_lite/controllers/static'
|
3
|
+
require 'railz_lite/controllers/show_exceptions'
|
4
|
+
require 'railz_lite/controllers/router'
|
5
|
+
|
6
|
+
router = Router.new
|
7
|
+
router.draw do
|
8
|
+
# add routes here
|
9
|
+
end
|
10
|
+
|
11
|
+
app = Proc.new do |env|
|
12
|
+
req = Rack::Request.new(env)
|
13
|
+
res = Rack::Response.new
|
14
|
+
router.run(req, res)
|
15
|
+
res.finish
|
16
|
+
end
|
17
|
+
|
18
|
+
app = Rack::Builder.new do
|
19
|
+
use Show_Exceptions # generates helpful error messages
|
20
|
+
use Static # serves static assets from /public
|
21
|
+
run app
|
22
|
+
end.to_app
|
23
|
+
|
24
|
+
Rack::Server.start(
|
25
|
+
app: app,
|
26
|
+
Port: 3000
|
27
|
+
)
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require_relative 'searchable'
|
2
|
+
require 'active_support/inflector'
|
3
|
+
|
4
|
+
class AssocOptions
|
5
|
+
attr_accessor(
|
6
|
+
:foreign_key,
|
7
|
+
:class_name,
|
8
|
+
:primary_key
|
9
|
+
)
|
10
|
+
|
11
|
+
def model_class
|
12
|
+
class_name.constantize
|
13
|
+
end
|
14
|
+
|
15
|
+
def table_name
|
16
|
+
model_class.table_name
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class BelongsToOptions < AssocOptions
|
21
|
+
def initialize(name, options = {})
|
22
|
+
foreign_key_sym = "#{name}_id".to_sym
|
23
|
+
class_name_val = name.to_s.camelcase.singularize
|
24
|
+
send("primary_key=", :id)
|
25
|
+
send("foreign_key=", foreign_key_sym)
|
26
|
+
send("class_name=", class_name_val)
|
27
|
+
|
28
|
+
options.each do |attr, val|
|
29
|
+
send("#{attr}=", val)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class HasManyOptions < AssocOptions
|
35
|
+
def initialize(name, self_class_name, options = {})
|
36
|
+
foreign_key_sym = "#{self_class_name.underscore}_id".to_sym
|
37
|
+
class_name_val = name.to_s.camelcase.singularize
|
38
|
+
|
39
|
+
send("primary_key=", :id)
|
40
|
+
send("foreign_key=", foreign_key_sym)
|
41
|
+
send("class_name=", class_name_val)
|
42
|
+
|
43
|
+
options.each do |attr, val|
|
44
|
+
send("#{attr}=", val)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
module Associatable
|
50
|
+
def belongs_to(name, options = {})
|
51
|
+
options = BelongsToOptions.new(name, options)
|
52
|
+
assoc_options[name] = options
|
53
|
+
define_method(name) do
|
54
|
+
foreign_key = send(options.foreign_key)
|
55
|
+
primary_key = options.primary_key
|
56
|
+
params = [[primary_key, foreign_key]].to_h
|
57
|
+
options.model_class.where(params).first
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def has_many(name, options = {})
|
62
|
+
options = HasManyOptions.new(name, self.name, options)
|
63
|
+
define_method(name) do
|
64
|
+
foreign_key = options.foreign_key
|
65
|
+
primary_key = send(options.primary_key)
|
66
|
+
params = [[foreign_key, primary_key]].to_h
|
67
|
+
options.model_class.where(params)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def assoc_options
|
72
|
+
@assoc_options ||= {}
|
73
|
+
@assoc_options
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class SQLObject
|
78
|
+
extend Associatable
|
79
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require_relative '02_searchable'
|
2
|
+
require 'active_support/inflector'
|
3
|
+
|
4
|
+
class AssocOptions
|
5
|
+
attr_accessor(
|
6
|
+
:foreign_key,
|
7
|
+
:class_name,
|
8
|
+
:primary_key
|
9
|
+
)
|
10
|
+
|
11
|
+
def model_class
|
12
|
+
class_name.constantize
|
13
|
+
end
|
14
|
+
|
15
|
+
def table_name
|
16
|
+
model_class.table_name
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class BelongsToOptions < AssocOptions
|
21
|
+
def initialize(name, options = {})
|
22
|
+
foreign_key_sym = "#{name}_id".to_sym
|
23
|
+
class_name_val = name.to_s.camelcase.singularize
|
24
|
+
send("primary_key=", :id)
|
25
|
+
send("foreign_key=", foreign_key_sym)
|
26
|
+
send("class_name=", class_name_val)
|
27
|
+
|
28
|
+
options.each do |attr, val|
|
29
|
+
send("#{attr}=", val)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class HasManyOptions < AssocOptions
|
35
|
+
def initialize(name, self_class_name, options = {})
|
36
|
+
foreign_key_sym = "#{self_class_name.underscore}_id".to_sym
|
37
|
+
class_name_val = name.to_s.camelcase.singularize
|
38
|
+
|
39
|
+
send("primary_key=", :id)
|
40
|
+
send("foreign_key=", foreign_key_sym)
|
41
|
+
send("class_name=", class_name_val)
|
42
|
+
|
43
|
+
options.each do |attr, val|
|
44
|
+
send("#{attr}=", val)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
module Associatable
|
50
|
+
def belongs_to(name, options = {})
|
51
|
+
options = BelongsToOptions.new(name, options)
|
52
|
+
assoc_options[name] = options
|
53
|
+
define_method(name) do
|
54
|
+
foreign_key = send(options.foreign_key)
|
55
|
+
primary_key = options.primary_key
|
56
|
+
params = [[primary_key, foreign_key]].to_h
|
57
|
+
options.model_class.where(params).first
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def has_many(name, options = {})
|
62
|
+
options = HasManyOptions.new(name, self.name, options)
|
63
|
+
define_method(name) do
|
64
|
+
foreign_key = options.foreign_key
|
65
|
+
primary_key = send(options.primary_key)
|
66
|
+
params = [[foreign_key, primary_key]].to_h
|
67
|
+
options.model_class.where(params)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def assoc_options
|
72
|
+
@assoc_options ||= {}
|
73
|
+
@assoc_options
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class SQLObject
|
78
|
+
extend Associatable
|
79
|
+
end
|