ditty 0.8.0 → 0.9.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 (123) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.pryrc +2 -0
  4. data/.rubocop.yml +1 -1
  5. data/.travis.yml +5 -4
  6. data/CNAME +1 -0
  7. data/Dockerfile +18 -0
  8. data/Gemfile.ci +0 -2
  9. data/Rakefile +2 -2
  10. data/_config.yml +1 -0
  11. data/config.ru +4 -4
  12. data/ditty.gemspec +9 -3
  13. data/docs/CNAME +1 -0
  14. data/docs/_config.yml +1 -0
  15. data/docs/index.md +34 -0
  16. data/exe/ditty +2 -0
  17. data/lib/ditty.rb +4 -2
  18. data/lib/ditty/cli.rb +28 -4
  19. data/lib/ditty/components/{app.rb → ditty.rb} +19 -14
  20. data/lib/ditty/controllers/{application.rb → application_controller.rb} +58 -29
  21. data/lib/ditty/controllers/{audit_logs.rb → audit_logs_controller.rb} +2 -2
  22. data/lib/ditty/controllers/{auth.rb → auth_controller.rb} +17 -16
  23. data/lib/ditty/controllers/{component.rb → component_controller.rb} +19 -18
  24. data/lib/ditty/controllers/{main.rb → main_controller.rb} +6 -2
  25. data/lib/ditty/controllers/roles_controller.rb +23 -0
  26. data/lib/ditty/controllers/{user_login_traits.rb → user_login_traits_controller.rb} +4 -3
  27. data/lib/ditty/controllers/{users.rb → users_controller.rb} +11 -10
  28. data/lib/ditty/db.rb +4 -3
  29. data/lib/ditty/emails/base.rb +5 -2
  30. data/lib/ditty/generators/crud_generator.rb +104 -0
  31. data/lib/ditty/generators/migration_generator.rb +26 -0
  32. data/lib/ditty/generators/project_generator.rb +51 -0
  33. data/lib/ditty/helpers/component.rb +2 -1
  34. data/lib/ditty/helpers/pundit.rb +20 -4
  35. data/lib/ditty/helpers/response.rb +20 -13
  36. data/lib/ditty/helpers/views.rb +7 -3
  37. data/lib/ditty/listener.rb +5 -3
  38. data/lib/ditty/memcached.rb +8 -0
  39. data/lib/ditty/middleware/accept_extension.rb +2 -2
  40. data/lib/ditty/middleware/error_catchall.rb +2 -2
  41. data/lib/ditty/models/base.rb +4 -0
  42. data/lib/ditty/models/role.rb +1 -0
  43. data/lib/ditty/models/user.rb +14 -1
  44. data/lib/ditty/policies/role_policy.rb +1 -1
  45. data/lib/ditty/policies/user_login_trait_policy.rb +1 -1
  46. data/lib/ditty/services/authentication.rb +11 -10
  47. data/lib/ditty/services/email.rb +8 -4
  48. data/lib/ditty/services/logger.rb +1 -1
  49. data/lib/ditty/tasks/ditty.rake +17 -0
  50. data/lib/ditty/tasks/omniauth-ldap.rake +2 -2
  51. data/lib/ditty/templates/.gitignore +5 -0
  52. data/lib/ditty/templates/.rspec +2 -0
  53. data/lib/ditty/templates/.rubocop.yml +7 -0
  54. data/lib/ditty/templates/Rakefile +12 -0
  55. data/lib/ditty/templates/application.rb +12 -0
  56. data/lib/ditty/templates/config.ru +37 -0
  57. data/lib/ditty/templates/controller.rb.erb +58 -0
  58. data/lib/ditty/templates/env.example +4 -0
  59. data/lib/ditty/templates/lib/project.rb.erb +5 -0
  60. data/lib/ditty/templates/migration.rb.erb +7 -0
  61. data/lib/ditty/templates/model.rb.erb +26 -0
  62. data/lib/ditty/templates/pids/.empty_directory +0 -0
  63. data/lib/ditty/templates/policy.rb.erb +48 -0
  64. data/lib/ditty/templates/public/css/sb-admin-2.min.css +10 -0
  65. data/lib/ditty/templates/public/js/sb-admin-2.min.js +7 -0
  66. data/lib/ditty/templates/settings.yml.erb +18 -0
  67. data/lib/ditty/templates/sidekiq.rb +18 -0
  68. data/lib/ditty/templates/sidekiq.yml +9 -0
  69. data/lib/ditty/templates/spec_helper.rb +43 -0
  70. data/lib/ditty/templates/type.rb.erb +21 -0
  71. data/lib/ditty/templates/views/display.haml.tt +20 -0
  72. data/lib/ditty/templates/views/edit.haml.tt +10 -0
  73. data/lib/ditty/templates/views/form.haml.tt +11 -0
  74. data/lib/ditty/templates/views/index.haml.tt +29 -0
  75. data/lib/ditty/templates/views/new.haml.tt +10 -0
  76. data/lib/ditty/version.rb +1 -1
  77. data/lib/rubocop/cop/ditty/call_services_directly.rb +2 -2
  78. data/migrate/20181209_add_user_login_traits.rb +4 -4
  79. data/migrate/20190220_add_parent_id_to_roles.rb +9 -0
  80. data/public/css/styles.css +13 -0
  81. data/public/js/scripts.js +1 -0
  82. data/views/404.haml +2 -4
  83. data/views/audit_logs/index.haml +32 -34
  84. data/views/auth/forgot_password.haml +27 -16
  85. data/views/auth/identity.haml +14 -13
  86. data/views/auth/ldap.haml +2 -2
  87. data/views/auth/login.haml +22 -17
  88. data/views/auth/register.haml +19 -18
  89. data/views/auth/register_identity.haml +27 -12
  90. data/views/auth/reset_password.haml +2 -2
  91. data/views/blank.haml +42 -0
  92. data/views/index.haml +1 -1
  93. data/views/layout.haml +37 -30
  94. data/views/partials/content_tag.haml +0 -0
  95. data/views/partials/delete_form.haml +1 -1
  96. data/views/partials/filter_control.haml +1 -1
  97. data/views/partials/footer.haml +5 -5
  98. data/views/partials/form_control.haml +19 -12
  99. data/views/partials/navitems.haml +44 -0
  100. data/views/partials/notifications.haml +12 -8
  101. data/views/partials/pager.haml +17 -17
  102. data/views/partials/search.haml +6 -7
  103. data/views/partials/sidebar.haml +15 -37
  104. data/views/partials/topbar.haml +68 -0
  105. data/views/roles/display.haml +27 -6
  106. data/views/roles/edit.haml +3 -3
  107. data/views/roles/form.haml +1 -0
  108. data/views/roles/index.haml +23 -16
  109. data/views/roles/new.haml +2 -2
  110. data/views/user_login_traits/display.haml +4 -4
  111. data/views/user_login_traits/edit.haml +3 -3
  112. data/views/user_login_traits/index.haml +4 -4
  113. data/views/user_login_traits/new.haml +2 -2
  114. data/views/users/display.haml +11 -12
  115. data/views/users/edit.haml +3 -3
  116. data/views/users/form.haml +0 -0
  117. data/views/users/index.haml +31 -24
  118. data/views/users/login_traits.haml +6 -8
  119. data/views/users/new.haml +2 -2
  120. data/views/users/profile.haml +13 -13
  121. metadata +143 -15
  122. data/lib/ditty/controllers/roles.rb +0 -13
  123. data/views/partials/navbar.haml +0 -22
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2b391296636a3f248171d3d71ca4c11466b8cce56f8814c271f2352e241da297
4
- data.tar.gz: 8b136a384187ea59d6d8caa8f46f3dcc7a4a72939ba924ddff0eb8a332828aa1
3
+ metadata.gz: 35f3891fe07db1d74d92de59cbcf9ebde20c7aa9f5fdc995a5bed98445ac38de
4
+ data.tar.gz: 2ed19a9d156c4a043aa3d29b8ad070ed70da16637a88577ef74630734038868e
5
5
  SHA512:
