jetski 0.4.8 → 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.
- checksums.yaml +4 -4
- data/bin/jetski +5 -0
- data/bin/jetski_cli_helpers/base.rb +11 -0
- data/bin/jetski_cli_helpers/database.rb +16 -12
- data/bin/jetski_cli_helpers/destroy.rb +11 -10
- data/bin/jetski_cli_helpers/destroyers/controller.rb +13 -0
- data/bin/jetski_cli_helpers/destroyers/model.rb +13 -0
- data/bin/jetski_cli_helpers/generate.rb +12 -42
- data/bin/jetski_cli_helpers/generators/controller.rb +40 -0
- data/bin/jetski_cli_helpers/generators/model.rb +31 -0
- data/lib/jetski/autoloader.rb +2 -6
- data/lib/jetski/base_controller.rb +2 -4
- data/lib/jetski/database/base.rb +8 -30
- data/lib/jetski/database/interface.rb +31 -0
- data/lib/jetski/database/sqlite3.rb +6 -0
- data/lib/jetski/frontend/javascript_helpers.rb +12 -0
- data/lib/jetski/helpers/delegatable.rb +1 -1
- data/lib/jetski/helpers/generic.rb +14 -0
- data/lib/jetski/helpers/route_helpers.rb +1 -2
- data/lib/jetski/helpers/view_helpers.rb +53 -8
- data/lib/jetski/model/attributes.rb +46 -0
- data/lib/jetski/model/crud_helpers.rb +76 -0
- data/lib/jetski/model.rb +14 -96
- data/lib/jetski/router/{shared_methods.rb → file_path_helper.rb} +2 -2
- data/lib/jetski/router/host/base.rb +58 -0
- data/lib/jetski/router/host/controller.rb +59 -0
- data/lib/jetski/router/host/crud.rb +72 -0
- data/lib/jetski/router/parser.rb +8 -8
- data/lib/jetski/router.rb +33 -57
- data/lib/jetski/server.rb +1 -1
- data/lib/jetski/version.rb +2 -2
- data/lib/jetski/view_renderer.rb +23 -8
- data/lib/jetski.rb +13 -5
- data/templates/controllers/controller.rb.erb +56 -0
- data/templates/controllers/views/default.html.erb +2 -0
- data/templates/controllers/views/edit.html.erb +7 -0
- data/templates/controllers/views/index.html.erb +12 -0
- data/templates/controllers/views/new.html.erb +7 -0
- data/templates/controllers/views/show.html.erb +8 -0
- data/templates/model/template.rb.erb +5 -0
- metadata +30 -10
- data/lib/jetski/frontend/reactive_form.rb +0 -8
- /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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0fba85e1a50746a7e376738a0ec5648ce22edcc7874ea0d9ee9b3be681d7364d
|
|
4
|
+
data.tar.gz: b3ac634c65fd946fb1dc43c62702b620b46dd17e1369ef0716eedfa6885e373d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9740af48073b1a0c8c069d834e2da63c7b351b5a84c5c77502348854c1164105a1002282c8036fa2eaa040cbf085b9e8e8a1ffb98c4b16a87208ca33dccd544c
|
|
7
|
+
data.tar.gz: cc288a4e32d8dff6c78c14baad4fb317049b2329d30a05bb3132ad1e054db0bf7a0924fec502720b7ae80a7e99d047ee2c364f1e1c5327d81244ddbb2734c6e1
|
data/bin/jetski
CHANGED
|
@@ -5,7 +5,12 @@ require 'optparse'
|
|
|
5
5
|
require 'thor'
|
|
6
6
|
require "pry"
|
|
7
7
|
|
|
8
|
+
require_relative './jetski_cli_helpers/generators/controller.rb'
|
|
9
|
+
require_relative './jetski_cli_helpers/generators/model.rb'
|
|
10
|
+
require_relative './jetski_cli_helpers/destroyers/controller.rb'
|
|
11
|
+
require_relative './jetski_cli_helpers/destroyers/model.rb'
|
|
8
12
|
require_relative './jetski_cli_helpers/shared_methods.rb'
|
|
13
|
+
require_relative './jetski_cli_helpers/base.rb'
|
|
9
14
|
require_relative './jetski_cli_helpers/generate.rb'
|
|
10
15
|
require_relative './jetski_cli_helpers/destroy.rb'
|
|
11
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,16 +1,20 @@
|
|
|
1
|
-
require 'thor'
|
|
2
1
|
module JetskiCLIHelpers
|
|
3
|
-
class Database <
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
|
14
18
|
end
|
|
15
19
|
|
|
16
20
|
desc "seed", "Seeds the database with records created from seed file"
|
|
@@ -1,20 +1,21 @@
|
|
|
1
|
-
require 'thor'
|
|
2
1
|
module JetskiCLIHelpers
|
|
3
|
-
class Destroy <
|
|
4
|
-
include
|
|
2
|
+
class Destroy < Base
|
|
3
|
+
include JetskiCLIHelpers::Destroyers::Controller,
|
|
4
|
+
JetskiCLIHelpers::Destroyers::Model
|
|
5
5
|
desc "controller NAME ACTION_NAMES", "Destroys a controller"
|
|
6
6
|
def controller(name, *actions)
|
|
7
|
-
|
|
8
|
-
remove_file(controller_file_path)
|
|
9
|
-
view_folder = "app/views/#{name}"
|
|
10
|
-
remove_dir(view_folder)
|
|
7
|
+
destroy_controller(name)
|
|
11
8
|
end
|
|
12
9
|
|
|
13
10
|
desc "model NAME ACTION_NAMES", "Destroys a model"
|
|
14
11
|
def model(name, *actions)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
destroy_model(name)
|
|
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)
|
|
18
19
|
end
|
|
19
20
|
end
|
|
20
21
|
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module JetskiCLIHelpers
|
|
2
|
+
module Destroyers
|
|
3
|
+
module Controller
|
|
4
|
+
def destroy_controller(name)
|
|
5
|
+
controller_name = pluralize_string(name)
|
|
6
|
+
controller_file_path = "app/controllers/#{controller_name}_controller.rb"
|
|
7
|
+
remove_file(controller_file_path)
|
|
8
|
+
view_folder = "app/views/#{controller_name}"
|
|
9
|
+
remove_dir(view_folder)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module JetskiCLIHelpers
|
|
2
|
+
module Destroyers
|
|
3
|
+
module Model
|
|
4
|
+
def destroy_model(name)
|
|
5
|
+
model_file_path = "app/models/#{name}.rb"
|
|
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)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -1,52 +1,22 @@
|
|
|
1
|
-
require 'thor'
|
|
2
1
|
module JetskiCLIHelpers
|
|
3
|
-
class Generate <
|
|
4
|
-
include
|
|
5
|
-
|
|
2
|
+
class Generate < Base
|
|
3
|
+
include JetskiCLIHelpers::Generators::Controller,
|
|
4
|
+
JetskiCLIHelpers::Generators::Model
|
|
6
5
|
desc "controller NAME ACTION_NAMES", "Create a controller with matching actions"
|
|
7
6
|
def controller(name, *actions)
|
|
8
|
-
|
|
9
|
-
create_file controller_file_path
|
|
10
|
-
append_to_file controller_file_path, <<~CONTROLLER
|
|
11
|
-
class #{name.capitalize}Controller < Jetski::BaseController
|
|
12
|
-
|
|
13
|
-
end
|
|
14
|
-
CONTROLLER
|
|
15
|
-
|
|
16
|
-
actions.each.with_index do |action_name, idx|
|
|
17
|
-
action_content = <<~ACTION_CONTENT
|
|
18
|
-
def #{action_name}
|
|
19
|
-
|
|
20
|
-
end
|
|
21
|
-
ACTION_CONTENT
|
|
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"
|
|
27
|
-
|
|
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
|
|
37
|
-
end
|
|
7
|
+
generate_controller(name, *actions)
|
|
38
8
|
end
|
|
39
9
|
|
|
40
10
|
desc "model NAME FIELD_NAMES", "Creates a model with matching fields"
|
|
41
11
|
def model(name, *field_names)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
12
|
+
generate_model(name, *field_names)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
desc "resource NAME FIELD_NAMES", "Creates a resource with model and controller and crud routes"
|
|
16
|
+
def resource(name, *field_names)
|
|
17
|
+
crud_actions = %w(new create show index edit update destroy)
|
|
18
|
+
generate_model(name, *field_names)
|
|
19
|
+
generate_controller(name, *crud_actions, field_names: field_names)
|
|
50
20
|
end
|
|
51
21
|
end
|
|
52
22
|
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
module JetskiCLIHelpers
|
|
2
|
+
module Generators
|
|
3
|
+
module Controller
|
|
4
|
+
def generate_controller(name, *actions, **extra_options)
|
|
5
|
+
field_names = extra_options[:field_names]
|
|
6
|
+
@name = name
|
|
7
|
+
@controller_name = pluralize_string(name)
|
|
8
|
+
|
|
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
|
|
15
|
+
|
|
16
|
+
# Create controller from template
|
|
17
|
+
template "controllers/controller.rb.erb", controller_file_path
|
|
18
|
+
|
|
19
|
+
actions.each do |action_name|
|
|
20
|
+
# create views
|
|
21
|
+
if !["create", "create", "update", "destroy"].include?(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}"
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module JetskiCLIHelpers
|
|
2
|
+
module Generators
|
|
3
|
+
module Model
|
|
4
|
+
def generate_model(name, *field_names)
|
|
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}"
|
|
17
|
+
end
|
|
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
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
data/lib/jetski/autoloader.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
class Jetski
|
|
2
2
|
module Autoloader
|
|
3
|
-
include Jetski::Router::
|
|
3
|
+
include Jetski::Router::FilePathHelper
|
|
4
4
|
extend self
|
|
5
5
|
# Responsibility is to load all models in app.
|
|
6
6
|
def call
|
|
@@ -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
|
-
|
|
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
|
|
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
|
|
@@ -19,8 +19,6 @@ module Jetski
|
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
# Method to render matching view with controller_name/action_name
|
|
22
|
-
# TODO: Make render available in view as seperate method.
|
|
23
|
-
|
|
24
22
|
def render(**args)
|
|
25
23
|
@performed_render = true
|
|
26
24
|
request_status = args[:status] || 200
|
data/lib/jetski/database/base.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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,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,10 +1,9 @@
|
|
|
1
1
|
# This is responsible for methods for routing in base_controller like the route class method
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
class Jetski
|
|
4
4
|
module Helpers
|
|
5
5
|
module RouteHelpers
|
|
6
6
|
def route(method_name, root: false, path: nil, request_method: nil)
|
|
7
|
-
# TODO: write code to set route
|
|
8
7
|
@custom_route_opts ||= {}
|
|
9
8
|
@custom_route_opts[method_name] = {
|
|
10
9
|
method_name: method_name,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
class Jetski
|
|
2
2
|
module Helpers
|
|
3
3
|
module ViewHelpers
|
|
4
4
|
# Expecting a relative path.
|
|
@@ -21,24 +21,60 @@ module Jetski
|
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
# button_to("Click me", class: "cool-btn")
|
|
24
|
-
def button_to(button_text, **html_opts)
|
|
25
|
-
|
|
24
|
+
def button_to(button_text, url = nil, **html_opts)
|
|
25
|
+
if url
|
|
26
|
+
_method = html_opts[:method] || 'POST'
|
|
27
|
+
# Create form with button inside lol
|
|
28
|
+
_form = "<form action='#{url}' method='#{_method}'>"
|
|
29
|
+
_form += "<button type='submit' #{format_html_options(**html_opts)}>#{button_text}</button>"
|
|
30
|
+
_form += "</form>"
|
|
31
|
+
_form
|
|
32
|
+
else
|
|
33
|
+
_button = "<button #{format_html_options(**html_opts)}>#{button_text}</button>"
|
|
34
|
+
end
|
|
26
35
|
end
|
|
27
36
|
|
|
28
|
-
def input_tag(**html_opts)
|
|
37
|
+
def input_tag(input_name = nil, **html_opts)
|
|
38
|
+
html_opts[:name] ||= input_name
|
|
29
39
|
"<input #{format_html_options(**html_opts)}>"
|
|
30
40
|
end
|
|
31
41
|
|
|
32
|
-
def
|
|
33
|
-
"<
|
|
42
|
+
def label_tag(text, **html_opts)
|
|
43
|
+
"<label #{format_html_options(**html_opts)}>#{text}</label>"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def textarea_tag(name = nil, value = nil, **html_opts)
|
|
47
|
+
html_opts[:name] ||= name
|
|
48
|
+
value ||= html_opts[:value]
|
|
49
|
+
"<textarea #{format_html_options(**html_opts.except(:value))}>#{value}</textarea>"
|
|
34
50
|
end
|
|
35
51
|
|
|
36
52
|
def image_tag(image_path, **html_opts)
|
|
37
|
-
|
|
53
|
+
abs_url = process_url(image_path)
|
|
54
|
+
"<img src='#{abs_url}' #{format_html_options(**html_opts)}></img>"
|
|
38
55
|
end
|
|
39
56
|
|
|
40
57
|
def favicon_tag(url, **html_opts)
|
|
41
|
-
|
|
58
|
+
abs_url = process_url(url)
|
|
59
|
+
"<link rel='icon' type='image/x-icon' #{format_html_options(**html_opts)} href='#{abs_url}'>"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def stylesheet_tag(url, **html_opts)
|
|
63
|
+
abs_url = process_url(url)
|
|
64
|
+
"<link rel='stylesheet' #{format_html_options(**html_opts)} href='#{abs_url}'>"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def javascript_include_tag(url, **html_opts)
|
|
68
|
+
abs_url = process_url(url)
|
|
69
|
+
"<script src='#{abs_url}' #{format_html_options(**html_opts)}></script>"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def javascript_tag(**html_opts)
|
|
73
|
+
"<script #{format_html_options(**html_opts)}>#{yield}</script>"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def truncate(text, limit)
|
|
77
|
+
text[0..limit]
|
|
42
78
|
end
|
|
43
79
|
|
|
44
80
|
def format_html_options(**html_opts)
|
|
@@ -47,6 +83,15 @@ module Jetski
|
|
|
47
83
|
"#{formatted_key}='#{v}'"
|
|
48
84
|
end.join(" ")
|
|
49
85
|
end
|
|
86
|
+
private
|
|
87
|
+
# TODO: could move this to a sharable method.
|
|
88
|
+
def process_url(url)
|
|
89
|
+
if url[0] == '/'
|
|
90
|
+
url
|
|
91
|
+
else
|
|
92
|
+
"/#{url}"
|
|
93
|
+
end
|
|
94
|
+
end
|
|
50
95
|
end
|
|
51
96
|
end
|
|
52
97
|
end
|
|
@@ -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
|