jun 0.0.1 → 0.3.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 (66) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +13 -0
  3. data/Gemfile +3 -1
  4. data/LICENSE.txt +1 -1
  5. data/README.md +18 -20
  6. data/Rakefile +13 -3
  7. data/bin/console +3 -9
  8. data/exe/jun +7 -0
  9. data/jun.gemspec +28 -18
  10. data/lib/jun/action_controller/base.rb +16 -0
  11. data/lib/jun/action_controller/callbacks.rb +46 -0
  12. data/lib/jun/action_controller/metal.rb +22 -0
  13. data/lib/jun/action_controller/redirecting.rb +17 -0
  14. data/lib/jun/action_controller/rendering.rb +84 -0
  15. data/lib/jun/action_dispatch/routing/mapper.rb +54 -0
  16. data/lib/jun/action_dispatch/routing/route_set.rb +112 -0
  17. data/lib/jun/action_dispatch/routing/welcome.html.erb +41 -0
  18. data/lib/jun/action_view/base.rb +26 -0
  19. data/lib/jun/action_view/helpers/url_helper.rb +13 -0
  20. data/lib/jun/action_view/helpers.rb +11 -0
  21. data/lib/jun/active_record/base.rb +52 -0
  22. data/lib/jun/active_record/migration.rb +76 -0
  23. data/lib/jun/active_record/migrator.rb +80 -0
  24. data/lib/jun/active_record/persistence.rb +60 -0
  25. data/lib/jun/active_record/relation.rb +42 -0
  26. data/lib/jun/active_support/core_ext/array/access.rb +27 -0
  27. data/lib/jun/active_support/core_ext/array/conversion.rb +10 -0
  28. data/lib/jun/active_support/core_ext/hash/transformation.rb +19 -0
  29. data/lib/jun/active_support/core_ext/string/access.rb +18 -0
  30. data/lib/jun/active_support/core_ext/string/inflector.rb +119 -0
  31. data/lib/jun/active_support/core_ext.rb +5 -0
  32. data/lib/jun/active_support/dependencies.rb +31 -0
  33. data/lib/jun/application.rb +45 -0
  34. data/lib/jun/cli/commands/base.rb +17 -0
  35. data/lib/jun/cli/commands/db/create.rb +35 -0
  36. data/lib/jun/cli/commands/db/drop.rb +18 -0
  37. data/lib/jun/cli/commands/db/migrate.rb +15 -0
  38. data/lib/jun/cli/commands/db/rollback.rb +15 -0
  39. data/lib/jun/cli/commands/db/schema/dump.rb +24 -0
  40. data/lib/jun/cli/commands/db/schema/load.rb +43 -0
  41. data/lib/jun/cli/commands/db/seed.rb +19 -0
  42. data/lib/jun/cli/commands/generate/migration.rb +27 -0
  43. data/lib/jun/cli/commands/new.rb +62 -0
  44. data/lib/jun/cli/commands/server.rb +17 -0
  45. data/lib/jun/cli/commands/version.rb +13 -0
  46. data/lib/jun/cli/generator_templates/migration.rb.erb +11 -0
  47. data/lib/jun/cli/generator_templates/new_app/Gemfile.erb +9 -0
  48. data/lib/jun/cli/generator_templates/new_app/README.md.erb +3 -0
  49. data/lib/jun/cli/generator_templates/new_app/app/controllers/application_controller.rb.erb +4 -0
  50. data/lib/jun/cli/generator_templates/new_app/app/helpers/application_helper.rb.erb +4 -0
  51. data/lib/jun/cli/generator_templates/new_app/app/models/application_record.rb.erb +4 -0
  52. data/lib/jun/cli/generator_templates/new_app/app/views/layouts/application.html.erb.erb +11 -0
  53. data/lib/jun/cli/generator_templates/new_app/bin/console.erb +8 -0
  54. data/lib/jun/cli/generator_templates/new_app/config/application.rb.erb +12 -0
  55. data/lib/jun/cli/generator_templates/new_app/config/environment.rb.erb +7 -0
  56. data/lib/jun/cli/generator_templates/new_app/config/routes.rb.erb +4 -0
  57. data/lib/jun/cli/generator_templates/new_app/config.ru.erb +6 -0
  58. data/lib/jun/cli/generator_templates/new_app/db/seeds.rb.erb +9 -0
  59. data/lib/jun/cli.rb +33 -0
  60. data/lib/jun/connection_adapters/sqlite_adapter.rb +19 -0
  61. data/lib/jun/version.rb +3 -1
  62. data/lib/jun.rb +50 -2
  63. metadata +129 -24
  64. data/.gitignore +0 -10
  65. data/.rspec +0 -2
  66. data/.travis.yml +0 -4
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jun
4
+ module CLI
5
+ module Commands
6
+ module DB
7
+ class Rollback < Base
8
+ def process(*args)
9
+ ActiveRecord::Migrator.new(direction: :down).call
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jun
4
+ module CLI
5
+ module Commands
6
+ module DB
7
+ module Schema
8
+ class Dump < Base
9
+ def process(*args)
10
+ schema_filepath = Jun.root.join("db/schema.sql")
11
+ db_filepath = Jun.root.join("db/app.db")
12
+
13
+ Bundler.with_original_env do
14
+ system("bundle exec sqlite3 #{db_filepath} .schema > #{schema_filepath}")
15
+ end
16
+
17
+ puts "Database schema updated."
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jun
4
+ module CLI
5
+ module Commands
6
+ module DB
7
+ module Schema
8
+ class Load < Base
9
+ def process(*args)
10
+ schema_filepath = Jun.root.join("db/schema.sql")
11
+ db_filepath = Jun.root.join("db/app.db")
12
+
13
+ Bundler.with_original_env do
14
+ system("bundle exec sqlite3 #{db_filepath} < #{schema_filepath}")
15
+ end
16
+
17
+ populate_schema_migrations!
18
+
19
+ puts "Database schema loaded."
20
+ end
21
+
22
+ private
23
+
24
+ def populate_schema_migrations!
25
+ migration_files = Dir.glob(Jun.root.join("db/migrate/*.rb")).sort
26
+
27
+ migration_files.each do |filepath|
28
+ filename = filepath.split("/").last.sub(".rb", "")
29
+ migration_version = filename.split("_").first
30
+
31
+ add_to_schema_migrations(migration_version)
32
+ end
33
+ end
34
+
35
+ def add_to_schema_migrations(version)
36
+ ActiveRecord::Base.connection.execute("INSERT INTO schema_migrations (version) VALUES (#{version});")
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jun
4
+ module CLI
5
+ module Commands
6
+ module DB
7
+ class Seed < Base
8
+ def process(*args)
9
+ seed_filepath = Jun.root.join("db/seed.rb")
10
+ abort("No seed file found.") unless File.exist?(seed_filepath)
11
+
12
+ load seed_filepath
13
+ puts "Seeding complete."
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jun
4
+ module CLI
5
+ module Commands
6
+ module Generate
7
+ class Migration < Base
8
+ def process(*args)
9
+ migration_name = args.first
10
+
11
+ template_filepath = File.expand_path("../../generator_templates/migration.rb.erb", __dir__)
12
+ template = Tilt::ERBTemplate.new(template_filepath)
13
+ template_locals = { migration_name: migration_name }
14
+
15
+ filename = "#{Time.now.to_i}_#{migration_name}.rb"
16
+ filepath = Jun.root.join("db/migrate/#{filename}")
17
+ file_body = template.render(nil, template_locals)
18
+
19
+ filepath.dirname.mkpath
20
+ File.open(filepath, "w") { |f| f.write(file_body) }
21
+ puts "created #{filename}"
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler"
4
+ require "fileutils"
5
+
6
+ module Jun
7
+ module CLI
8
+ module Commands
9
+ class New < Base
10
+ def process(*args)
11
+ if Jun.root
12
+ puts "Already in a Jun app..."
13
+ else
14
+ generate_new_app(args.first)
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def generate_new_app(app_name)
21
+ puts "Generating new Jun app (#{app_name})..."
22
+
23
+ templates = [
24
+ "config.ru",
25
+ "Gemfile",
26
+ "README.md",
27
+ "app/controllers/application_controller.rb",
28
+ "app/helpers/application_helper.rb",
29
+ "app/models/application_record.rb",
30
+ "app/views/layouts/application.html.erb",
31
+ "bin/console",
32
+ "config/application.rb",
33
+ "config/environment.rb",
34
+ "config/routes.rb",
35
+ "db/seeds.rb"
36
+ ]
37
+
38
+ FileUtils.mkdir_p(app_name)
39
+
40
+ FileUtils.chdir(app_name) do
41
+ templates.each do |filepath|
42
+ template_filepath = File.expand_path("../generator_templates/new_app/#{filepath}.erb", __dir__)
43
+ template = Tilt::ERBTemplate.new(template_filepath)
44
+ template_locals = { app_name: app_name }
45
+ file_body = template.render(nil, template_locals)
46
+
47
+ FileUtils.mkdir_p(File.dirname(filepath))
48
+
49
+ File.open(filepath, "w") { |f| f.write(file_body) }
50
+ puts "created #{filepath}"
51
+ end
52
+
53
+ FileUtils.chmod("u+x", "bin/console")
54
+
55
+ puts "Installing dependencies..."
56
+ Bundler.with_original_env { system("bundle install") }
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jun
4
+ module CLI
5
+ module Commands
6
+ class Server < Base
7
+ def process(*args)
8
+ if Jun.root
9
+ system("rerun --background -- rackup -p 6291")
10
+ else
11
+ abort("Command \"#{self.class.command_name}\" must be run inside of a Jun app.")
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jun
4
+ module CLI
5
+ module Commands
6
+ class Version < Base
7
+ def process(*args)
8
+ puts "Jun #{Jun::VERSION}"
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class <%= migration_name.camelize %> < ActiveRecord::Migration
4
+ def up
5
+
6
+ end
7
+
8
+ def down
9
+
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "jun", path: "/Users/zoran/dev/jun"
4
+ gem "puma"
5
+
6
+ group :development do
7
+ gem "pry"
8
+ gem "rerun"
9
+ end
@@ -0,0 +1,3 @@
1
+ # New Jun App
2
+
3
+ Your newly created Jun app.
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ApplicationController < Jun::ActionController::Base
4
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ApplicationHelper
4
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ApplicationRecord < ActiveRecord::Base
4
+ end
@@ -0,0 +1,11 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <title>Jun App</title>
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ </head>
7
+
8
+ <body>
9
+ <%%= yield %>
10
+ </body>
11
+ </html>
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "jun"
6
+
7
+ require "irb"
8
+ IRB.start(__FILE__)
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "jun"
4
+
5
+ # Require gems listed in the Gemfile, including any gems specified
6
+ # in the current environment group (e.g. :development, :production).
7
+ Bundler.require(*Jun.groups)
8
+
9
+ module <%= app_name.camelize %>
10
+ class Application < Jun::Application
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Load the Jun application.
4
+ require_relative "application"
5
+
6
+ # Initialize the application.
7
+ Jun.application.initialize!
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ Jun.application.routes.draw do
4
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/setup"
4
+ require_relative "config/environment"
5
+
6
+ run Jun.application
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file is used by the `jun db:seed` command and should include
4
+ # any necessary logic for seeding the database.
5
+ #
6
+ # Example:
7
+ #
8
+ # User.create(name: "Sam", occupation: "author")
9
+ # Post.create(title: "How to Build a Bird House")
data/lib/jun/cli.rb ADDED
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ Dir[File.expand_path("cli/commands/**/*.rb", __dir__)].each do |filepath|
4
+ require_relative filepath
5
+ end
6
+
7
+ module Jun
8
+ module CLI
9
+ class << self
10
+ COMMAND_KLASSES = [
11
+ Jun::CLI::Commands::New,
12
+ Jun::CLI::Commands::DB::Create,
13
+ Jun::CLI::Commands::DB::Migrate,
14
+ Jun::CLI::Commands::DB::Rollback,
15
+ Jun::CLI::Commands::DB::Seed,
16
+ Jun::CLI::Commands::DB::Drop,
17
+ Jun::CLI::Commands::DB::Schema::Dump,
18
+ Jun::CLI::Commands::DB::Schema::Load,
19
+ Jun::CLI::Commands::Generate::Migration,
20
+ Jun::CLI::Commands::Server,
21
+ Jun::CLI::Commands::Version
22
+ ].freeze
23
+
24
+ def process_command(argv)
25
+ command_name = argv.shift
26
+ command_klass = COMMAND_KLASSES.find { |klass| klass.command_name == command_name }
27
+ abort("Command \"#{command_name}\" not found.") if command_klass.nil?
28
+
29
+ command_klass.new.process(*argv)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "sqlite3"
4
+
5
+ class SqliteAdapter
6
+ def initialize
7
+ @db = SQLite3::Database.new(Jun.root.join("db/app.db").to_s, results_as_hash: true)
8
+ end
9
+
10
+ def execute(sql)
11
+ @db.execute(sql).each do |row|
12
+ row.keys.each { |key| row[(key.to_sym rescue key) || key] = row.delete(key) }
13
+ end
14
+ end
15
+
16
+ def columns(table_name)
17
+ @db.table_info(table_name).map { |info| info["name"].to_sym }
18
+ end
19
+ end
data/lib/jun/version.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Jun
2
- VERSION = "0.0.1"
4
+ VERSION = "0.3.0"
3
5
  end