6
- metadata.gz: 8102d97c1b3516e4f922600055a22b5bff5293dd69fbcb92a5cd233ad0e9f2e52fc6f091e05aebcee9e1dd610e76b0049db29b1eccfd54ff09f794325156cf68
7
- data.tar.gz: c1ad5e59438e58fc6dbc34d5d2a95b1c5da4a0ccb88481fc15b9dd5942ece2d7525adcf52d3d520f9fd2c91dff65829d24a27ad8fb60d66889ac6f9b983c2fba
6
+ metadata.gz: b11cb4cdab8e3afa910750884a5129becfe68202f779a35011e368a3d872724a41d2b3bd90b06485fdbdea740fbbe1c7165a8da50095ab7c7d767c28c2595185
7
+ data.tar.gz: 9e06c150bc6fd18dcc564dae5cf43bc3d9a5327541df1d64dd7b6f305381d83102ef1c9105ae4a9bcfe82cfa11881eda1fb93ec2321bd549072d92c2ee0c4acb
data/.gitignore CHANGED
@@ -14,3 +14,5 @@ vendor
14
14
  *.db
15
15
  /Gemfile.dev.lock
16
16
  migrations
17
+ /gems.*
18
+ .env
data/.pryrc CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  if defined?(PryByebug)
2
4
  Pry.commands.alias_command 'c', 'continue'
