railz_lite 0.2.7 → 0.2.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +104 -3
- data/lib/railz_lite/models/db_connection.rb +24 -13
- data/lib/railz_lite/models/sql_object.rb +2 -2
- data/lib/railz_lite/models/wrappers/pg_wrapper.rb +46 -0
- data/lib/railz_lite/models/wrappers/sqlite3_wrapper.rb +30 -0
- data/lib/railz_lite/version.rb +1 -1
- data/railz_lite.gemspec +1 -0
- metadata +18 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aff7d4d6f62b5eee1669eef62895d5170f55a5d3241db179191a690bb9dc26f1
|
4
|
+
data.tar.gz: 2ab955ed52a300dcf3c614e1a0c4bcbf9f0e8ef81613e2bae9aa7324f08980db
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0b6b915059bf4ed2ce158b1b6eef235fb742cac8fa3a416bdd88df3d4183510c632021181cec277551e86b3142253bf09732d6aed1954cf1c92b08c820c02b2b
|
7
|
+
data.tar.gz: 7118f1462ba3e8d772d4e64bfea0304f8cae53cebd073d9b38c97e318a3129f42bf5560369c96f7edc7b916b9a1e77e22d7d713c18ed31526a189f080f00c25b
|
data/README.md
CHANGED
@@ -1,8 +1,30 @@
|
|
1
1
|
# RailzLite
|
2
2
|
|
3
|
-
|
3
|
+
A lite-weight Ruby gem inspired by Ruby on Rails.
|
4
4
|
|
5
|
-
|
5
|
+
To get started with a new project, execute the command
|
6
|
+
|
7
|
+
```
|
8
|
+
$ railz_lite new MyWebApp
|
9
|
+
```
|
10
|
+
|
11
|
+
This will generate controllers/, views/, models/, and other necessary directories.
|
12
|
+
|
13
|
+
After changing into the root project directory, run the server command to get the Rack server running
|
14
|
+
|
15
|
+
```
|
16
|
+
$ cd MyWebApp && railz_lite server
|
17
|
+
```
|
18
|
+
|
19
|
+
To create a new sqlite3 database file, write your desired SQL code in app.sql then execute
|
20
|
+
|
21
|
+
```
|
22
|
+
$ railz_lite reset_db
|
23
|
+
```
|
24
|
+
|
25
|
+
An example web app can be found at the following repo:
|
26
|
+
|
27
|
+
https://github.com/bryanqb07/trash_films
|
6
28
|
|
7
29
|
## Installation
|
8
30
|
|
@@ -22,7 +44,86 @@ Or install it yourself as:
|
|
22
44
|
|
23
45
|
## Usage
|
24
46
|
|
25
|
-
|
47
|
+
### Controllers
|
48
|
+
|
49
|
+
All controllers should inherit from the RailzLite::ControllerBase class. An example is as follows:
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
class FilmsController < RailzLite::ControllerBase
|
53
|
+
def index
|
54
|
+
@films = Film.all
|
55
|
+
end
|
56
|
+
|
57
|
+
def show
|
58
|
+
@film = Film.find(params['id'])
|
59
|
+
end
|
60
|
+
end
|
61
|
+
```
|
62
|
+
|
63
|
+
### Models
|
64
|
+
|
65
|
+
Models inherit from RailzLite::SQLObject. Please note that any class declaration must be ended with a finalize! statement
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
class Film < RailzLite::SQLObject
|
69
|
+
has_many :reviews, foreign_key: :film_id
|
70
|
+
def average_rating
|
71
|
+
ratings = reviews.map(&:rating)
|
72
|
+
return 0 if ratings.empty?
|
73
|
+
|
74
|
+
ratings.reduce(:+) / reviews.length
|
75
|
+
end
|
76
|
+
finalize!
|
77
|
+
end
|
78
|
+
```
|
79
|
+
|
80
|
+
### Views
|
81
|
+
|
82
|
+
Views use the rails convention for path-resolution. Also, they are required to end in a .erb extension, even if no embedded ruby is used.
|
83
|
+
|
84
|
+
ex. FilmsController#index corresponds to /views/films/index.html.erb
|
85
|
+
|
86
|
+
### Server + Routes
|
87
|
+
|
88
|
+
The server file can be found in config/server.
|
89
|
+
|
90
|
+
Routes are configured in the following structure
|
91
|
+
|
92
|
+
```
|
93
|
+
http_method, regex to match route, controller, action
|
94
|
+
```
|
95
|
+
|
96
|
+
Below is an example route config:
|
97
|
+
```ruby
|
98
|
+
router.draw do
|
99
|
+
# add routes here
|
100
|
+
get Regexp.new('^/films$'), FilmsController, :index
|
101
|
+
get Regexp.new("^/films/(?<id>\\d+)$"), FilmsController, :show
|
102
|
+
|
103
|
+
get Regexp.new("^/films/(?<film_id>\\d+)/reviews/new$"), ReviewsController, :new
|
104
|
+
post Regexp.new("^/films/(?<film_id>\\d+)/reviews$"), ReviewsController, :create
|
105
|
+
end
|
106
|
+
```
|
107
|
+
|
108
|
+
### Assets
|
109
|
+
|
110
|
+
Assets are served via the static middleware included within the framework. The default load paths for assets are "/public" and "/assets".
|
111
|
+
Any file within these two folders can be accessed in the app by specifying the root folder + the file name.
|
112
|
+
|
113
|
+
ex.) MyProject/public/balloons.jpg
|
114
|
+
|
115
|
+
```html
|
116
|
+
<h1>Congratulations!!! <img src="public/balloons.jpg" /></h1>
|
117
|
+
```
|
118
|
+
|
119
|
+
ex.) MyProject/assets/home.css
|
120
|
+
|
121
|
+
```html
|
122
|
+
<head>
|
123
|
+
<title>My Project</title>
|
124
|
+
<link rel="stylesheet" href="assets/application.css">
|
125
|
+
</head>
|
126
|
+
```
|
26
127
|
|
27
128
|
## Development
|
28
129
|
|
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
require_relative 'wrappers/pg_wrapper'
|
2
|
+
require_relative 'wrappers/sqlite3_wrapper'
|
2
3
|
|
3
4
|
class DBConnection
|
4
5
|
PRINT_QUERIES = ENV['PRINT_QUERIES'] == 'true'
|
@@ -10,22 +11,27 @@ class DBConnection
|
|
10
11
|
DBConnection.open(DB_FILE)
|
11
12
|
end
|
12
13
|
|
13
|
-
def self.open(
|
14
|
-
|
15
|
-
|
16
|
-
@db
|
14
|
+
def self.open(db_name) # for sqlite3 we need file.db, for postgresql we need database name
|
15
|
+
db_uri = ENV['DATABASE_URL']
|
16
|
+
|
17
|
+
@db = db_uri.nil? ? SQLite3Wrapper.new(db_name) : PGWrapper.new(db_uri)
|
17
18
|
|
18
19
|
@db
|
19
20
|
end
|
20
21
|
|
21
22
|
def self.reset
|
22
|
-
|
23
|
-
"rm '#{DB_FILE}'",
|
24
|
-
"cat '#{SQL_FILE}' | sqlite3 '#{DB_FILE}'"
|
25
|
-
]
|
23
|
+
db_uri = ENV['DATABASE_URL']
|
26
24
|
|
27
|
-
|
28
|
-
|
25
|
+
if db_uri.nil? # sqlite
|
26
|
+
commands = ["rm '#{DB_FILE}'", "cat '#{SQL_FILE}' | sqlite3 '#{DB_FILE}'"]
|
27
|
+
|
28
|
+
commands.each { |command| `#{command}` }
|
29
|
+
DBConnection.open(DB_FILE)
|
30
|
+
else # postgres
|
31
|
+
DBConnection.open(db_uri)
|
32
|
+
sql = File.read(SQL_FILE)
|
33
|
+
instance.execute(sql)
|
34
|
+
end
|
29
35
|
end
|
30
36
|
|
31
37
|
def self.instance
|
@@ -34,20 +40,25 @@ class DBConnection
|
|
34
40
|
@db
|
35
41
|
end
|
36
42
|
|
43
|
+
# results hash of results [{id: 1, name: 'Bob'}...]
|
37
44
|
def self.execute(*args)
|
38
45
|
print_query(*args)
|
39
46
|
instance.execute(*args)
|
40
47
|
end
|
41
48
|
|
49
|
+
# returns result with header fields [['id', 'name'...], { id: 1, name: 'Bob' ... }
|
42
50
|
def self.execute2(*args)
|
43
51
|
print_query(*args)
|
44
52
|
instance.execute2(*args)
|
45
53
|
end
|
46
54
|
|
47
|
-
|
48
|
-
|
55
|
+
# used to insert data into tables
|
56
|
+
def self.insert(*args)
|
57
|
+
print_query(*args)
|
58
|
+
instance.insert(*args)
|
49
59
|
end
|
50
60
|
|
61
|
+
|
51
62
|
private
|
52
63
|
|
53
64
|
def self.print_query(query, *interpolation_args)
|
@@ -82,13 +82,13 @@ module RailzLite
|
|
82
82
|
end
|
83
83
|
|
84
84
|
def insert
|
85
|
-
DBConnection.
|
85
|
+
last_row_id = DBConnection.insert(<<-SQL, *attribute_values)
|
86
86
|
INSERT INTO
|
87
87
|
#{self.class.table_name}(#{self.class.columns.join(',')})
|
88
88
|
VALUES
|
89
89
|
(#{(["?"] * attribute_values.length).join(',')})
|
90
90
|
SQL
|
91
|
-
self.id =
|
91
|
+
self.id = last_row_id
|
92
92
|
end
|
93
93
|
|
94
94
|
def update
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'pg'
|
2
|
+
|
3
|
+
class PGWrapper
|
4
|
+
def initialize(db_uri)
|
5
|
+
@db = PG::Connection.new(db_uri)
|
6
|
+
@db.type_map_for_results = PG::BasicTypeMapForResults.new(@db) # converts pgsql strings to ruby type
|
7
|
+
@db
|
8
|
+
end
|
9
|
+
|
10
|
+
def execute(sql, *args)
|
11
|
+
converted_sql = convert_escaped_question_marks(sql)
|
12
|
+
@db.exec_params(converted_sql, args).to_a
|
13
|
+
end
|
14
|
+
|
15
|
+
def execute2(sql, *args)
|
16
|
+
converted_sql = convert_escaped_question_marks(sql)
|
17
|
+
result = @db.exec_params(converted_sql, args)
|
18
|
+
[result.fields, result.to_a]
|
19
|
+
end
|
20
|
+
|
21
|
+
def insert(sql, *args)
|
22
|
+
sql.insert(sql.index(';'), ' RETURNING ID')
|
23
|
+
converted_sql = convert_escaped_question_marks(sql)
|
24
|
+
result = @db.exec_params(converted_sql, *args)
|
25
|
+
result.to_a.first['id']
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
# for pgsql, SELECT * FROM films WHERE x = ?; must be converted to SELECT * FROM films WHERE x = $1;
|
32
|
+
def convert_escaped_question_marks(sql)
|
33
|
+
converted_sql = ""
|
34
|
+
index = 1
|
35
|
+
sql.each_char do |char|
|
36
|
+
if char == '?'
|
37
|
+
converted_sql += "$#{index}"
|
38
|
+
index += 1
|
39
|
+
else
|
40
|
+
converted_sql += char
|
41
|
+
end
|
42
|
+
end
|
43
|
+
converted_sql
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'sqlite3'
|
2
|
+
|
3
|
+
class SQLite3Wrapper
|
4
|
+
def initialize(db_file_name)
|
5
|
+
@db = SQLite3::Database.new(db_file_name)
|
6
|
+
@db.results_as_hash = true
|
7
|
+
@db.type_translation = true
|
8
|
+
|
9
|
+
@db
|
10
|
+
end
|
11
|
+
|
12
|
+
def execute(*args)
|
13
|
+
@db.execute(*args)
|
14
|
+
end
|
15
|
+
|
16
|
+
def execute2(*args)
|
17
|
+
@db.execute2(*args)
|
18
|
+
end
|
19
|
+
|
20
|
+
def insert(*args)
|
21
|
+
execute(*args)
|
22
|
+
last_insert_row_id
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def self.last_insert_row_id
|
28
|
+
@db.last_insert_row_id
|
29
|
+
end
|
30
|
+
end
|
data/lib/railz_lite/version.rb
CHANGED
data/railz_lite.gemspec
CHANGED
@@ -33,6 +33,7 @@ Gem::Specification.new do |spec|
|
|
33
33
|
spec.add_dependency "activesupport", '~> 6.1.4'
|
34
34
|
spec.add_dependency "puma", '~> 5.3.2'
|
35
35
|
spec.add_dependency "sqlite3", '~> 1.4.2'
|
36
|
+
spec.add_dependency "pg", '~> 1.2.3'
|
36
37
|
spec.add_dependency "thor", '~> 1.1.0'
|
37
38
|
spec.add_dependency "loofah", '~> 2.10.0'
|
38
39
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: railz_lite
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- bryan lynch
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-07-
|
11
|
+
date: 2021-07-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: 1.4.2
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pg
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 1.2.3
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.2.3
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: thor
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -192,6 +206,8 @@ files:
|
|
192
206
|
- lib/railz_lite/models/searchable.rb
|
193
207
|
- lib/railz_lite/models/sql_object.rb
|
194
208
|
- lib/railz_lite/models/validatable.rb
|
209
|
+
- lib/railz_lite/models/wrappers/pg_wrapper.rb
|
210
|
+
- lib/railz_lite/models/wrappers/sqlite3_wrapper.rb
|
195
211
|
- lib/railz_lite/version.rb
|
196
212
|
- railz_lite.gemspec
|
197
213
|
homepage: https://github.com/bryanqb07/my_rails
|