data/lib/jun.rb CHANGED
@@ -1,5 +1,53 @@
1
- require "jun/version"
1
+ # frozen_string_literal: true
2
+
3
+ require "pathname"
4
+
5
+ require_relative "jun/version"
6
+ require_relative "jun/active_support/core_ext"
7
+ require_relative "jun/active_support/dependencies"
8
+ require_relative "jun/action_dispatch/routing/route_set"
9
+ require_relative "jun/active_record/base"
10
+ require_relative "jun/active_record/migration"
11
+ require_relative "jun/active_record/migrator"
12
+ require_relative "jun/active_record/relation"
13
+ require_relative "jun/action_controller/base"
14
+ require_relative "jun/application"
2
15
 
3
16
  module Jun
4
-
17
+ class << self
18
+ attr_accessor :app_class
19
+
20
+ def application
21
+ @application ||= app_class&.new
22
+ end
23
+
24
+ def root
25
+ project_root_path
26
+ end
27
+
28
+ def env
29
+ ENV["JUN_ENV"] || ENV["RACK_ENV"] || "development"
30
+ end
31
+
32
+ def groups
33
+ [:default, env]
34
+ end
35
+
36
+ private
37
+
38
+ def project_root_path
39
+ current_dir = Dir.pwd
40
+ root_file = "config.ru"
41
+
42
+ while current_dir && File.directory?(current_dir) && !File.exist?("#{current_dir}/#{root_file}")
43
+ parent_dir = File.dirname(current_dir)
44
+ current_dir = parent_dir != current_dir && parent_dir
45
+ end
46
+
47
+ root_dir = current_dir if File.exist?("#{current_dir}/#{root_file}")
48
+ return if root_dir.nil?
49
+
50
+ Pathname.new(File.realpath(root_dir))
51
+ end
52
+ end
5
53
  end