3
5
  Pry.commands.alias_command 's', 'step'
@@ -1,7 +1,7 @@
1
1
  require: rubocop-rspec
2
2
 
3
3
  AllCops:
4
- TargetRubyVersion: 2.3
4
+ TargetRubyVersion: 2.7
5
5
  Metrics/LineLength:
6
6
  Max: 120
7
7
  Layout/LeadingCommentSpace:
@@ -1,10 +1,11 @@
1
1
  sudo: false
2
2
  language: ruby
3
3
  rvm:
4
- - 2.6.0
5
- - 2.5.3
6
- - 2.4.5
7
- - 2.3.8
4
+ - 2.7
5
+ - 2.6
6
+ - 2.5
7
+ - 2.4
8
+ - 2.3
8
9
  gemfile: Gemfile.ci
9
10
  env:
10
11
  global:
data/CNAME ADDED
@@ -0,0 +1 @@
1
+ ditty.io
@@ -0,0 +1,18 @@
1
+ FROM ruby:2.5.3-alpine3.8
2
+ LABEL maintainer: "Sergey Shkarupa <s.shkarupa@gmail.com>"
3
+
4
+ RUN apk add --no-cache \
5
+ build-base \
6
+ less \
7
+ git \
8
+ libxml2-dev \
9
+ libxslt-dev \
10
+ sqlite-dev \
11
+ sqlite-doc \
12
+ sqlite-libs \
13
+ && gem install bundler:1.17.3
14
+
15
+ WORKDIR /usr/src/app
16
+
17
+ COPY . ./
18
+ RUN bundle install --jobs=$(nproc) --no-cache --clean
data/Gemfile.ci CHANGED
@@ -4,8 +4,6 @@ source 'https://rubygems.org'
4
4
  gemspec
5
5
 
6
6
  gem 'faker'
7
- gem 'rubocop'
8
- gem 'rubocop-rspec'
9
7
  gem 'simplecov', '~> 0.13.0'
10
8
  gem 'sqlite3'
11
9
 
data/Rakefile CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  require 'rake'
4
4
  require 'ditty'
5
- require 'ditty/components/app'
5
+ require 'ditty/components/ditty'
6
6
 
7
- Ditty.component :app
7
+ Ditty.component :ditty
8
8
 
9
9
  Ditty::Components.tasks
