jetski 0.4.0 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ffe71a8de5f4201c446a70331fae92f982af3887b388426e5b64f1b6c3d897c8
4
- data.tar.gz: 73a1faada7420962abfdbab298f7f81157431b995452ca5fc2adefd903d074ec
3
+ metadata.gz: a7f1033d352171f7ccf893f673b76ed6f847c404b0aa460812fe60dc4ce0883a
4
+ data.tar.gz: 88b3a07a229f606c2599c6f728423a584b1c242441217f6c04d14c9b1dd8e873
5
5
  SHA512:
6
- metadata.gz: 35e4cfce787089dfe046575b38969927013e09a91b855dee64af15394872eed1660a087ecdd801fb4c0ede590b491da3759b5d68f1ff2c92a49363426f5a8f38
7
- data.tar.gz: '049857042cd6299e591dab667ef9f3943637649905fe77e09174eabdc3a1131abb9849e93e35f07adb32d9c09dda067ffc19c8d671ddade29715d74ff0c9acfa'
6
+ metadata.gz: dcce62044cc495b3e39645033c102a5146d39d7a00ecd3dc151d75aed67eda8f0c757323bb426c743cd8873cfa9e33945fbf8881b579853e872a61af524a4473
7
+ data.tar.gz: 2edf2994dd5a44423f48d4a9d2059e6508d2a1f766d0310597ffb7e7e6d975df0fcf0ef66ae6c7168c68e78baa41fc9bd6cfa9d293ce662b4c699909b5039d2a
data/bin/jetski CHANGED
@@ -3,8 +3,14 @@
3
3
  require 'jetski'
4
4
  require 'optparse'
5
5
  require 'thor'
6
+ require "sqlite3"
7
+ require "pry"
8
+
9
+ require_relative './jetski_cli_helpers/shared_methods.rb'
6
10
  require_relative './jetski_cli_helpers/generate.rb'
7
11
  require_relative './jetski_cli_helpers/destroy.rb'
12
+ require_relative './jetski_cli_helpers/database.rb'
13
+
8
14
  require 'bundler/setup'
9
15
 
10
16
  class JetskiCLI < Thor
@@ -40,11 +46,22 @@ class JetskiCLI < Thor
40
46
  Jetski::Server.new.call
41
47
  end
42
48
 
49
+ desc "console", "opens jetski console"
50
+ def console
51
+ # TODO: Open console and include all controllers/models/etc
52
+ Jetski::Autoloader.call
53
+ Jetski::Autoloader.load_controllers
54
+ Pry.start
55
+ end
56
+
43
57
  desc "generate", "generates resources in your jetski app"
44
58
  subcommand "generate", JetskiCLIHelpers::Generate
45
59
 
46
60
  desc "destroy", "destroys a resource in your jetski app"
47
61
  subcommand "destroy", JetskiCLIHelpers::Destroy
62
+
63
+ desc "db", "commands related to database"
64
+ subcommand "db", JetskiCLIHelpers::Database
48
65
 
49
66
  def self.source_root
50
67
  File.join(File.dirname(__FILE__), 'templates')
@@ -0,0 +1,27 @@
1
+ require 'thor'
2
+ module JetskiCLIHelpers
3
+ class Database < Thor
4
+ include Thor::Actions, JetskiCLIHelpers::SharedMethods,
5
+ Jetski::Database::Base
6
+ desc "create", "Creates a database for your app"
7
+ def create
8
+ say "🌊 Database was created successfully!"
9
+ end
10
+
11
+ desc "create_table NAME COLUMN_NAMES", "Creates a new table in your database"
12
+ def create_table(name, *fields)
13
+ db.execute create_table_sql(table_name: name, field_names: fields)
14
+ end
15
+
16
+ desc "seed", "Seeds the database with records created from seed file"
17
+ def seed
18
+ seed_file_path = './seed.rb'
19
+ if File.exist?(seed_file_path)
20
+ Jetski::Autoloader.call
21
+ load(seed_file_path)
22
+ else
23
+ say "No seed file is specified create one in your app ./seed.rb"
24
+ end
25
+ end
26
+ end
27
+ end
@@ -9,5 +9,12 @@ module JetskiCLIHelpers
9
9
  view_folder = "app/views/#{name}"
10
10
  remove_dir(view_folder)
11
11
  end
