jetski 0.4.9 → 0.5.0

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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/bin/jetski +1 -0
  3. data/bin/jetski_cli_helpers/base.rb +11 -0
  4. data/bin/jetski_cli_helpers/database.rb +16 -11
  5. data/bin/jetski_cli_helpers/destroy.rb +8 -2
  6. data/bin/jetski_cli_helpers/destroyers/controller.rb +3 -8
  7. data/bin/jetski_cli_helpers/destroyers/model.rb +4 -2
  8. data/bin/jetski_cli_helpers/generate.rb +3 -4
  9. data/bin/jetski_cli_helpers/generators/controller.rb +28 -33
  10. data/bin/jetski_cli_helpers/generators/model.rb +21 -7
  11. data/lib/jetski/autoloader.rb +1 -5
  12. data/lib/jetski/base_controller.rb +2 -2
  13. data/lib/jetski/database/base.rb +8 -30
  14. data/lib/jetski/database/interface.rb +31 -0
  15. data/lib/jetski/database/sqlite3.rb +6 -0
  16. data/lib/jetski/frontend/javascript_helpers.rb +12 -0
  17. data/lib/jetski/helpers/delegatable.rb +1 -1
  18. data/lib/jetski/helpers/generic.rb +14 -0
  19. data/lib/jetski/helpers/route_helpers.rb +1 -1
  20. data/lib/jetski/helpers/view_helpers.rb +2 -2
  21. data/lib/jetski/model/attributes.rb +46 -0
  22. data/lib/jetski/model/crud_helpers.rb +76 -0
  23. data/lib/jetski/model.rb +14 -108
  24. data/lib/jetski/router/file_path_helper.rb +1 -1
  25. data/lib/jetski/router/host/base.rb +1 -1
  26. data/lib/jetski/router/host/controller.rb +4 -2
  27. data/lib/jetski/router/host/crud.rb +4 -5
  28. data/lib/jetski/router/parser.rb +1 -1
  29. data/lib/jetski/router.rb +4 -6
  30. data/lib/jetski/server.rb +1 -1
  31. data/lib/jetski/version.rb +2 -2
  32. data/lib/jetski/view_renderer.rb +2 -4
  33. data/lib/jetski.rb +9 -4
  34. data/templates/controllers/controller.rb.erb +56 -0
  35. data/templates/controllers/views/default.html.erb +2 -0
  36. data/templates/controllers/views/edit.html.erb +7 -0
  37. data/templates/controllers/views/index.html.erb +12 -0
  38. data/templates/controllers/views/new.html.erb +7 -0
  39. data/templates/controllers/views/show.html.erb +8 -0
  40. data/templates/model/template.rb.erb +5 -0
  41. metadata +22 -9
  42. data/lib/jetski/frontend/reactive_form.rb +0 -8
  43. /data/lib/jetski/frontend/{reactive_form.js → javascript_helpers.js} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 147bd3b0e3d8cbbf54b2a4163fe00af53e3941e99942c6d91324e034aaee7f88
4
- data.tar.gz: 21042af9af87651f01bc4b3b01ed6bb95d45990abcc9ff6fa1bea68b8b38bd68
3
+ metadata.gz: 0fba85e1a50746a7e376738a0ec5648ce22edcc7874ea0d9ee9b3be681d7364d
4
+ data.tar.gz: b3ac634c65fd946fb1dc43c62702b620b46dd17e1369ef0716eedfa6885e373d
5
5
  SHA512:
6
- metadata.gz: 7b045263bc0e38b3e733d0552d7884a5648351a38ba422e8aee9f2604f56d94ef8a9409113aaa377d4828888787587e6b98bc90e6693e7cfcaf63bd5e11a99e6
7
- data.tar.gz: 6c82897a30e17b21c3b7cb0a626b2cf5240124da8ea197e91c18ff3527e2da93965f456feffcd26c760d40e56534e13c770206de1b712998d2e8c0e4f3496237
6
+ metadata.gz: 9740af48073b1a0c8c069d834e2da63c7b351b5a84c5c77502348854c1164105a1002282c8036fa2eaa040cbf085b9e8e8a1ffb98c4b16a87208ca33dccd544c
7
+ data.tar.gz: cc288a4e32d8dff6c78c14baad4fb317049b2329d30a05bb3132ad1e054db0bf7a0924fec502720b7ae80a7e99d047ee2c364f1e1c5327d81244ddbb2734c6e1
data/bin/jetski CHANGED
@@ -10,6 +10,7 @@ require_relative './jetski_cli_helpers/generators/model.rb'
10
10
  require_relative './jetski_cli_helpers/destroyers/controller.rb'
11
11
  require_relative './jetski_cli_helpers/destroyers/model.rb'
12
12
  require_relative './jetski_cli_helpers/shared_methods.rb'
13
+ require_relative './jetski_cli_helpers/base.rb'
13
14
  require_relative './jetski_cli_helpers/generate.rb'
14
15
  require_relative './jetski_cli_helpers/destroy.rb'
15
16
  require_relative './jetski_cli_helpers/database.rb'
@@ -0,0 +1,11 @@
1
+ # Reason for this is to dry up code and includes between classes
2
+ module JetskiCLIHelpers
3
+ class Base < Thor
4
+ include Jetski::Helpers::Generic, Thor::Actions, JetskiCLIHelpers::SharedMethods,
5
+ Jetski::Database::Base, Jetski::Database::Interface
6
+
7
+ def self.source_root
8
+ File.join(File.dirname(__FILE__), '..', '..', 'templates')
9
+ end
10
+ end
11
+ end
@@ -1,15 +1,20 @@
1
1
  module JetskiCLIHelpers