10
10
  require 'bundler/gem_tasks' if File.exist? 'ditty.gemspec'
@@ -0,0 +1 @@
1
+ theme: jekyll-theme-architect
data/config.ru CHANGED
@@ -6,14 +6,14 @@ use Rack::Session::Cookie,
6
6
  # :secure=>!TEST_MODE, # Uncomment if only allowing https:// access
7
7
  secret: File.read('.session_secret')
8
8
 
9
- require 'ditty/components/app'
10
- Ditty.component :app
9
+ require 'ditty/components/ditty'
10
+ Ditty.component :ditty
11
11
 
12
12
  require 'ditty/services/authentication'
13
13
  use OmniAuth::Builder do
14
- Ditty::Services::Authentication.config.each do |prov, config|
14
+ ::Ditty::Services::Authentication.config.each do |prov, config|
15
15
  provider prov, *config[:arguments]
16
16
  end
17
17
  end
18
18
 
19
- run Rack::URLMap.new Ditty::Components.routes
19
+ run Rack::URLMap.new ::Ditty::Components.routes
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- lib = File.expand_path('../lib', __FILE__)
3
+ lib = File.expand_path('lib', __dir__)
4
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
  require 'ditty/version'
6
6
 
7
7
  Gem::Specification.new do |spec|
8
8
  spec.name = 'ditty'
9
- spec.version = Ditty::VERSION
9
+ spec.version = ::Ditty::VERSION
10
10
  spec.authors = ['Jurgens du Toit']
11
11
  spec.email = ['jrgns@jadeit.co.za']
12
12
 
@@ -26,12 +26,18 @@ Gem::Specification.new do |spec|
26
26
  spec.add_development_dependency 'rack-test'
27
27
  spec.add_development_dependency 'racksh'
28
28
  spec.add_development_dependency 'rspec', '~> 3.0'
29
+ spec.add_development_dependency 'rubocop'
30
+ spec.add_development_dependency 'rubocop-performance'
31
+ spec.add_development_dependency 'rubocop-rspec'
32
+ spec.add_development_dependency 'rubocop-sequel'
33
+ spec.add_development_dependency 'rubocop-thread_safety'
29
34
  spec.add_development_dependency 'timecop'
30
35
 
31
36
  spec.add_dependency 'activesupport', '>= 3'
32
37
  spec.add_dependency 'bcrypt', '~> 3.1'
33
38
  spec.add_dependency 'browser', '~> 2.5'
34
- spec.add_dependency 'haml', '~> 5.0'
39
+ spec.add_dependency 'dotenv', '>= 2'
40
+ spec.add_dependency 'haml', '~> 5.1.2'
35
41
  spec.add_dependency 'logger', '~> 1.0'
36
42
  spec.add_dependency 'mail', '>= 1.7'
37
43
  spec.add_dependency 'oga', '>= 2.14'