12
+
13
+ desc "model NAME ACTION_NAMES", "Destroys a model"
14
+ def model(name, *actions)
15
+ model_file_path = "app/models/#{name}.rb"
16
+ remove_file(controller_file_path)
17
+ # TODO: Remove from db.
18
+ end
12
19
  end
13
20
  end
@@ -1,7 +1,8 @@
1
1
  require 'thor'
2
2
  module JetskiCLIHelpers
3
3
  class Generate < Thor
4
- include Thor::Actions
4
+ include Thor::Actions, JetskiCLIHelpers::SharedMethods,
5
+ Jetski::Database::Base
5
6
  desc "controller NAME ACTION_NAMES", "Create a controller with matching actions"
6
7
  def controller(name, *actions)
7
8
  controller_file_path = "app/controllers/#{name}_controller.rb"
@@ -18,23 +19,34 @@ module JetskiCLIHelpers
18
19
 
19
20
  end
20
21
  ACTION_CONTENT
21
- insert_into_file(controller_file_path, indent_code(action_content, 1), before: "\nend")
22
- path_to_view = "app/views/#{name}/#{action_name}.html.erb"
22
+ action_nl_seperator = ((idx + 1) != actions.size) ? "\n\n" : ""
23
+ insert_into_file(controller_file_path, "#{indent_code(action_content, 1)}#{action_nl_seperator}", before: "\nend")
24
+
25
+ if !["create", "create", "update", "destroy"].include?(action_name)
26
+ path_to_view = "app/views/#{name}/#{action_name}.html.erb"
23
27
 
24
- empty_directory("app/views/#{name}")
25
- create_file(path_to_view)
26
- append_to_file path_to_view, <<~EXAMPLEFILE
27
- <h1> #{name}##{action_name} </h1>
28
- <p> edit the content of this page at app/views/#{path_to_view}/#{action_name}.html.erb </p>
29
- EXAMPLEFILE
30
-
31
- say "🌊 View your new page at http://localhost:8000/#{name}/#{action_name}"
28
+ empty_directory("app/views/#{name}")
29
+ create_file(path_to_view)
30
+ append_to_file path_to_view, <<~EXAMPLEFILE
31
+ <h1> #{name}##{action_name} </h1>
32
+ <p> edit the content of this page at app/views/#{path_to_view}/#{action_name}.html.erb </p>
33
+ EXAMPLEFILE
34
+
35
+ say "🌊 View your new page at http://localhost:8000/#{name}/#{action_name}"
36
+ end
32
37
  end
33
38
  end
34
-
35
- private
36
- def indent_code(code, level = 1)
37
- code.strip.split("\n").map { |l| (1..level).map { |lvl| " " }.join + l }.join("\n")
39
+
40
+ desc "model NAME FIELD_NAMES", "Creates a model with matching fields"
41
+ def model(name, *field_names)
42
+ db.execute create_table_sql(table_name: name, field_names: field_names)
43
+ model_file_path = "app/models/#{name}.rb"
44
+ create_file model_file_path
45
+ append_to_file model_file_path, <<~MODEL
46
+ class #{name.capitalize} < Jetski::Model
47
+
48
+ end
49
+ MODEL
38
50
  end
39
51
  end
40
52
  end
@@ -0,0 +1,8 @@
1
+ module JetskiCLIHelpers
2
+ module SharedMethods
3
+ def indent_code(code, level = 1)
4
+ code.strip.split("\n").map { |l|
5
+ (1..level).map { |lvl| " " }.join + l }.join("\n")
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,18 @@
1
+ module Jetski
2
+ module Autoloader
3
+ include Jetski::Router::SharedMethods
4
+ extend self
5
+ # Responsibility is to load all models in app.
6
+ def call
7
+ model_file_paths.each do |path_to_model|
8
+ require_relative path_to_model
9
+ end
10
+ end
11
+
12
+ def load_controllers
13
+ controller_file_paths.each do |file_path|
14
+ require_relative file_path
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,25 +1,12 @@
1
1
  # This is the base controller of the library
2
2
  module Jetski
3
3
  class BaseController
4
- attr_accessor :action_name, :controller_name, :controller_path, :params
5
- attr_reader :res
6
- attr_reader :performed_render
4
+ include ReactiveForm
5
+ attr_accessor :action_name, :controller_name, :controller_path,
6
+ :params, :cookies
7
+ attr_reader :res, :performed_render
7
8
  attr_writer :root, :path, :request_method