2
- class Database < Thor
3
- include Thor::Actions, JetskiCLIHelpers::SharedMethods,
4
- Jetski::Database::Base
5
- desc "create", "Creates a database for your app"
6
- def create
7
- say "🌊 Database was created successfully!"
8
- end
9
-
10
- desc "create_table NAME COLUMN_NAMES", "Creates a new table in your database"
11
- def create_table(name, *fields)
12
- db.execute create_table_sql(table_name: name, field_names: fields)
2
+ class Database < Base
3
+ desc "migrate", "Create, load, and patch DB from models"
4
+ def migrate
5
+ Jetski::Autoloader.call
6
+ # Get all models defined in users app
7
+ Jetski::Model.subclasses.each do |model|
8
+ table_name = model.pluralized_table_name
9
+ # Create table if it doesnt exist
10
+ create_table(table_name) if !table_exists?(table_name)
11
+ # Get model attributes
12
+ model.db_attribute_values.each do |obj|
13
+ name = obj[:name]
14
+ type = obj[:type]
15
+ add_column_unless_exists(table_name, name, type)
16
+ end
17
+ end
13
18
  end
14
19
 
15
20
  desc "seed", "Seeds the database with records created from seed file"
@@ -1,6 +1,6 @@
1
1
  module JetskiCLIHelpers
2
- class Destroy < Thor
3
- include Thor::Actions, JetskiCLIHelpers::Destroyers::Controller,
2
+ class Destroy < Base
3
+ include JetskiCLIHelpers::Destroyers::Controller,
4
4
  JetskiCLIHelpers::Destroyers::Model
5
5
  desc "controller NAME ACTION_NAMES", "Destroys a controller"
6
6
  def controller(name, *actions)
@@ -11,5 +11,11 @@ module JetskiCLIHelpers
11
11
  def model(name, *actions)
12
12
  destroy_model(name)
13
13
  end
14
+
15
+ desc "resource NAME ACTION_NAMES", "Destroys a resource"
16
+ def resource(name, *actions)
17
+ destroy_controller(name)
18
+ destroy_model(name)
19
+ end
14
20
  end
15
21
  end
@@ -2,15 +2,10 @@ module JetskiCLIHelpers
2
2
  module Destroyers
3
3
  module Controller
4
4
  def destroy_controller(name)
5
- pluralized_name = if name[-1] == 's'
6
- name
7
- else
8
- name + 's'
9
- end
10
-
11
- controller_file_path = "app/controllers/#{pluralized_name}_controller.rb"
5
+ controller_name = pluralize_string(name)
6
+ controller_file_path = "app/controllers/#{controller_name}_controller.rb"
12
7
  remove_file(controller_file_path)
13
- view_folder = "app/views/#{pluralized_name}"
8
+ view_folder = "app/views/#{controller_name}"
14
9
  remove_dir(view_folder)
15
10
  end
16
11
  end
@@ -3,8 +3,10 @@ module JetskiCLIHelpers
3
3
  module Model
4
4
  def destroy_model(name)
5
5
  model_file_path = "app/models/#{name}.rb"
6
- remove_file(controller_file_path)
7
- # TODO: Remove from db.
6
+ remove_file(model_file_path)
7
+ table_name = pluralize_string(name)
8
+ remove_table_sql = "DROP TABLE #{table_name}"
9
+ db.execute(remove_table_sql)
8
10
  end
9
11
  end
10
12
  end
@@ -1,7 +1,6 @@
1
1
  module JetskiCLIHelpers
2
- class Generate < Thor
3
- include Thor::Actions, JetskiCLIHelpers::SharedMethods,
4
- Jetski::Database::Base, JetskiCLIHelpers::Generators::Controller,
2
+ class Generate < Base
3
+ include JetskiCLIHelpers::Generators::Controller,
5
4
  JetskiCLIHelpers::Generators::Model
6
5
  desc "controller NAME ACTION_NAMES", "Create a controller with matching actions"
7
6
  def controller(name, *actions)
@@ -17,7 +16,7 @@ module JetskiCLIHelpers
17
16
  def resource(name, *field_names)
18
17
  crud_actions = %w(new create show index edit update destroy)
19
18
  generate_model(name, *field_names)
20
- generate_controller(name, *crud_actions)
19
+ generate_controller(name, *crud_actions, field_names: field_names)
21
20
  end
22
21
  end
23
22
  end
@@ -1,42 +1,37 @@
1
1
  module JetskiCLIHelpers
2
2
  module Generators
3
3
  module Controller
4
- def generate_controller(name, *actions)
5
- pluralized_name = if name[-1] == 's'
6
- name
7
- else
8
- name + 's'
9
- end
10
-
11
- formatted_controller_name = pluralized_name.split("_").map(&:capitalize).join
12
- controller_file_path = "app/controllers/#{pluralized_name}_controller.rb"
13
- create_file controller_file_path
14
- append_to_file controller_file_path, <<~CONTROLLER
15
- class #{formatted_controller_name}Controller < Jetski::BaseController
4
+ def generate_controller(name, *actions, **extra_options)
5
+ field_names = extra_options[:field_names]
6
+ @name = name
7
+ @controller_name = pluralize_string(name)
16
8
 
17
- end
18
- CONTROLLER
9
+ controller_file_path = "app/controllers/#{@controller_name}_controller.rb"
10
+
11
+ @controller_class_name = @controller_name.split("_").map(&:capitalize).join
12
+ @model_class_name = @name.capitalize # post -> Post
13
+ @field_names = field_names
14
+ @actions = actions
19
15
 