@@ -0,0 +1 @@
1
+ ditty.io
@@ -0,0 +1 @@
1
+ theme: jekyll-theme-architect
@@ -0,0 +1,34 @@
1
+ # Ditty.io
2
+
3
+ Ditty is a Web Application Framework built on top of the [Sinatra](http://sinatrarb.com/) framework.
4
+
5
+ ## Installation
6
+
7
+ Add these lines to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'ditty'
11
+ gem 'sqlite3'
12
+ ```
13
+
14
+ You can replace `sqlite3` with a DB adapter of your choice.
15
+
16
+ And then execute:
17
+
18
+ ```bash
19
+ bundle install
20
+ ```
21
+
22
+ Or install it yourself as:
23
+
24
+ ```bash
25
+ gem install ditty
26
+ ```
27
+
28
+ ## Usage
29
+
30
+ 1. Add the components to your rack config file. See the included [`config.ru`](https://github.com/EagerELK/ditty/blob/master/config.ru) file for an example setup
31
+ 2. Set the DB connection as the `DATABASE_URL` ENV variable: `DATABASE_URL=sqlite://development.db`
32
+ 3. Prepare the Ditty folder: `bundle exec ditty prep`
33
+ 3. Run the Ditty migrations: `bundle exec ditty migrate`
34
+ 4. Run the Ditty server: `bundle exec ditty server`
data/exe/ditty CHANGED
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
2
4
  require 'ditty/cli'
3
5
 
4
6
  Ditty::CLI.start
@@ -62,7 +62,9 @@ module Ditty
62
62
  h = @components
63
63
  unless (component = h[name])
64
64
  require "ditty/components/#{name}"
65
- raise ComponentError, "Component #{name} did not register itself correctly in Ditty::Components" unless (component = h[name])
65
+ unless (component = h[name])
66
+ raise ComponentError, "Component #{name} did not register itself correctly in Ditty::Components"
67
+ end
66
68
  end
67
69
  component
68
70
  end
@@ -76,7 +78,7 @@ module Ditty
76
78
  #
77
79
  # Ditty::Components.register_component(:component_name, ComponentModule)
78
80
  def self.register_component(name, mod)
79
- Ditty::Services::Logger.instance.info "Registering #{mod} as #{name}"
81
+ ::Ditty::Services::Logger.info "Registering #{mod} as #{name}"
80
82
  @components[name] = mod
81
83
  end
82
84
 
@@ -1,24 +1,38 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # https://nandovieira.com/creating-generators-and-executables-with-thor
4
- require 'dotenv/load'
4
+ require 'dotenv/load' rescue LoadError # rubocop:disable Style/RescueModifier - Ignore dotenv/load errors
5
5
  require 'thor'
6
6
  require 'rack'
7
7
  require 'rake'
8
+ require 'ditty/db' if ENV['DATABASE_URL']
9
+ require 'ditty/generators/crud_generator'
10
+ require 'ditty/generators/project_generator'
11
+ require 'ditty/generators/migration_generator'
12
+ require 'ditty/components/ditty'
8
13
 
9
14
  module Ditty
10
15
  class CLI < Thor
11
16
  include Thor::Actions
12
17
 
18
+ register ::Ditty::Generators::CrudGenerator, 'crud', 'crud NAME', 'Generate a CRUD endpoint'
19
+
20
+ register ::Ditty::Generators::ProjectGenerator, 'init', 'init', 'Initialize a Ditty Project'
21
+
22
+ register ::Ditty::Generators::MigrationGenerator, 'migration', 'migration NAME', 'Create a new Sequel migration'
23
+
24
+ default_task :server
25
+
13
26
  desc 'server', 'Start the Ditty server'
14
27
  require './application' if File.exist?('application.rb')
15
- Ditty::Components.tasks
28
+ ::Ditty::Components.tasks
16
29
  def server
17
30
  # Ensure the token files are present
18
31
  Rake::Task['ditty:generate_tokens'].invoke
19
32
 
20
33
  # Prep Ditty
21
- Rake::Task['ditty:prep'].invoke
34
+ Rake::Task['ditty:prep:folders'].invoke
35
+ Rake::Task['ditty:prep:migrations'].invoke
22
36
 
23
37
  # Check the migrations
24
38
  Rake::Task['ditty:migrate:check'].invoke
@@ -35,7 +49,7 @@ module Ditty
35
49
  desc 'migrate', 'Run the Ditty migrations'
36
50
  def migrate
37
51
  # Prep Ditty
38
- Rake::Task['ditty:prep'].invoke
52
+ Rake::Task['ditty:prep:migrations'].invoke
39
53
 
40
54
  # Run the migrations
41
55
  Rake::Task['ditty:migrate:up'].invoke
@@ -44,5 +58,15 @@ module Ditty
44
58
  Rake::Task['ditty:dump_schema'].invoke
45
59
  puts 'Ditty DB Schema Dumped'
46
60
  end
61
+
62
+ desc 'seed', 'Seed the predefined seeind data'
63
+ def seed
64
+ Rake::Task['ditty:seed'].invoke
65
+ end
66
+
67
+ desc 'console', 'Open a fully loaded console'
68
+ def console
69
+ Rake::Task['ditty:console'].invoke
70
+ end
47
71
  end
48
72
  end
@@ -4,10 +4,10 @@ require 'ditty'
4
4
  require 'ditty/services/settings'
5
5
 
6
6
  module Ditty
7
- class App
7
+ class Ditty
8
8
  def self.load
9
9
  controllers = File.expand_path('../controllers', __dir__)
10
- Dir.glob("#{controllers}/*.rb").each { |f| require f }
10
+ Dir.glob("#{controllers}/*.rb").sort.each { |f| require f }
11
11
 
12
12
  require 'ditty/models/user'
13
13
  require 'ditty/models/role'
@@ -29,15 +29,19 @@ module Ditty
29
29
  File.expand_path('../../../views', __dir__)
30
30
  end
31
31
 
32
+ def self.public_folder
33
+ File.expand_path('../../../public', __dir__)
34
+ end
35
+
32
36
  def self.routes
33
37
  load
34
38
  {
35
- '/' => ::Ditty::Main,
36
- '/auth' => ::Ditty::Auth,
37
- '/users' => ::Ditty::Users,
38
- '/roles' => ::Ditty::Roles,
39
- '/audit-logs' => ::Ditty::AuditLogs,
40
- '/login-traits' => ::Ditty::UserLoginTraits
39
+ '/' => ::Ditty::MainController,
40
+ '/auth' => ::Ditty::AuthController,
41
+ '/users' => ::Ditty::UsersController,
42
+ '/roles' => ::Ditty::RolesController,
43
+ '/audit-logs' => ::Ditty::AuditLogsController,
44
+ '/login-traits' => ::Ditty::UserLoginTraitsController
41
45
  }
42
46
  end
43
47
 
@@ -53,7 +57,8 @@ module Ditty
53
57
  items: [
54
58
  { order: 10, link: '/users/', text: 'Users', target: ::Ditty::User, icon: 'user' },
55
59
  { order: 20, link: '/roles/', text: 'Roles', target: ::Ditty::Role, icon: 'check-square' },
56
- { order: 30, link: '/audit-logs/', text: 'Audit Logs', target: ::Ditty::AuditLog, icon: 'history' }
60
+ { order: 30, link: '/audit-logs/', text: 'Audit Logs', target: ::Ditty::AuditLog, icon: 'history' },
61
+ { order: 40, link: '/login-traits/', text: 'User Login Traits', target: ::Ditty::UserLoginTrait, icon: 'list' }
57
62
  ]
58
63
  }
