From 5be25af7b8e3cbc037f256772d1402e58332a528 Mon Sep 17 00:00:00 2001 From: Jeff Peterson Date: Mon, 2 Dec 2024 17:54:57 -0500 Subject: [PATCH] update for namespaces. etc --- .../cafe_car/active_record/base_presenter.rb | 8 +++++++- app/presenters/cafe_car/presenter.rb | 3 ++- app/views/application/_filters.html.haml | 4 ++++ app/views/application/_form.html.haml | 2 +- lib/cafe_car/controller.rb | 2 +- lib/cafe_car/helpers.rb | 8 ++++++-- lib/cafe_car/link_builder.rb | 13 +++++++------ lib/cafe_car/query_builder.rb | 3 +++ lib/cafe_car/table/row_builder.rb | 2 +- test/cafe_car/queryable_test.rb | 2 +- .../app/controllers/admin/articles_controller.rb | 5 +++++ .../dummy/app/controllers/admin/users_controller.rb | 5 +++++ test/dummy/app/controllers/users_controller.rb | 3 --- test/dummy/app/models/article.rb | 1 + test/dummy/app/models/user.rb | 4 ++++ test/dummy/config/routes.rb | 8 ++++++-- 16 files changed, 54 insertions(+), 19 deletions(-) create mode 100644 test/dummy/app/controllers/admin/articles_controller.rb create mode 100644 test/dummy/app/controllers/admin/users_controller.rb delete mode 100644 test/dummy/app/controllers/users_controller.rb diff --git a/app/presenters/cafe_car/active_record/base_presenter.rb b/app/presenters/cafe_car/active_record/base_presenter.rb index ffd92ca..dd5981f 100644 --- a/app/presenters/cafe_car/active_record/base_presenter.rb +++ b/app/presenters/cafe_car/active_record/base_presenter.rb @@ -17,7 +17,13 @@ def associations(*names, **options, &block) end def to_model = object - def to_html = link_to title, [self] rescue title + def to_html + if partial? object.to_partial_path + render object + else + link_to title, [self] rescue title + end + end end end end diff --git a/app/presenters/cafe_car/presenter.rb b/app/presenters/cafe_car/presenter.rb index 5aa3a53..f322ee7 100644 --- a/app/presenters/cafe_car/presenter.rb +++ b/app/presenters/cafe_car/presenter.rb @@ -2,7 +2,7 @@ module CafeCar class Presenter attr_reader :object, :options - delegate *%w[l t capture concat link_to render safe_join tag ui], to: :@template + delegate *%w[l t capture concat link_to partial? render safe_join tag ui], to: :@template def self.present(template, object, **options) object = object.object if object.is_a?(Presenter) @@ -48,6 +48,7 @@ def attributes(*methods, except: nil, **options, &block) end def attribute(method, **options, &block) + # TODO: rescue from missing attribute errors and suggest checking the policy @shown_attributes[method] = true content = show(method, **options, &block).to_s return "" if content.blank? diff --git a/app/views/application/_filters.html.haml b/app/views/application/_filters.html.haml index 44a564f..d3c19e9 100644 --- a/app/views/application/_filters.html.haml +++ b/app/views/application/_filters.html.haml @@ -1,6 +1,10 @@ = ui.card do |card| = filter_form_for objects do |f| + = card.section do + - if title = policy(objects).title_attribute + = f.field "#{title}~", label: "Search" + - f.remaining_attributes.each do |attr| = f.field attr diff --git a/app/views/application/_form.html.haml b/app/views/application/_form.html.haml index 06366a2..da7b23a 100644 --- a/app/views/application/_form.html.haml +++ b/app/views/application/_form.html.haml @@ -1,4 +1,4 @@ -= form_for object do |f| += form_for [*namespace, object] do |f| = card.section do = render "fields", f: diff --git a/lib/cafe_car/controller.rb b/lib/cafe_car/controller.rb index 7e3ca45..3b44e09 100644 --- a/lib/cafe_car/controller.rb +++ b/lib/cafe_car/controller.rb @@ -126,7 +126,7 @@ def object=(value) def model_name = model.model_name def model - @model ||= self.class.name.gsub(/.*::|Controller$/, '').singularize.constantize + @model ||= self.class.name.gsub(/.*::|Controller$/, '').classify.then { self.class.module_parent.const_get _1 } end def created_redirect = redirect_back fallback_location: [model_name.plural.to_sym] diff --git a/lib/cafe_car/helpers.rb b/lib/cafe_car/helpers.rb index dfaccd6..e4ce9f6 100644 --- a/lib/cafe_car/helpers.rb +++ b/lib/cafe_car/helpers.rb @@ -41,10 +41,10 @@ def present(*args, **options) def current_href?(...) = current_page? href_for(...) - def href_for(*parts, **params) + def href_for(*parts, namespace: self.namespace, **params) params.merge! parts.extract_options! params.delete(:action) if %i[show destroy index].include? params[:action] - url_for([*parts, params]) + url_for([*namespace, *parts, params]) end def link(object) @@ -78,5 +78,9 @@ def get_partial(path) prefixes = path.include?(?/) ? [] : lookup_context.prefixes lookup_context.find(path, prefixes, true) end + + def namespace + @namespace ||= controller_path.split("/").tap(&:pop).map(&:to_sym) + end end end diff --git a/lib/cafe_car/link_builder.rb b/lib/cafe_car/link_builder.rb index e553854..5cd0e68 100644 --- a/lib/cafe_car/link_builder.rb +++ b/lib/cafe_car/link_builder.rb @@ -4,9 +4,10 @@ class LinkBuilder delegate :link_to, :link_to_unless, :current_page?, :href_for, to: :@template - def initialize(template, object) - @template = template - @object = object + def initialize(template, object, namespace: template.namespace) + @template = template + @object = object + @namespace = namespace end def model = @object.is_a?(Class) ? @object : @object.class @@ -28,8 +29,8 @@ def disabled(action, reason) = i18n(action, scope: [:disabled, reason]) def turbo!(opts) opts.replace({ - data: {turbo_stream: true, - turbo_method: opts.delete(:method), + data: {turbo_stream: true, + turbo_method: opts.delete(:method), turbo_confirm: opts.delete(:confirm) } }.deep_merge(opts)) @@ -39,7 +40,7 @@ def link(action, target, label = i18n(action), disabled: false, hide: false, **o disabled ||= cant?(action) return "" if disabled and hide - href = href_for(*target, action:) + href = href_for(*target, action:, namespace: @namespace) current = current_page?(href) link_to_unless(disabled || current, label, href, **turbo!(opts)) do diff --git a/lib/cafe_car/query_builder.rb b/lib/cafe_car/query_builder.rb index 86ddb49..e4cd9f3 100644 --- a/lib/cafe_car/query_builder.rb +++ b/lib/cafe_car/query_builder.rb @@ -63,6 +63,8 @@ def parse_value(key, value) value.exclude_end?) in Array | Op value.map { parse_value(key, _1) } + in "true" then true + in "false" then false in String case column(key)&.type || reflection(key)&.macro when :datetime then parse_time(value) || value @@ -140,6 +142,7 @@ def association!(name, value, ...) end def scope!(name, value) + value = parse_value(name, value) arity = (@scope.scopes[name] || @scope.method(name)).arity value = nil if arity == 0 and value == true diff --git a/lib/cafe_car/table/row_builder.rb b/lib/cafe_car/table/row_builder.rb index 921f998..7c11bd6 100644 --- a/lib/cafe_car/table/row_builder.rb +++ b/lib/cafe_car/table/row_builder.rb @@ -11,7 +11,7 @@ def policy = @template.policy(@object) def value(method) = present(@object.public_send(method)) def cell(method, *flags, href: nil, **options, &block) - href = @template.url_for(@object) if href == true + href = @template.href_for(@object) if href == true href = href.to_proc.(@object) if href.respond_to?(:to_proc) content = block ? capture(value(method), &block) : value(method) diff --git a/test/cafe_car/queryable_test.rb b/test/cafe_car/queryable_test.rb index c053fc4..85e0b8d 100644 --- a/test/cafe_car/queryable_test.rb +++ b/test/cafe_car/queryable_test.rb @@ -25,7 +25,7 @@ class QueryableTest < ActiveSupport::TestCase end test "query count" do - refute_empty User.query(articles: 1..5) + refute_empty User.query(articles: 1..5, title: /bob/) assert_empty User.query(articles: 99) refute_empty User.query(articles!: 99) end diff --git a/test/dummy/app/controllers/admin/articles_controller.rb b/test/dummy/app/controllers/admin/articles_controller.rb new file mode 100644 index 0000000..7c9e89e --- /dev/null +++ b/test/dummy/app/controllers/admin/articles_controller.rb @@ -0,0 +1,5 @@ +module Admin + class ArticlesController < ApplicationController + recline_in_the_cafe_car + end +end diff --git a/test/dummy/app/controllers/admin/users_controller.rb b/test/dummy/app/controllers/admin/users_controller.rb new file mode 100644 index 0000000..7572580 --- /dev/null +++ b/test/dummy/app/controllers/admin/users_controller.rb @@ -0,0 +1,5 @@ +module Admin + class UsersController < ApplicationController + recline_in_the_cafe_car + end +end diff --git a/test/dummy/app/controllers/users_controller.rb b/test/dummy/app/controllers/users_controller.rb deleted file mode 100644 index 3089ab4..0000000 --- a/test/dummy/app/controllers/users_controller.rb +++ /dev/null @@ -1,3 +0,0 @@ -class UsersController < ApplicationController - recline_in_the_cafe_car -end diff --git a/test/dummy/app/models/article.rb b/test/dummy/app/models/article.rb index d3bf1ce..882b020 100644 --- a/test/dummy/app/models/article.rb +++ b/test/dummy/app/models/article.rb @@ -8,6 +8,7 @@ class Article < ApplicationRecord scope :draft, -> { where(published_at: Time.zone.now..) } scope :published, -> { where(published_at: ..Time.zone.now) } scope :unpublished, -> { where(published_at: nil) } + scope :search, ->(term) { query("title~": term) } def published? = published_at && published_at < Time.zone.now def draft? = published_at && published_at > Time.zone.now diff --git a/test/dummy/app/models/user.rb b/test/dummy/app/models/user.rb index f8d3445..5a11e68 100644 --- a/test/dummy/app/models/user.rb +++ b/test/dummy/app/models/user.rb @@ -3,4 +3,8 @@ class User < ApplicationRecord has_secure_password validates :username, presence: true + + def self.search(query) + query("username~": query) + end end diff --git a/test/dummy/config/routes.rb b/test/dummy/config/routes.rb index 366dd0d..23e8303 100644 --- a/test/dummy/config/routes.rb +++ b/test/dummy/config/routes.rb @@ -1,9 +1,13 @@ Rails.application.routes.draw do - mount CafeCar::Engine => "/admin" get "up" => "rails/health#show", as: :rails_health_check resources :articles - resources :users + + namespace :admin do + mount CafeCar::Engine => "/" + resources :articles + resources :users + end get "*path", to: "pages#show", as: :page root "pages#show"