20
- actions.each.with_index do |action_name, idx|
21
- action_content = <<~ACTION_CONTENT
22
- def #{action_name}
23
-
24
- end
25
- ACTION_CONTENT
26
- action_nl_seperator = ((idx + 1) != actions.size) ? "\n\n" : ""
27
- insert_into_file(controller_file_path, "#{indent_code(action_content, 1)}#{action_nl_seperator}", before: "\nend")
28
-
16
+ # Create controller from template
17
+ template "controllers/controller.rb.erb", controller_file_path
18
+
19
+ actions.each do |action_name|
20
+ # create views
29
21
  if !["create", "create", "update", "destroy"].include?(action_name)
30
- path_to_view = "app/views/#{pluralized_name}/#{action_name}.html.erb"
31
-
32
- empty_directory("app/views/#{pluralized_name}")
33
- create_file(path_to_view)
34
- append_to_file path_to_view, <<~EXAMPLEFILE
35
- <h1> #{pluralized_name}##{action_name} </h1>
36
- <p> edit the content of this page at app/views/#{path_to_view}/#{action_name}.html.erb </p>
37
- EXAMPLEFILE
38
-
39
- say "🌊 View your new page at http://localhost:8000/#{pluralized_name}/#{action_name}"
22
+ empty_directory("app/views/#{@controller_name}")
23
+
24
+ # For new, show, edit, index actions
25
+ @path_to_view = "app/views/#{@controller_name}/#{action_name}.html.erb"
26
+
27
+ template_name = if ["new", "show", "edit", "index"].include?(action_name)
28
+ action_name
29
+ else
30
+ "default"
31
+ end
32
+ @action_name = action_name
33
+ template "controllers/views/#{template_name}.html.erb", @path_to_view
34
+ say "🌊 View your new page at http://localhost:8000/#{@controller_name}/#{action_name}"
40
35
  end
41
36
  end
42
37
  end
@@ -2,14 +2,28 @@ module JetskiCLIHelpers
2
2
  module Generators
3
3
  module Model
4
4
  def generate_model(name, *field_names)
5
- db.execute create_table_sql(table_name: name, field_names: field_names)
6
- model_file_path = "app/models/#{name}.rb"
7
- create_file model_file_path
8
- append_to_file model_file_path, <<~MODEL
9
- class #{name.capitalize} < Jetski::Model
10
-
5
+ # TODO: Instead of creating table here we should have a db:migrate method
6
+ # this will automatically build and patch db tables. Add/remove columns
7
+ #db.execute create_table_sql(table_name: name, field_names: field_names)
8
+ @model_name = name
9
+
10
+
11
+ if field_names
12
+ @model_attributes = []
13
+ custom_fields = field_names.filter { |f| f.include?(":") }
14
+ string_fields = field_names - custom_fields
15
+ string_fields.each do |field|
16
+ @model_attributes << ":#{field}"
11
17
  end
12
- MODEL
18
+
19
+ custom_fields.each do |custom_field|
20
+ field, type = custom_field.split(":")
21
+ @model_attributes << "#{field}: :#{type}"
22
+ end
23
+ end
24
+
25
+ model_file_path = "app/models/#{name}.rb"
26
+ template "model/template.rb.erb", model_file_path
13
27
  end
14
28
  end
15
29
  end
@@ -1,4 +1,4 @@
1
- module Jetski
1
+ class Jetski
2
2
  module Autoloader
3
3
  include Jetski::Router::FilePathHelper
4
4
  extend self
@@ -12,10 +12,6 @@ module Jetski
12
12
  .split("/")
13
13
  .map(&:capitalize)
14
14
  .join("::")
15
- # posts/comment
16
- # Post/comment
17
- model_class = Object.const_get(model_name)
18
- model_class.define_attribute_methods
19
15
  end
20
16
  end
21
17
 
@@ -1,12 +1,12 @@
1
1
  # This is the base controller of the library
2
- module Jetski
2
+ class Jetski
3
3
  class BaseController
4
4
  RESERVED_INSTANCE_VARIABLES = [
5
5
  :@res, :@performed_render, :@action_name,
6
6
  :@controller_name, :@controller_path, :@cookies
7
7
  ]
8
8
 
9
- include ReactiveForm
9
+ include Jetski::Frontend::JavascriptHelpers
10
10
  extend Jetski::Helpers::RouteHelpers
11
11
  attr_accessor :action_name, :controller_name, :controller_path,
12
12
  :params, :cookies
@@ -1,4 +1,4 @@
1
- module Jetski
1
+ class Jetski
2
2
  module Database
3
3
  module Base
4
4
  extend self
@@ -7,35 +7,13 @@ module Jetski
7
7
  @_db ||= SQLite3::Database.new "test.db"
8
8
  end
9
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
-
20
- # Default fields on all models
21
- _gen_sql += " created_at datetime,\n"
22
- _gen_sql += " updated_at datetime,\n"
23
- _gen_sql += " id integer,\n"
24
-
25
- field_names.each.with_index do |field_name, idx|
26
- field, field_data_type = if field_name.include?(":")
27
- field_name.split(":")
28
- else
29
- [field_name, ""]
30
- end
31
- data_type = sql_data_type(field_data_type)
32
- _gen_sql += " #{field} #{data_type}"
33
- if (idx + 1) < field_names.size
34
- _gen_sql += ",\n"
35
- else
36
- _gen_sql += "\n"
37
- end
38
- end
10
+ def create_table_sql(table_name:, field_names: [])
11
+ table_name = pluralize_string(table_name)
12
+ default_fields = [["created_at", "datetime"], ["updated_at", "datetime"], ["id", "integer"]]
13
+ fields = field_names.map { |f| f.split(":") }
14
+ all_fields = fields + default_fields
15
+ _gen_sql = "create table #{table_name} (\n"
16
+ _gen_sql += all_fields.map { |field, data_type| " #{field} #{data_type}" }.join(",\n")
39
17
  _gen_sql += ");\n"