59
64
  ]
@@ -63,18 +68,18 @@ module Ditty
63
68
  proc do
64
69
  load
65
70
 
66
- ::Ditty::Role.find_or_create(name: 'super_admin')
67
- ::Ditty::Role.find_or_create(name: 'admin')
68
- ::Ditty::Role.find_or_create(name: 'user')
71
+ sa = ::Ditty::Role.find_or_create(name: 'super_admin')
72
+ admin = ::Ditty::Role.find_or_create(name: 'admin') { |e| e.parent = sa }
73
+ ::Ditty::Role.find_or_create(name: 'user') { |e| e.parent = admin }
69
74
  end
70
75
  end
71
76
 
72
77
  def self.tasks
73
78
  Kernel.load 'ditty/tasks/ditty.rake'
74
- auth_settings = Ditty::Services::Settings[:authentication] || {}
79
+ auth_settings = ::Ditty::Services::Settings[:authentication] || {}
75
80
  Kernel.load 'ditty/tasks/omniauth-ldap.rake' if auth_settings.key?(:ldap)
76
81
  end
77
82
  end
78
83
  end
79
84
 
80
- Ditty::Components.register_component(:app, Ditty::App)
85
+ Ditty::Components.register_component(:ditty, Ditty::Ditty)
@@ -17,13 +17,14 @@ require 'rack/contrib'
17
17
  require 'rack/csrf'
