diff --git a/Gemfile b/Gemfile index 5509758..f05a350 100644 --- a/Gemfile +++ b/Gemfile @@ -1,5 +1,7 @@ source "https://rubygems.org" +gem "whetrails", path: "." + # Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main" gem "rails", "~> 8.1.3" # The modern asset pipeline for Rails [https://github.com/rails/propshaft] diff --git a/Gemfile.lock b/Gemfile.lock index ecf201b..0ddf7ba 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,3 +1,10 @@ +PATH + remote: . + specs: + whetrails (0.1.0) + activerecord (>= 7.0) + railties (>= 7.0) + GEM remote: https://rubygems.org/ specs: @@ -420,6 +427,7 @@ DEPENDENCIES turbo-rails tzinfo-data web-console + whetrails! BUNDLED WITH 2.5.22 diff --git a/app/controllers/whetrails/application_controller.rb b/app/controllers/whetrails/application_controller.rb new file mode 100644 index 0000000..a6cf91f --- /dev/null +++ b/app/controllers/whetrails/application_controller.rb @@ -0,0 +1,23 @@ +module Whetrails + class ApplicationController < ActionController::Base + layout "whetrails/application" + protect_from_forgery with: :exception + + before_action :load_all_models + + private + + def load_all_models + ::Rails.application.eager_load! + app_root = ::Rails.root.to_s + @all_models = ::ActiveRecord::Base.descendants + .reject(&:abstract_class?) + .reject { |m| m.name.nil? } + .select { |m| + file = Object.const_source_location(m.name)&.first rescue nil + file&.start_with?(app_root) + } + .sort_by(&:name) + end + end +end diff --git a/app/controllers/whetrails/models_controller.rb b/app/controllers/whetrails/models_controller.rb new file mode 100644 index 0000000..7746e81 --- /dev/null +++ b/app/controllers/whetrails/models_controller.rb @@ -0,0 +1,16 @@ +module Whetrails + class ModelsController < ApplicationController + def index + if @all_models.any? + redirect_to model_path(@all_models.first.name) + end + end + + def show + @model_class = params[:id].constantize + @chain = ::Whetrails::Inspector.inspect_model(@model_class) + rescue NameError + head :not_found + end + end +end diff --git a/app/helpers/whetrails/models_helper.rb b/app/helpers/whetrails/models_helper.rb new file mode 100644 index 0000000..14573ec --- /dev/null +++ b/app/helpers/whetrails/models_helper.rb @@ -0,0 +1,20 @@ +module Whetrails + module ModelsHelper + def vscode_uri(file, line) + "vscode://file/#{file}:#{line}" if file + end + + def short_path(file) + return nil unless file + file.sub("#{::Rails.root}/", "") + end + + def condition_label(c) + c.is_a?(Symbol) ? ":#{c}" : "<proc>" + end + + def validator_type_label(type) + type.split("::").last.sub("Validator", "").downcase + end + end +end diff --git a/app/views/layouts/whetrails/application.html.erb b/app/views/layouts/whetrails/application.html.erb new file mode 100644 index 0000000..54e6e8c --- /dev/null +++ b/app/views/layouts/whetrails/application.html.erb @@ -0,0 +1,210 @@ + + +
+No callbacks registered.
+<% end %> + +<% if @chain.validators.any? %> +No validators registered.
+<% end %> diff --git a/config/application.rb b/config/application.rb index 718557f..39bb6e6 100644 --- a/config/application.rb +++ b/config/application.rb @@ -14,7 +14,8 @@ module Whetrails # Please, add to the `ignore` list any other `lib` subdirectories that do # not contain `.rb` files, or that should not be reloaded or eager loaded. # Common ones are `templates`, `generators`, or `middleware`, for example. - config.autoload_lib(ignore: %w[assets tasks]) + # lib/whetrails/**/* uses manual requires (gem source), not Zeitwerk autoloading + config.autoload_lib(ignore: %w[assets tasks whetrails.rb whetrails]) # Configuration for the application, engines, and railties goes here. # diff --git a/config/routes.rb b/config/routes.rb index 48254e8..77fb6f0 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,4 +1,6 @@ Rails.application.routes.draw do + mount Whetrails::Engine, at: "/whetrails" + # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html # Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500. diff --git a/lib/whetrails.rb b/lib/whetrails.rb index 88db6bf..48b3414 100644 --- a/lib/whetrails.rb +++ b/lib/whetrails.rb @@ -1,6 +1,7 @@ require_relative "whetrails/version" require_relative "whetrails/chain" require_relative "whetrails/inspector" +require_relative "whetrails/engine" if defined?(Rails) module Whetrails def self.inspect_model(model_class) diff --git a/lib/whetrails/engine.rb b/lib/whetrails/engine.rb new file mode 100644 index 0000000..957ba48 --- /dev/null +++ b/lib/whetrails/engine.rb @@ -0,0 +1,9 @@ +module Whetrails + class Engine < ::Rails::Engine + isolate_namespace Whetrails + + # In the gem's dev setup, config/routes.rb belongs to the host app. + # Point the engine's routing path to a dedicated file. + config.paths.add "config/routes.rb", with: "lib/whetrails/engine_routes.rb" + end +end diff --git a/lib/whetrails/engine_routes.rb b/lib/whetrails/engine_routes.rb new file mode 100644 index 0000000..9793df1 --- /dev/null +++ b/lib/whetrails/engine_routes.rb @@ -0,0 +1,4 @@ +Whetrails::Engine.routes.draw do + resources :models, only: [:index, :show] + root to: "models#index" +end diff --git a/whetrails.gemspec b/whetrails.gemspec index 776c054..1642424 100644 --- a/whetrails.gemspec +++ b/whetrails.gemspec @@ -12,7 +12,7 @@ Gem::Specification.new do |spec| spec.required_ruby_version = ">= 3.0" - spec.files = Dir["lib/**/*.rb", "exe/*", "LICENSE", "README.md"] + spec.files = Dir["lib/**/*.rb", "app/**/*.rb", "app/views/**/*.erb", "config/**/*.rb", "exe/*", "LICENSE", "README.md"] spec.executables = ["whetrails"] spec.add_dependency "railties", ">= 7.0"