8
9
 
9
- class << self
10
- def request_method(method)
11
- # Really just a shell method since Im using File.readlines to use the logic in routes.
12
- end
13
-
14
- def root
15
- # another shell method
16
- end
17
-
18
- def path(location)
19
- # Another shell method
20
- end
21
- end
22
-
23
10
  def initialize(res)
24
11
  @res = res
25
12
  @performed_render = false
@@ -51,6 +38,14 @@ module Jetski
51
38
  res.set_redirect(WEBrick::HTTPStatus::Found, url)
52
39
  end
53
40
 
41
+ def set_cookie(name, value)
42
+ res.cookies.push WEBrick::Cookie.new(name.to_s, value || "")
43
+ end
44
+
45
+ def get_cookie(name)
46
+ cookies&.find { |c| c.name == name.to_s }&.value
47
+ end
48
+
54
49
  def is_root?
55
50
  @root == true
56
51
  end
@@ -99,6 +94,9 @@ module Jetski
99
94
  _content_for_head += "<script src='/#{path_to_controller}.js' defer></script>\n"
100
95
  end
101
96
 
97
+ # Add reactive form JS code
98
+ _content_for_head += "<script src='/reactive-form.js' defer></script>\n"
99
+
102
100
  _content_for_head
103
101
  end
104
102
 