18
18
 
19
19
  module Ditty
20
- class Application < Sinatra::Base
20
+ class ApplicationController < Sinatra::Base
21
21
  include ActiveSupport::Inflector
22
22
 
23
23
  set :root, ENV['APP_ROOT'] || ::File.expand_path(::File.dirname(__FILE__) + '/../../../')
24
24
  set :map_path, nil
25
25
  set :view_location, nil
26
26
  set :view_folder, nil
27
+ set :base_path, nil
27
28
  set :model_class, nil
28
29
  set :raise_sinatra_param_exceptions, true
29
30
  set track_actions: false
@@ -42,7 +43,7 @@ module Ditty
42
43
 
43
44
  helpers do
44
45
  def logger
45
- Ditty::Services::Logger.instance
46
+ ::Ditty::Services::Logger
46
47
  end
47
48
 
48
49
  def base_path
@@ -51,9 +52,9 @@ module Ditty
51
52
 
52
53
  def view_location
53
54
  return settings.view_location if settings.view_location
54
- return underscore(pluralize(demodulize(settings.model_class))) if settings.model_class
55
55
 
56
- underscore(demodulize(self.class))
56
+ loc = demodulize(settings.model_class || self.class)
57
+ pluralize(underscore(loc.gsub(/Controller\Z/, '')))
57
58
  end
58
59
 
59
60
  def browser
@@ -61,24 +62,26 @@ module Ditty
61
62
  end
62
63
 
63
64
  def config(name, default = '')
64
- Ditty::Services::Settings[name] || default
65
+ ::Ditty::Services::Settings[name] || default
65
66
  end
66
67
  end
67
68
 
68
69
  def view_folders
69
70
  folders = ['./views']
70
71
  folders << settings.view_folder if settings.view_folder
71
- folders << Ditty::App.view_folder
72
+ folders << ::Ditty::Ditty.view_folder
72
73
  end
73
74
 
74
75
  def find_template(views, name, engine, &block)
75
76
  # Backwards compatability
76
- return super(views, name, engine, &block) if settings.view_folder.nil? && self.class.name.split('::').first != 'Ditty'
77
+ if settings.view_folder.nil? && self.class.name.split('::').first != 'Ditty'
78
+ return super(views, name, engine, &block)
79
+ end
77
80
 
78
81
  view_folders.each do |folder|
79
82
  super(folder, name, engine, &block) # Root
80
83
  end
81
- raise Ditty::TemplateNotFoundError, "Could not find template `#{name}`"
84
+ raise ::Ditty::TemplateNotFoundError, "Could not find template `#{name}`"
82
85
  end
83
86
 
84
87
  configure :production do
@@ -92,7 +95,7 @@ module Ditty
92
95
 
93
96
  configure :production, :development do
94
97
  disable :logging
95
- use Rack::CommonLogger, Ditty::Services::Logger.instance
98
+ use Rack::CommonLogger, ::Ditty::Services::Logger
96
99
  end
97
100
 
98
101
  not_found do
@@ -102,7 +105,11 @@ module Ditty
102
105
  haml :'404', locals: { title: '4 oh 4' }, layout: layout
103
106
  end
104
107
  format.json do
105
- json code: 404, errors: ['Not Found']
108
+ if response.body.empty?
109
+ json code: 404, errors: ['Not Found']
110
+ else
111
+ [404, response.body]
112
+ end
106
113
  end
107
114
  end
108
115
  end
@@ -134,30 +141,46 @@ module Ditty
134
141
  end
135
142
  end
136
143
 
137
- error Sequel::ValidationFailed do
144
+ error ::Sinatra::Param::InvalidParameterError do
138
145
  respond_to do |format|
139
- entity = env['sinatra.error'].model
140
- errors = env['sinatra.error'].errors
141
146
  status 400
142
147
  format.html do