40
18
  _gen_sql
41
19
  end
@@ -0,0 +1,31 @@
1
+ # Responsibility is to wrap calls to db and make it more clean and readable.
2
+
3
+ class Jetski
4
+ module Database
5
+ module Interface
6
+ extend self
7
+
8
+ # expects an array of fields with type seperated by colon :
9
+ def create_table(table_name, *fields)
10
+ db.execute create_table_sql(table_name: table_name, field_names: fields)
11
+ end
12
+
13
+ def add_column(table_name, field_name, data_type = "string")
14
+ db.execute("ALTER TABLE #{table_name} ADD #{field_name} #{sql_data_type(data_type)}")
15
+ end
16
+
17
+ def add_column_unless_exists(table_name, field_name, data_type = nil)
18
+ add_column(table_name, field_name, data_type) if !field_exists?(table_name, field_name)
19
+ end
20
+
21
+ def table_exists?(table_name)
22
+ db.get_first_value("SELECT name FROM sqlite_master WHERE type='table' AND name=?", table_name)
23
+ end
24
+
25
+ def field_exists?(table_name, field_name)
26
+ table_info = db.execute("PRAGMA table_info(#{table_name})")
27
+ table_info.find { |d| d[1] == field_name } != nil
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,6 @@
1
+ class Jetski
2
+ module Database
3
+ module Sqlite3
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,12 @@
1
+ class Jetski
2
+ module Frontend
3
+ module JavascriptHelpers
4
+ def reactive_text_area(path, **opts)
5
+ css_classes = opts[:class]
6
+ value = opts[:value]
7
+ # Text area that auto saves to url.
8
+ "<textarea reactive-form-path='#{path}' class='#{css_classes}'>#{value}</textarea>"
9
+ end
10
+ end
11
+ end
12
+ end
@@ -1,4 +1,4 @@
1
- module Jetski
1
+ class Jetski
2
2
  module Helpers
3
3
  module Delegatable
4
4
  # delegate(:method, to: :class)
@@ -0,0 +1,14 @@
1
+ class Jetski
2
+ module Helpers
3
+ module Generic
4
+ # Helpers for use all over codebase for simple grammatics etc..
5
+ def pluralize_string(string)
6
+ if string[-1] == 's'
7
+ string
8
+ else
9
+ string + 's'
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,6 +1,6 @@
1
1
  # This is responsible for methods for routing in base_controller like the route class method
2
2
 
3
- module Jetski
3
+ class Jetski
4
4
  module Helpers
5
5
  module RouteHelpers
6
6
  def route(method_name, root: false, path: nil, request_method: nil)
@@ -1,4 +1,4 @@
1
- module Jetski
1
+ class Jetski
2
2
  module Helpers
3
3
  module ViewHelpers
4
4
  # Expecting a relative path.
@@ -84,8 +84,8 @@ module Jetski
84
84
  end.join(" ")
85
85
  end
86
86
  private
87
+ # TODO: could move this to a sharable method.
87
88
  def process_url(url)
88
- # Need to ensure urls start with / to avoid relative requests
89
89
  if url[0] == '/'
90
90
  url
91
91
  else
