railz_lite 0.2.7 → 0.2.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e77147f68729fb2f1b68f730aa31e1e50ca822df8990e6fb35ba9eb2e02cbf5d
4
- data.tar.gz: e96ec7817513298e3899cde8d3e9d3f43cbc97589302443db38c4ec8a993258b
3
+ metadata.gz: aff7d4d6f62b5eee1669eef62895d5170f55a5d3241db179191a690bb9dc26f1
4
+ data.tar.gz: 2ab955ed52a300dcf3c614e1a0c4bcbf9f0e8ef81613e2bae9aa7324f08980db
5
5
  SHA512:
6
- metadata.gz: 5968f44535f416c2524445365be98cacfe92894e1ed1079268cb8261ea0c44bd8101ad9f7fb62d84677fb0f2e5f57937f955144046bb1c399659b61c0065acb2
7
- data.tar.gz: 958a09155c32bd8707908f4a820a2cc5e8f4116e0d90fa91c44ca24855827df3e4819ab31a410beffeb866615013418012890bab1237d105e0e9111bba4664ac
6
+ metadata.gz: 0b6b915059bf4ed2ce158b1b6eef235fb742cac8fa3a416bdd88df3d4183510c632021181cec277551e86b3142253bf09732d6aed1954cf1c92b08c820c02b2b
7
+ data.tar.gz: 7118f1462ba3e8d772d4e64bfea0304f8cae53cebd073d9b38c97e318a3129f42bf5560369c96f7edc7b916b9a1e77e22d7d713c18ed31526a189f080f00c25b
data/README.md CHANGED
@@ -1,8 +1,30 @@
1
1
  # RailzLite
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/railz_lite`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ A lite-weight Ruby gem inspired by Ruby on Rails.
4
4
 
5
- TODO: Delete this and the text above, and describe your gem
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
- TODO: Write usage instructions here
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
- require 'sqlite3'
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(db_file_name)
14
- @db = SQLite3::Database.new(db_file_name)
15
- @db.results_as_hash = true
16
- @db.type_translation = true
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
- commands = [
23
- "rm '#{DB_FILE}'",
24
- "cat '#{SQL_FILE}' | sqlite3 '#{DB_FILE}'"
25
- ]
23
+ db_uri = ENV['DATABASE_URL']
26
24
 
27
- commands.each { |command| `#{command}` }
28
- DBConnection.open(DB_FILE)
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
- def self.last_insert_row_id
48
- instance.last_insert_row_id
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.execute(<<-SQL, *attribute_values)
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 = DBConnection.last_insert_row_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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailzLite
4
- VERSION = "0.2.7"
4
+ VERSION = "0.2.8"
5
5
  end
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.7
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-03 00:00:00.000000000 Z
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