143
- action = entity.id ? :edit : :new
144
- haml :"#{view_location}/#{action}", locals: { entity: entity, title: heading(action) }, layout: layout
148
+ flash.now[:danger] = env['sinatra.error'].message
149
+ haml :'400', locals: { title: '4 oh oh' }, layout: layout
145
150
  end
146
151
  format.json do
147
- json code: 400, errors: errors, full_errors: errors.full_messages
152
+ json code: 400, errors: { env['sinatra.error'].param => env['sinatra.error'].message }, full_errors: [env['sinatra.error'].message]
148
153
  end
149
154
  end
150
155
  end
151
156
 
152
- error Sinatra::Param::InvalidParameterError do
157
+ error ::Sequel::NoMatchingRow do
153
158
  respond_to do |format|
159
+ status 404
160
+ format.html do
161
+ haml :'404', locals: { title: '4 oh 4' }, layout: layout
162
+ end
163
+ format.json do
164
+ if response.body.empty?
165
+ json code: 404, errors: ['Not Found']
166
+ else
167
+ [404, response.body]
168
+ end
169
+ end
170
+ end
171
+ end
172
+
173
+ error ::Sequel::ValidationFailed do
174
+ respond_to do |format|
175
+ entity = env['sinatra.error'].model
176
+ errors = env['sinatra.error'].errors
154
177
  status 400
155
178
  format.html do
156
- flash.now[:danger] = env['sinatra.error'].message
157
- haml :'400', locals: { title: '4 oh oh' }, layout: layout
179
+ action = entity.id ? :edit : :new
180
+ haml :"#{view_location}/#{action}", locals: { entity: entity, title: heading(action) }, layout: layout
158
181
  end
159
182
  format.json do
160
- json code: 400, errors: { env['sinatra.error'].param => env['sinatra.error'].message }, full_errors: [env['sinatra.error'].message]
183
+ json code: 400, errors: errors, full_errors: errors.full_messages
161
184
  end
162
185
  end
163
186
  end
@@ -177,7 +200,7 @@ module Ditty
177
200
  end
178
201
  end
179
202
 
180
- error Ditty::TemplateNotFoundError do
203
+ error ::Ditty::TemplateNotFoundError do
181
204
  # TODO: Display a better error message
182
205
  error = env['sinatra.error']
183
206
  broadcast(:application_error, error)
@@ -207,10 +230,10 @@ module Ditty
207
230
 
208
231
  before(/.*/) do
209
232
  logger.info "Running with #{self.class} - #{request.path_info}"
210
- if request.path =~ /.*\.json\Z/
233
+ if /.*\.json\Z/.match?(request.path)
211
234
  content_type :json
212
235
  request.path_info = request.path_info.gsub(/.json$/, '')
213
- elsif request.path =~ /.*\.csv\Z/
236
+ elsif /.*\.csv\Z/.match?(request.path)
214
237
  content_type :csv
215
238
  request.path_info = request.path_info.gsub(/.csv$/, '')
216
239
  elsif request.env['ACCEPT']
@@ -222,15 +245,21 @@ module Ditty
222
245
 
223
246
  after do
224
247
  return if params[:layout].nil?
248
+ return unless response.body.respond_to?(:map)
225
249
 
226
- response.body = response.body.map do |resp|
227
- document = Oga.parse_html(resp)
228
- document.css('a').each do |elm|
229
- unless (href = elm.get('href')).nil?
230
- elm.set 'href', with_layout(href)
250
+ begin
251
+ orig = response.body
252
+ response.body = response.body.map do |resp|
253
+ document = Oga.parse_html(resp)
254
+ document.css('a').each do |elm|
255
+ unless (href = elm.get('href')).nil?
256
+ elm.set 'href', with_layout(href)
257
+ end
231
258
  end
259
+ document.to_xml
232
260
  end
233
- document.to_xml
261
+ rescue StandardError => _e
262
+ orig
234
263
  end
235
264
  end
236
265
  end