@@ -0,0 +1,46 @@
1
+ class Jetski
2
+ class Model
3
+ module Attributes
4
+ # class method for user to configure add/remove attributes on model
5
+ def attributes(*string_attributes, **custom_attributes)
6
+ @_db_string_attributes = string_attributes
7
+ @_db_custom_attributes = custom_attributes
8
+ combined_attributes = string_attributes + custom_attributes.map { |k, _v| k }
9
+ @_attribute_names ||= []
10
+ @_attribute_names.concat(combined_attributes)
11
+ @_attribute_names.concat([:created_at, :updated_at, :id]) # defaults
12
+ @_attribute_names = @_attribute_names.uniq
13
+ @_attribute_names.each do |attribute|
14
+ define_method attribute do
15
+ @virtual_attributes[attribute]
16
+ end
17
+ end
18
+ end
19
+
20
+ def attribute_names
21
+ @_attribute_names || []
22
+ end
23
+
24
+ def db_attribute_values
25
+ # Returns the formatted objects with types for each attribute
26
+ _db_attributes = []
27
+
28
+ @_db_string_attributes.each do |value|
29
+ _db_attributes << {
30
+ name: value,
31
+ type: :string
32
+ }
33
+ end
34
+
35
+ @_db_custom_attributes.each do |key, value|
36
+ _db_attributes << {
37
+ name: key,
38
+ type: value
39
+ }
40
+ end
41
+
42
+ _db_attributes
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,76 @@
1
+ class Jetski
2
+ class Model
3
+ module CrudHelpers
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
7
+
8
+ def destroy!
9
+ # Destroy record: remove from db
10
+ delete_sql = <<~SQL
11
+ DELETE from #{self.class.pluralized_table_name} WHERE id=?
12
+ SQL
13
+ self.class.db.execute(delete_sql, id)
14
+ nil
15
+ end
16
+
17
+ module ClassMethods
18
+ def create(hash_args = nil, **key_args)
19
+ args = if hash_args && hash_args.is_a?(Hash)
20
+ hash_args
21
+ else
22
+ key_args
23
+ end
24
+
25
+ return puts "#{table_name.capitalize}.create was called with no args" if args.size == 0
26
+ data_values = args.map { |k,v| v }
27
+ key_names = args.map { |k, v| k }
28
+
29
+ # Set default values on create
30
+
31
+ key_names.append "created_at"
32
+ data_values.append Time.now.to_s
33
+
34
+ current_record_count = (count || 0)
35
+ record_id = current_record_count + 1
36
+ key_names.append "id"
37
+ data_values.append(record_id)
38
+
39
+ sql_command = <<~SQL
40
+ INSERT INTO #{pluralized_table_name} (#{key_names.join(", ")})
41
+ VALUES (#{(1..key_names.size).map { |n| "?" }.join(", ")})
42
+ SQL
43
+
44
+ db.execute(sql_command, data_values)
45
+
46
+ record_attributes = {}
47
+ key_names.each.with_index do |k, i|
48
+ record_attributes[k.to_sym] = data_values[i]
49
+ end
50
+
51
+ new(**record_attributes)
52
+ end
53
+
54
+ def all
55
+ columns, *rows = db.execute2( "select * from #{pluralized_table_name}" )
56
+ _all = []
57
+ rows.map do |row|
58
+ _all << format_model_obj(row, columns)
59
+ end
60
+ _all
61
+ end
62
+
63
+ def find(id)
64
+ id_as_integer = id.to_i
65
+ columns, *rows = db.execute2( "select * from #{pluralized_table_name} WHERE id=?", id_as_integer)
66
+ format_model_obj(rows.last, columns)
67
+ end
68
+
69
+
70
+ def destroy_all!
71
+ db.execute("DELETE from #{pluralized_table_name}")
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
data/lib/jetski/model.rb CHANGED
@@ -1,15 +1,16 @@
1
- module Jetski
1
+ class Jetski
2
2
  class Model
3
- extend Jetski::Database::Base
3
+ extend Jetski::Database::Base, Jetski::Helpers::Generic,
4
+ Jetski::Model::Attributes
5
+ include CrudHelpers, Jetski::Helpers::Generic
4
6
 
5
7
  def initialize(**args)
6
8
  @virtual_attributes = args
7
9
  end
8
10
 
9
11
  def inspect
10
- post_obj_id = object_id
11
- inspect_str = "#<#{self.class.to_s}:#{post_obj_id}"
12
- self.class.attributes.each do |attribute_name|
12
+ inspect_str = "#<#{self.class.to_s}:#{object_id}"
13
+ self.class.attribute_names.each do |attribute_name|
13
14
  attribute_value = @virtual_attributes[attribute_name]
14
15
  inspect_str += " #{attribute_name}=\"#{attribute_value}\""
15
16
  end
@@ -17,120 +18,25 @@ module Jetski
17
18
  inspect_str
18
19
  end
19
20
 
20
- def destroy!
21
- # Destroy record: remove from db
22
- delete_sql = <<~SQL
23
- DELETE from #{self.class.pluralized_table_name} WHERE id=?
24
- SQL
25
- self.class.db.execute(delete_sql, id)
26
- nil
27
- end
28
-
29
21
  class << self
30
- def create(hash_args = nil, **key_args)
31
- args = if hash_args && hash_args.is_a?(Hash)
32
- hash_args
33
- else
34
- key_args
35
- end
36
-
37
- return puts "#{table_name.capitalize}.create was called with no args" if args.size == 0
38
- data_values = args.map { |k,v| v }
39
- key_names = args.map { |k, v| k }
40
-
41
- # Set default values on create
42
-
43
- key_names.append "created_at"
44
- data_values.append Time.now.to_s
45
-
46
- current_post_count = (count || 0)
47
- post_id = current_post_count + 1
48
- key_names.append "id"
49
- data_values.append(post_id)
50
-
51
- sql_command = <<~SQL
52
- INSERT INTO #{pluralized_table_name} (#{key_names.join(", ")})
53
- VALUES (#{(1..key_names.size).map { |n| "?" }.join(", ")})
54
- SQL
55
-
56
- db.execute(sql_command, data_values)
57
-
58
- post_attributes = {}
59
- key_names.each.with_index do |k, i|
60
- post_attributes[k] = data_values[i]
61
- end
62
-
63
- new(**post_attributes)
64
- end
65
-
66
- # Careful methods / delete all records from table
67
- def destroy_all!
68
- db.execute("DELETE from #{pluralized_table_name}")
69
- end
70
-
71
- def define_attribute_methods
72
- attributes.each do |attribute|
73
- define_method attribute do
74
- @virtual_attributes[attribute]
75
- end
76
- end
77
- end
22
+ extend Jetski::Helpers::Delegatable
23
+ delegate :count, :last, :first, to: :all
78
24
 
79
- def all
80
- columns, *rows = db.execute2( "select * from #{pluralized_table_name}" )
81
- _all = []
82
- rows.map do |row|
83
- _all << format_model_obj(row, columns)
84
- end
85
- _all
86
- end
87
-
88
- def pluck_rows
89
- db.execute( "select * from #{pluralized_table_name}" )
90
- end
91
-
92
- def count
93
- pluck_rows.size
94
- end
95
-
96
- def attributes
97
- # TODO: Find a more performant way to get the column names from a table
98
- columns, *rows = db.execute2( "select * from #{pluralized_table_name}" )
99
- columns
100
- end
101
-
102
- def last
103
- format_model_obj(pluck_rows.last)
104
- end
105
-
106
- def first
107
- format_model_obj(pluck_rows.first)
108
- end
109
-
110
- def find(id)
111
- id_as_integer = id.to_i
112
- columns, *rows = db.execute2( "select * from #{pluralized_table_name} WHERE id=?", id_as_integer)
113
- format_model_obj(rows.last, columns)
114
- end
115
-
116
25
  def table_name
117
26
  self.to_s.downcase
118
27
  end
119
28
 
120
29
  def pluralized_table_name
121
- if table_name[-1] == "s"
122
- table_name
123
- else
124
- table_name + "s"
125
- end
30
+ pluralize_string(table_name)
126
31
  end
32
+
33
+ # Mark attributes method as private hide it from IRB
34
+ private :attributes
127
35
  private
128
- def format_model_obj(row, columns = nil)
129
- return unless row
130
- columns ||= attributes
36
+ def format_model_obj(row, columns)
131
37
  row_obj = {}
132
38
  columns.each.with_index do |col, idx|
133
- row_obj[col] = row[idx]
39
+ row_obj[col.to_sym] = row[idx]
134
40
  end
135
41
  new(**row_obj)
136
42
  end
@@ -1,4 +1,4 @@
1
- module Jetski
1
+ class Jetski
2
2
  class Router
3
3
  module FilePathHelper
4
4
  def controller_file_paths
@@ -1,4 +1,4 @@
1
- module Jetski
1
+ class Jetski
2
2
  class Router
3
3
  module Host
4
4
  class Base
@@ -1,4 +1,4 @@
1
- module Jetski
1
+ class Jetski
2
2
  class Router
3
3
  module Host
4
4
  class Controller < Base
@@ -33,6 +33,8 @@ module Jetski
33
33
  parsed_body = parse_body(req.body, req.content_type)
34
34
  params_hash = parsed_body.merge(params_hash)
35
35
  end
36
+
37
+ # TODO: Need to support deep object structuring.
36
38
  controller.params = OpenStruct.new(params_hash)
37
39
  controller.cookies = req.cookies
38
40
  controller.send(action_name)
@@ -40,7 +42,7 @@ module Jetski
40
42
  controller.render
41
43
  end
42
44
  end
43
-
45
+ private
44
46
  def parse_body(body, content_type = '')
45
47
  case content_type
46
48
  when "application/x-www-form-urlencoded"
@@ -1,4 +1,4 @@
1
- module Jetski
1
+ class Jetski
2
2
  class Router
3
3
  module Host
4
4
  class Crud < Base
@@ -26,7 +26,6 @@ module Jetski
26
26
  end
27
27
  private
28
28
  def determine_action_from_url
29
- # TODO: Handle checking for url params.
30
29
  req_path = req.request_uri.path
31
30
  custom_route_options.tap do |opts|
32
31
  case req_path
@@ -45,11 +44,11 @@ module Jetski
45
44
  else
46
45
  url_param = req_path.split("#{controller_path}/")[-1]
47
46
  case
48
- when url_param.match(/\d(\/edit)/)
47
+ when url_param&.match(/\d(\/edit)/)
49
48
  # Edit page
50
49
  opts[:action_name] = "edit"
51
50
  opts[:method] = "GET"
52
- when url_param.match(/\d\z/)
51
+ when url_param&.match(/\d\z/)
53
52
  # matches only id 5 with no additional characters
54
53
  # Determine if show/update/destroy from request_method
55
54
  opts[:method] = req.request_method
@@ -62,7 +61,7 @@ module Jetski
62
61
  opts[:action_name] = "destroy"
63
62
  end
64
63
  else
65
- handle_controller_render = false
64
+ @handle_controller_render = false
66
65
  end
67
66
  end
68
67
  end
@@ -1,4 +1,4 @@
1
- module Jetski
1
+ class Jetski
2
2
  class Router
3
3
  module Parser
4
4
  include Jetski::Router::FilePathHelper
data/lib/jetski/router.rb CHANGED
@@ -1,4 +1,4 @@
1
- module Jetski
1
+ class Jetski
2
2
  class Router
3
3
  include Parser
4
4
  attr_reader :server, :routes, :crud_routes
@@ -28,16 +28,14 @@ module Jetski
28
28
  end
29
29
 
30
30
  def host_crud_routes
31
- # TODO: Build server block to handle custom crud routes
32
31
  crud_routes_for_controller = crud_routes.group_by { |route| route[:controller_path] }
33
32
  crud_routes_for_controller.each do |controller_path, controller_routes|
34
- # TODO: Implement base level server block and checking.
35
33
  Host::Crud.new(server, controller_routes, **controller_routes.first).call
36
34
  end
37
35
  end
38
36
 
39
37
  def host_assets
40
- host_css && host_images && host_javascript && host_reactive_form_js
38
+ host_css && host_images && host_javascript && host_javascript_helpers
41
39
  end
42
40
 
43
41
  def host_css
@@ -79,10 +77,10 @@ module Jetski
79
77
  end
80
78
  end
81
79
 
82
- def host_reactive_form_js
80
+ def host_javascript_helpers
83
81
  server.mount_proc "/reactive-form.js" do |req, res|
84
82
  res.content_type = "text/javascript"
85
- res.body = File.read(File.join(__dir__, 'frontend/reactive_form.js'))
83
+ res.body = File.read(File.join(__dir__, 'frontend/javascript_helpers.js'))
86
84
  end
87
85
  end
88
86
 
data/lib/jetski/server.rb CHANGED
@@ -1,4 +1,4 @@
1
- module Jetski
1
+ class Jetski
2
2
  class Server
3
3
  attr_reader :port
4
4
 
@@ -1,3 +1,3 @@
1
- module Jetski
2
- VERSION = "0.4.9"
1
+ class Jetski
2
+ VERSION = "0.5.0"
3
3
  end
@@ -1,4 +1,4 @@
1
- module Jetski
1
+ class Jetski
2
2
  class ViewRenderer
3
3
  include Jetski::Helpers::ViewHelpers
4
4
  extend Jetski::Helpers::Delegatable
@@ -33,8 +33,6 @@ module Jetski
33
33
 
34
34
  def process_erb(content)
35
35
  template = ERB.new(content)
36
- # Perserve instance variables to view render
37
- # @posts from controller to posts/index.html.erb
38
36
 
39
37
  grab_instance_variables
40
38
  template.result(binding)
@@ -69,7 +67,7 @@ module Jetski
69
67
 
70
68
  application_js_file = File.join(assets_folder, "javascript", "application.js")
71
69
  if File.exist? application_js_file
72
- _content_for_head += "<script src='application.js' defer></script>\n"
70
+ _content_for_head += "<script src='/application.js' defer></script>\n"
73
71
  end
74
72
 
75
73
  controller_js_file = File.join(assets_folder, "javascript", "#{path_to_controller}.js")
data/lib/jetski.rb CHANGED
@@ -6,10 +6,11 @@ require "rack"
6
6
  require "sqlite3"
7
7
 
8
8
  require_relative './jetski/version'
9
+ require_relative './jetski/helpers/generic'
9
10
  require_relative './jetski/helpers/view_helpers'
10
11
  require_relative './jetski/helpers/route_helpers'
11
12
  require_relative './jetski/helpers/delegatable'
12
- require_relative './jetski/frontend/reactive_form'
13
+ require_relative './jetski/frontend/javascript_helpers'
13
14
  require_relative './jetski/base_controller'
14
15
  require_relative './jetski/router/file_path_helper'
15
16
  require_relative './jetski/router/parser'
@@ -20,12 +21,16 @@ require_relative './jetski/router'
20
21
  require_relative './jetski/autoloader'
21
22
  require_relative './jetski/server'
22
23
  require_relative './jetski/database/base'
24
+ require_relative './jetski/database/sqlite3'
25
+ require_relative './jetski/database/interface'
26
+ require_relative './jetski/model/crud_helpers'
27
+ require_relative './jetski/model/attributes'
23
28
  require_relative './jetski/model'
24
29
  require_relative './jetski/view_renderer'
25
30
 
26
- module Jetski
27
- extend self
28
- def app_root
31
+ class Jetski
32
+ include Jetski::Helpers::Generic
33
+ def self.app_root
29
34
  Dir.pwd
30
35
  end
31
36
  end
@@ -0,0 +1,56 @@
1
+ class <%= @controller_class_name %>Controller < Jetski::BaseController
2
+ <% @actions.each.with_index do |action_name, idx| -%>
3
+ <% if action_name == "new" -%>
4
+ def new
5
+ @<%= @name %> = <%= @model_class_name %>.new
6
+ end
7
+ <% end -%>
8
+ <% if action_name == "create" -%>
9
+ def create
10
+ @<%= @name %> = <%= @model_class_name %>.create(<%= @name %>_params)
11
+ redirect_to "/<%= @controller_name %>/" + @<%= @name %>.id.to_s
12
+ end
13
+ <% end -%>
14
+ <% if action_name == "show" -%>
15
+ def show
16
+ @<%= @name %> = <%= @model_class_name %>.find(params[:id])
17
+ end
18
+ <% end -%>
19
+ <% if action_name == "edit" -%>
20
+ def edit
21
+ @<%= @name %> = <%= @model_class_name %>.find(params[:id])
22
+ end
23
+ <% end -%>
24
+ <% if action_name == "update" -%>
25
+ def update
26
+ @<%= @name %> = <%= @model_class_name %>.find(params[:id])
27
+ @<%= @name %>.update(<%= @name %>_params)
28
+ redirect_to "/<%= @controller_name %>/" + @<%= @name %>.id.to_s
29
+ end
30
+ <% end -%>
31
+ <% if action_name == "destroy" -%>
32
+ def destroy
33
+ @<%= @name %> = <%= @model_class_name %>.find(params[:id])
34
+ @<%= @name %>.destroy
35
+ redirect_to <%= @controller_name %>
36
+ end
37
+ <% end -%>
38
+ <% if action_name == "index" -%>
39
+ def index
40
+ @<%= @controller_name %> = <%= @model_class_name %>.all
41
+ end
42
+ <% end -%>
43
+
44
+ <% end -%>
45
+ private
46
+
47
+ <% if @field_names -%>
48
+ def <%= @name %>_params
49
+ {
50
+ <% @field_names.each do |field| -%>
51
+ <%= field.split(":")[0] %>: params["<%= @controller_name%>"]["<%= field.split(":")[0] %>"],
52
+ <% end -%>
53
+ }
54
+ end
55
+ <% end -%>
56
+ end
@@ -0,0 +1,2 @@
1
+ <h1> <%= @controller_name %>#<%= @action_name %> </h1>
2
+ <p> edit the content of this page at app/views/<%= @path_to_view %>/ <%= @action_name %>.html.erb </p>
@@ -0,0 +1,7 @@
1
+ <h1> Edit <%= @name %> </h1>
2
+ <form action='/<%= @controller_name %>/<%%= @<%= @name %>.id %>' method='PUT'>
3
+ <% @field_names.each do |field| -%>
4
+ <input name='<%= @controller_name %>[<%= field.split(":")[0] %>]'/>
5
+ <% end -%>
6
+ <button type='submit'>Update <%= @name %></button>
7
+ </form>
@@ -0,0 +1,12 @@
1
+ <h1> Viewing all <%= @controller_name %></h1>
2
+
3
+ <a href="/<%= @controller_name %>/new"> New <%= @name %> </a>
4
+
5
+ <%% @<%= @controller_name %>.each do |<%= @name %>| %>
6
+ <% @field_names.each do |field| -%>
7
+ <p>
8
+ <%= field.split(":")[0] %>: <%%= <%= @name %>.<%= field.split(":")[0] %> %>
9
+ </p>
10
+ <a href='/<%= @controller_name %>/<%%= <%= @name %>.id %>'> View <%= @name %></a>
11
+ <% end %>
12
+ <%% end %>
@@ -0,0 +1,7 @@
1
+ <h1> New <%= @name %> </h1>
2
+ <form action='/<%= @controller_name %>' method='POST'>
3
+ <% @field_names.each do |field| -%>
4
+ <input name='<%= @controller_name %>[<%= field.split(":")[0] %>]'/>
5
+ <% end -%>
6
+ <button type='submit'>Create <%= @name %></button>
7
+ </form>
@@ -0,0 +1,8 @@
1
+ <h1> Viewing your <%= @name %> </h1>
2
+ <a href="/<%= @controller_name %>"> Back to <%= @controller_name %></a>
3
+ <a href="/<%= @controller_name %>/<%%= @<%= @name %>.id %>/edit"> Edit <%= @name %></a>
4
+ <% @field_names.each do |field| -%>
5
+ <p>
6
+ <%= field.split(":")[0] %>: <%%= @<%= @name %>.<%= field.split(":")[0] %> %>
7
+ </p>
8
+ <% end -%>
@@ -0,0 +1,5 @@
1
+ class <%= @model_name.capitalize %> < Jetski::Model
2
+ <% if @model_attributes -%>
3
+ attributes <%= @model_attributes.join(", ") %>
4
+ <% end -%>
5
+ end
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.9
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Indigo Tech Tutorials
@@ -38,33 +38,33 @@ dependencies:
38
38
  - !ruby/object:Gem::Version
39
39
  version: 1.4.0
40
40
  - !ruby/object:Gem::Dependency
41
- name: ostruct
41
+ name: erb
42
42
  requirement: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
- version: 0.6.2
46
+ version: 5.1.2
47
47
  type: :runtime
48
48
  prerelease: false
49
49
  version_requirements: !ruby/object:Gem::Requirement
50
50
  requirements:
51
51
  - - "~>"
52
52
  - !ruby/object:Gem::Version
53
- version: 0.6.2
53
+ version: 5.1.2
54
54
  - !ruby/object:Gem::Dependency
55
- name: erb
55
+ name: ostruct
56
56
  requirement: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
- version: 5.1.2
60
+ version: 0.6.2
61
61
  type: :runtime
62
62
  prerelease: false
63
63
  version_requirements: !ruby/object:Gem::Requirement
64
64
  requirements:
65
65
  - - "~>"
66
66
  - !ruby/object:Gem::Version
67
- version: 5.1.2
67
+ version: 0.6.2
68
68
  - !ruby/object:Gem::Dependency
69
69
  name: sqlite3
70
70
  requirement: !ruby/object:Gem::Requirement
@@ -116,6 +116,7 @@ extensions: []
116
116
  extra_rdoc_files: []
117
117
  files:
118
118
  - bin/jetski
119
+ - bin/jetski_cli_helpers/base.rb
119
120
  - bin/jetski_cli_helpers/database.rb
120
121
  - bin/jetski_cli_helpers/destroy.rb
121
122
  - bin/jetski_cli_helpers/destroyers/controller.rb
@@ -128,12 +129,17 @@ files:
128
129
  - lib/jetski/autoloader.rb
129
130
  - lib/jetski/base_controller.rb
130
131
  - lib/jetski/database/base.rb
131
- - lib/jetski/frontend/reactive_form.js
132
- - lib/jetski/frontend/reactive_form.rb
132
+ - lib/jetski/database/interface.rb
133
+ - lib/jetski/database/sqlite3.rb
134
+ - lib/jetski/frontend/javascript_helpers.js
135
+ - lib/jetski/frontend/javascript_helpers.rb
133
136
  - lib/jetski/helpers/delegatable.rb
137
+ - lib/jetski/helpers/generic.rb
134
138
  - lib/jetski/helpers/route_helpers.rb
135
139
  - lib/jetski/helpers/view_helpers.rb
136
140
  - lib/jetski/model.rb
141
+ - lib/jetski/model/attributes.rb
142
+ - lib/jetski/model/crud_helpers.rb
137
143
  - lib/jetski/router.rb
138
144
  - lib/jetski/router/file_path_helper.rb
139
145
  - lib/jetski/router/host/base.rb
@@ -151,6 +157,13 @@ files:
151
157
  - templates/base/app/controllers/pages_controller.rb
152
158
  - templates/base/app/views/layouts/application.html.erb
153
159
  - templates/base/app/views/pages/home.html.erb
160
+ - templates/controllers/controller.rb.erb
161
+ - templates/controllers/views/default.html.erb
162
+ - templates/controllers/views/edit.html.erb
163
+ - templates/controllers/views/index.html.erb
164
+ - templates/controllers/views/new.html.erb
165
+ - templates/controllers/views/show.html.erb
166
+ - templates/model/template.rb.erb
154
167
  homepage: https://rubygems.org/gems/jetski
155
168
  licenses:
156
169
  - MIT
@@ -1,8 +0,0 @@
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