@@ -0,0 +1,51 @@
1
+ module Jetski
2
+ module Database
3
+ module Base
4
+ extend self
5
+
6
+ def db
7
+ @_db ||= SQLite3::Database.new "test.db"
8
+ end
9
+
10
+ def create_table_sql(table_name:, field_names:)
11
+ pluralized_table_name = if table_name.chars.last == "s"
12
+ table_name
13
+ else
14
+ table_name + "s"
15
+ end
16
+
17
+ _gen_sql = ""
18
+ _gen_sql += "create table #{pluralized_table_name} (\n"
19
+ _gen_sql += " created_at datetime,\n"
20
+ _gen_sql += " updated_at datetime,\n"
21
+ _gen_sql += " id integer,\n"
22
+
23
+ field_names.each.with_index do |field_name, idx|
24
+ field, field_data_type = if field_name.include?(":")
25
+ field_name.split(":")
26
+ else
27
+ [field_name, ""]
28
+ end
29
+ data_type = sql_data_type(field_data_type)
30
+ _gen_sql += " #{field} #{data_type}"
31
+ if (idx + 1) < field_names.size
32
+ _gen_sql += ",\n"
33
+ else
34
+ _gen_sql += "\n"
35
+ end
36
+ end
37
+ _gen_sql += ");\n"
38
+ _gen_sql
39
+ end
40
+
41
+ def sql_data_type(str)
42
+ case str
43
+ when "", "string"
44
+ "varchar(255)"
45
+ else
46
+ str
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,12 @@
1
+ let reactiveFormELS = document.querySelectorAll("[reactive-form-path]")
2
+ reactiveFormELS.forEach(reactiveFormElement => {
3
+ reactiveFormElement.addEventListener("input", () => {
4
+ let reactiveFormURL = reactiveFormElement.getAttribute("reactive-form-path")
5
+ fetch(reactiveFormURL, {
6
+ body: JSON.stringify({
7
+ content: reactiveFormElement.value,
8
+ }),
9
+ method: "POST",
10
+ })
11
+ })
12
+ })
@@ -0,0 +1,8 @@
1
+ module ReactiveForm
2
+ def reactive_text_area(path, **opts)
3
+ css_classes = opts[:class]
4
+ value = opts[:value]
5
+ # Text area that auto saves to url.
6
+ "<textarea reactive-form-path='#{path}' class='#{css_classes}'>#{value}</textarea>"
7
+ end
8
+ end
@@ -0,0 +1,74 @@
1
+ module Jetski
2
+ class Model
3
+ extend Jetski::Database::Base
4
+ class << self
5
+ def create(**args)
6
+ return puts "#{table_name.capitalize}.create was called with no args" if args.size == 0
7
+ data_values = args.map { |k,v| v }
8
+ key_names = args.map { |k, v| k }
9
+
10
+ key_names.append "created_at"
11
+ data_values.append Time.now.to_s
12
+
13
+ sql_command = <<~SQL
14
+ INSERT INTO #{pluralized_table_name} (#{key_names.join(", ")})
15
+ VALUES (#{(1..key_names.size).map { |n| "?" }.join(", ")})
16
+ SQL
17
+
18
+ db.execute(sql_command, data_values)
19
+ end
20
+
21
+ def all
22
+ columns, *rows = db.execute2( "select * from #{pluralized_table_name}" )
23
+ _all = []
24
+ rows.map do |row|
25
+ _all << format_model_obj(row, columns)
26
+ end
27
+ _all
28
+ end
29
+
30
+ def pluck_rows
31
+ db.execute( "select * from #{pluralized_table_name}" )
32
+ end
33
+
34
+ def count
35
+ pluck_rows.size
36
+ end
37
+
38
+ def attributes
39
+ columns, *rows = db.execute2( "select * from #{pluralized_table_name}" )
40
+ columns
41
+ end
42
+
43
+ def last
44
+ format_model_obj(pluck_rows.last)
45
+ end
46
+
47
+ def first
48
+ format_model_obj(pluck_rows.first)
49
+ end
50
+ private
51
+ def table_name
52
+ self.to_s.downcase
53
+ end
54
+
55
+ def pluralized_table_name
56
+ if table_name[-1] == "s"
57
+ table_name
58
+ else
59
+ table_name + "s"
60
+ end
61
+ end
62
+
63
+ def format_model_obj(row, columns = nil)
64
+ return unless row
65
+ columns ||= attributes
66
+ row_obj = {}
67
+ columns.each.with_index do |col, idx|
68
+ row_obj[col] = row[idx]
69
+ end
70
+ OpenStruct.new(row_obj)
71
+ end
72
+ end
73
+ end
74
+ end
@@ -1,10 +1,10 @@
1
1
  module Jetski
2
2
  class Router
3
3
  module Parser
4
+ include Jetski::Router::SharedMethods
4
5
  extend self
5
6
  def compile_routes
6
7
  auto_found_routes = []
7
- controller_file_paths = Dir.glob([File.join(Jetski.app_root, 'app', 'controllers', '**', '*_controller.rb')])
8
8
  controller_file_paths.each do |file_path|
9
9
  require_relative file_path
10
10
  controller_file_name = file_path.split('app/controllers')[1]
@@ -0,0 +1,13 @@
1
+ module Jetski
2
+ class Router
3
+ module SharedMethods
4
+ def controller_file_paths
5
+ Dir.glob([File.join(Jetski.app_root, 'app', 'controllers', '**', '*_controller.rb')])
6
+ end
7
+
8
+ def model_file_paths
9
+ Dir.glob(File.join(Jetski.app_root, 'app', 'models', '**/*.rb'))
10
+ end
11
+ end
12
+ end
13
+ end
data/lib/jetski/router.rb CHANGED
@@ -41,7 +41,12 @@ module Jetski
41
41
  controller.action_name = action_name
42
42
  controller.controller_name = controller_name
43
43
  controller.controller_path = controller_path
44
- controller.params = OpenStruct.new(JSON.parse(req.body)) if req.body
44
+ # TODO: Check how body is being passed in and parse it correctly.
45
+ # Currently is breaking with regular html form submissions
46
+ if req.body
47
+ controller.params = parse_body(req.body, req.content_type)
48
+ end
49
+ controller.cookies = req.cookies
45
50
  controller.send(action_name)
46
51
  if !controller.performed_render && (request_method.upcase == "GET")
47
52
  controller.render
@@ -56,8 +61,7 @@ module Jetski
56
61
  end
57
62
 
58
63
  def host_assets
59
- # Render stylesheets css via url
60
- host_css && host_images && host_javascript
64
+ host_css && host_images && host_javascript && host_reactive_form_js
61
65
  end
62
66
 
63
67
  def host_css
@@ -73,8 +77,7 @@ module Jetski
73
77
  end
74
78
 
75
79
  def host_images
76
- # TODO: Expand this to support more types of images.
77
- file_ext_types = ["png", "jpg"]
80
+ file_ext_types = ["png", "jpg"] # TODO: Expand this to support more types of images.
78
81
  image_files = Dir.glob(
79
82
  file_ext_types.map { |ext| File.join(Jetski.app_root, "app/assets/images/*.#{ext}") }
80
83
  )
@@ -99,5 +102,23 @@ module Jetski
99
102
  end
100
103
  end
101
104
  end
105
+
106
+ def host_reactive_form_js
107
+ server.mount_proc "/reactive-form.js" do |req, res|
108
+ res.content_type = "text/javascript"
109
+ res.body = File.read(File.join(__dir__, 'frontend/reactive_form.js'))
110
+ end
111
+ end
112
+ private
113
+ def parse_body(body, content_type = '')
114
+ case content_type
115
+ when "application/x-www-form-urlencoded"
116
+ Rack::Utils.parse_nested_query body
117
+ when "application/json"
118
+ OpenStruct.new(JSON.parse(body))
119
+ else
120
+ body
121
+ end
122
+ end
102
123
  end
103
124
  end
data/lib/jetski/server.rb CHANGED
@@ -6,6 +6,8 @@ module Jetski
6
6
  def call
7
7
  server = WEBrick::HTTPServer.new Port: 8000
8
8
 
9
+ Jetski::Autoloader.call
10
+
9
11
  Jetski::Router.new(server).call
10
12
 
11
13
  trap 'INT' do server.shutdown end
@@ -1,3 +1,3 @@
1
1
  module Jetski
2
- VERSION = "0.4.0"
2
+ VERSION = "0.4.1"
3
3
  end
data/lib/jetski.rb CHANGED
@@ -3,12 +3,18 @@ require "json"
3
3
  require "json"
4
4
  require "ostruct"
5
5
  require "erb"
6
+ require "rack"
6
7
 
7
8
  require_relative './jetski/version'
9
+ require_relative './jetski/frontend/reactive_form'
8
10
  require_relative './jetski/base_controller'
9
- require_relative './jetski/server'
11
+ require_relative './jetski/router/shared_methods'
10
12
  require_relative './jetski/router/parser'
11
13
  require_relative './jetski/router'
14
+ require_relative './jetski/autoloader'
15
+ require_relative './jetski/server'
16
+ require_relative './jetski/database/base'
17
+ require_relative './jetski/model'
12
18
 
13
19
  module Jetski
14
20
  extend self
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jetski
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Indigo Tech Tutorials
@@ -65,6 +65,48 @@ dependencies:
65
65
  - - "~>"
66
66
  - !ruby/object:Gem::Version
67
67
  version: 5.1.2
68
+ - !ruby/object:Gem::Dependency
69
+ name: sqlite3
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: 2.8.0
75
+ type: :runtime
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: 2.8.0
82
+ - !ruby/object:Gem::Dependency
83
+ name: pry
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: 0.15.2
89
+ type: :runtime
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: 0.15.2
96
+ - !ruby/object:Gem::Dependency
97
+ name: rack
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: 3.2.4
103
+ type: :runtime
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: 3.2.4
68
110
  description: 'Would you rather ride on a train or a jetski? that is the question you
69
111
  might use when comparing using our framework or the popular Ruby on Rails framework. '
70
112
  email: indigo@tech.tut
@@ -74,8 +116,10 @@ extensions: []
74
116
  extra_rdoc_files: []
75
117
  files:
76
118
  - bin/jetski
119
+ - bin/jetski_cli_helpers/database.rb
77
120
  - bin/jetski_cli_helpers/destroy.rb
78
121
  - bin/jetski_cli_helpers/generate.rb
122
+ - bin/jetski_cli_helpers/shared_methods.rb
79
123
  - bin/templates/base/Gemfile
80
124
  - bin/templates/base/app/assets/images/jetski-logo.png
81
125
  - bin/templates/base/app/assets/javascript/application.js
@@ -85,9 +129,15 @@ files:
85
129
  - bin/templates/base/app/views/layouts/application.html.erb
86
130
  - bin/templates/base/app/views/pages/home.html.erb
87
131
  - lib/jetski.rb
132
+ - lib/jetski/autoloader.rb
88
133
  - lib/jetski/base_controller.rb
134
+ - lib/jetski/database/base.rb
135
+ - lib/jetski/frontend/reactive_form.js
136
+ - lib/jetski/frontend/reactive_form.rb
137
+ - lib/jetski/model.rb
89
138
  - lib/jetski/router.rb
90
139
  - lib/jetski/router/parser.rb
140
+ - lib/jetski/router/shared_methods.rb
91
141
  - lib/jetski/server.rb
92
142
  - lib/jetski/version.rb
93
143
  homepage: https://rubygems.org/gems/jetski