base_editing_bootstrap 1.8.1 → 1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 40690c34bdbdecebbcf083394fefe5ea626b958a085ce695fe4a039b17c8cfa9
4
- data.tar.gz: a087acc3bda536ea0451af2e3818cc2c07c20a3a6a5e549bb74e96d7abcd6dd5
3
+ metadata.gz: e3e85aa56464a6efc36c36170a8d8473b8c6c97107f62ba9a3d9599232c0d30b
4
+ data.tar.gz: 48c8890bba4d8740cfb1a210a93a9743b658fa3ef505f0c39db5b6b621504a35
5
5
  SHA512:
6
- metadata.gz: f85bc8f2ed0aa273b2e59258ace609e711dbcb088bf9420a5eaf5a48aa7a48c0907f7d6eb75ac9614cfcf0f536f1124a7bd9ee9541c68c3f4d29908e739a280d
7
- data.tar.gz: 5565e435135fd2bae6a1a6e1907a6d150cb6be69d5b82c52d91095a3637efa811322519ae6f696578760b961339cd986b036f508a06d08532311f88d53209508
6
+ metadata.gz: 9716d018b278998444613dec959a1cf70938d17b02828ff3c5b4bd1efa3ef5ec94e46fefcc06de6f8329f04201f12a2a57ad3375867d5e9f693f0c18a16db4e3
7
+ data.tar.gz: 6236f739ce354a526bbab9664337dccecc6b54f39976c7491cbc3bc15b8d8d4f310714bb0df6c08b5815d37343563da1dfc1528d6b865cf7eaadcd6c235bad5d
data/CHANGELOG.md CHANGED
@@ -2,6 +2,25 @@
2
2
  All notable changes to this project will be documented in this file. See [conventional commits](https://www.conventionalcommits.org/) for commit guidelines.
3
3
 
4
4
  - - -
5
+ ## 1.9.0 - 2025-07-30
6
+ #### Bug Fixes
7
+ - Correct add is-invalid class on relation fields - (21e4a92) - Marino Bonetti
8
+ - Correct path generator for namespaced resources - (a4f72c8) - Marino Bonetti
9
+ - Migliore formattazione generatore - (1ceda4d) - Marino Bonetti
10
+ - Creazione dei nested attributi necessari con belongs to - (564f61b) - Marino Bonetti
11
+ - Correct Shared Specs - (1994128) - Marino Bonetti
12
+ - Authentication Model configurable (#19) - (cef424f) - Marino Bonetti
13
+ - Errore Traduzione di test - (95ff702) - Marino Bonetti
14
+ #### Documentation
15
+ - Add info on test matrix - (b097a01) - Marino Bonetti
16
+ #### Features
17
+ - Configurable test controller requests - (327163e) - Marino Bonetti
18
+ - In caso di molti attributi struttura multilinea - (21dfe09) - Marino Bonetti
19
+ - Add customizable title New and Edit - (d484e23) - Marino Bonetti
20
+ - Check model inheritance for partial search (#18) - (14f081f) - Marino Bonetti
21
+
22
+ - - -
23
+
5
24
  ## 1.8.1 - 2025-03-24
6
25
  #### Bug Fixes
7
26
  - Correct generator install multiple gems - (73948f5) - Marino Bonetti
data/README.md CHANGED
@@ -1,7 +1,9 @@
1
1
  # BaseEditingBootstrap
2
2
  [![Gem Version](https://badge.fury.io/rb/base_editing_bootstrap.svg)](https://badge.fury.io/rb/base_editing_bootstrap)
3
3
 
4
- WIP
4
+ ### Active tested on:
5
+ * rails: 7.x,8.x
6
+ * ruby: 3.x
5
7
 
6
8
  ## Installation
7
9
  Add this line to your application's Gemfile:
@@ -1,13 +1,22 @@
1
1
  module Utilities::PageHelper
2
2
  include Utilities::IconHelper
3
+
4
+ ##
5
+ # Traduzione del titolo EDIT con possibilità di modificare intestazione rispetto a modello
6
+ # - Il default è quello di Utilizzare la chiave .edit
7
+ # - Viene cercato la traduzione con la chiave titles.CHIAVE_I18N_MODELLO.edit
3
8
  # @param [BaseModel] base_class
4
9
  def title_mod_g(base_class)
5
- "#{t("edit")} #{base_class.model_name.human}"
10
+ "#{t("titles.#{base_class.model_name.i18n_key}.edit", default: :edit)} #{base_class.model_name.human}"
6
11
  end
7
12
 
13
+ ##
14
+ # Traduzione del titolo NUOVO con possibilità di modificare intestazione rispetto a modello
15
+ # - Il default è quello di Utilizzare la chiave .new
16
+ # - Viene cercato la traduzione con la chiave titles.CHIAVE_I18N_MODELLO.new
8
17
  # @param [BaseModel] base_class
9
18
  def title_new_g(base_class)
10
- "#{t("new")} #{base_class.model_name.human}"
19
+ "#{t("titles.#{base_class.model_name.i18n_key}.new", default: :new)} #{base_class.model_name.human}"
11
20
  end
12
21
 
13
22
  # Quando e se servirà verrà testato:
@@ -15,20 +15,34 @@ module Utilities::TemplateHelper
15
15
  def find_template_with_fallbacks(obj, field, base_path, generic_field)
16
16
  # nei casi in cui passiamo la classe e non l'oggetto, dobbiamo utilizzare un metodo interno a rails per
17
17
  # avere la partial_path
18
+
19
+ obj_base_paths = []
20
+ # Primo livello in cui troviamo la partial path rispetto ad istanza o classe
18
21
  partial_path = (obj.respond_to? :to_partial_path) ? obj.to_partial_path : obj._to_partial_path
19
- obj_base_path = "#{partial_path}/#{base_path}"
22
+ obj_base_paths << "#{partial_path}/#{base_path}"
23
+
24
+ # Cerchiamo anche tutti i livelli di inheritance del modello
25
+ start_class = ((obj.respond_to? :to_partial_path) ? obj.class : obj).superclass
26
+
27
+ while start_class < ApplicationRecord
28
+ partial_path = start_class._to_partial_path
29
+ obj_base_paths << "#{partial_path}/#{base_path}"
30
+ start_class = start_class.superclass
31
+ end
20
32
 
21
33
  [
22
34
  # Precedenza modello e campo specifico
23
- [field, [obj_base_path]],
35
+ ["Campo SPECIFICO + inheritance tra modelli", field, obj_base_paths],
24
36
  # cerco tramite nome modello semplice, con namespace della risorsa (cell_field,header_field,form_field) e nome del campo specifico
25
- ["#{obj.model_name.element}/#{base_path}/#{field}", lookup_context.prefixes],
37
+ ["Campo specifico con nome modello + inheritance controllers", "#{obj.model_name.element}/#{base_path}/#{field}", lookup_context.prefixes],
38
+ # cerco struttura senza il livello del nome del modello
39
+ ["Campo specifico senza nome modello + inheritance controllers", "#{base_path}/#{field}", lookup_context.prefixes],
26
40
  # Ricerca tramite campo generico e prefissi di contesto che contiene anche controller e namespace di controller
27
- ["#{base_path}/#{generic_field}", lookup_context.prefixes],
28
- [generic_field, [obj_base_path]],
29
- ["base_editing/#{base_path}/#{generic_field}", []],
30
- ].each do |partial, prefixes|
31
- Rails.logger.debug { "[BASE EDITING BOOTSTRAP] Cerco partial:`#{partial}` in #{prefixes.inspect}" }
41
+ ["Campo GENERICO + inheritance controllers", "#{base_path}/#{generic_field}", lookup_context.prefixes],
42
+ ["Campo GENERICO + inheritance tra modelli", generic_field, obj_base_paths],
43
+ ["Default BaseEditingController", "base_editing/#{base_path}/#{generic_field}", []],
44
+ ].each do |desc,partial, prefixes|
45
+ Rails.logger.debug { "[BASE EDITING BOOTSTRAP] #{desc} - partial:`#{partial}` in #{prefixes.inspect}" }
32
46
  if lookup_context.exists?(partial, prefixes, true)
33
47
  return lookup_context.find(partial, prefixes, true)
34
48
  end
@@ -78,8 +78,4 @@ it:
78
78
  i_cont: "contiene"
79
79
  base_editing:
80
80
  form_base_errors:
81
- title: Presenti errori generici
82
- post:
83
- base_editing:
84
- form_base_errors:
85
- title: Presenti errori per il modello POST
81
+ title: Presenti errori generici
@@ -1 +1 @@
1
- 1.8.1
1
+ 1.9.0
@@ -25,7 +25,7 @@ module BaseEditingBootstrap
25
25
  if auth_object
26
26
  Pundit.policy(auth_object, self.new).permitted_attributes_for_ransack.map(&:to_s)
27
27
  else
28
- Pundit.policy(User.new, self.new).permitted_attributes_for_ransack.map(&:to_s)
28
+ Pundit.policy(BaseEditingBootstrap.authentication_model.new, self.new).permitted_attributes_for_ransack.map(&:to_s)
29
29
  end
30
30
  end
31
31
 
@@ -33,7 +33,7 @@ module BaseEditingBootstrap
33
33
  if auth_object
34
34
  Pundit.policy(auth_object, self.new).permitted_associations_for_ransack.map(&:to_s)
35
35
  else
36
- Pundit.policy(User.new, self.new).permitted_associations_for_ransack.map(&:to_s)
36
+ Pundit.policy(BaseEditingBootstrap.authentication_model.new, self.new).permitted_associations_for_ransack.map(&:to_s)
37
37
  end
38
38
  end
39
39
 
@@ -41,7 +41,7 @@ module BaseEditingBootstrap
41
41
  if auth_object
42
42
  Pundit.policy(auth_object, self.new).permitted_scopes_for_ransack.map(&:to_s)
43
43
  else
44
- Pundit.policy(User.new, self.new).permitted_scopes_for_ransack.map(&:to_s)
44
+ Pundit.policy(BaseEditingBootstrap.authentication_model.new, self.new).permitted_scopes_for_ransack.map(&:to_s)
45
45
  end
46
46
  end
47
47
  end
@@ -26,7 +26,13 @@ module BaseEditingBootstrap::Forms
26
26
  #
27
27
  def form_style_class_for(method, options = {}, base_classes: ["form-control"])
28
28
  classes = base_classes
29
- classes << "is-invalid" if object.errors && object.errors.include?(method)
29
+ if object.errors
30
+ classes << "is-invalid" if object.errors.include?(method)
31
+ # caso in cui il metodo è una relazione
32
+ if method.to_s.match(/(.*)_id\z/)
33
+ classes << "is-invalid" if object.errors.include?(Regexp.last_match(1))
34
+ end
35
+ end
30
36
  classes << options[:class].split(" ") if options[:class]
31
37
  classes.flatten.compact.uniq.join(" ")
32
38
  end
@@ -47,7 +53,7 @@ module BaseEditingBootstrap::Forms
47
53
 
48
54
  def select(method, choices = nil, options = {}, html_options = {}, &block)
49
55
  html_options.merge!(class: form_style_class_for(method, html_options, base_classes: ["form-control", "form-select"]))
50
- super(method, choices, options,html_options , &block)
56
+ super(method, choices, options, html_options, &block)
51
57
  end
52
58
 
53
59
  def check_box(method, options = {}, checked_value = "1", unchecked_value = "0")
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/concern'
4
+
5
+ module BaseEditingBootstrap::GeneratorsHelpers
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+
10
+ private
11
+ def class_to_view_path(class_name)
12
+ base_path = ["app/views"]
13
+
14
+ base_path << class_name.deconstantize.then { |c| c.underscore.downcase }
15
+ singular_name = class_name.demodulize.underscore.downcase.singularize
16
+ base_path << singular_name.pluralize
17
+ base_path << singular_name
18
+ base_path.compact_blank!
19
+ end
20
+
21
+ end
22
+
23
+ end
24
+
@@ -36,8 +36,20 @@ module BaseEditingBootstrap
36
36
  # possibili valori :edit , :index
37
37
  config_accessor :after_success_create_redirect, default: :edit
38
38
 
39
+ ##
40
+ # Classe che rappresenta l'utente, solitamente User
41
+ config_accessor :authentication_model_class, default: "User"
42
+
43
+ def self.authentication_model
44
+ self.authentication_model_class.constantize
45
+ end
46
+
47
+ ##
48
+ # Factory per la creazione del modello che rappresenta l'auteticazione
49
+ config_accessor :authentication_model_factory, default: :user
50
+
39
51
  def self.deprecator
40
- @deprecator ||= ActiveSupport::Deprecation.new("1.0", "BaseEditingBootstrap")
52
+ @deprecator ||= ActiveSupport::Deprecation.new("2.0", "BaseEditingBootstrap")
41
53
  end
42
54
 
43
55
  end
@@ -3,6 +3,7 @@
3
3
  module BaseEditingBootstrap
4
4
  module Generators
5
5
  class CellOverrideGenerator < ::Rails::Generators::Base
6
+ include BaseEditingBootstrap::GeneratorsHelpers
6
7
  source_root File.expand_path("../../../../app/views/base_editing", __dir__)
7
8
  argument :name, type: :string, banner: "Post", required: true
8
9
  argument :attributes, type: :array, default: [], banner: "field field:type"
@@ -20,15 +21,15 @@ module BaseEditingBootstrap
20
21
  if attributes.empty?
21
22
  say "Need one field"
22
23
  else
23
- singular_name = name.underscore.downcase.singularize
24
- plural_name = singular_name.pluralize
24
+ base_path = class_to_view_path(name)
25
+
25
26
  attributes.each do |a|
26
27
  attr_name, type = a.split(":")
27
28
 
28
29
  type = :base if type.nil?
29
30
  type = type.to_sym
30
31
  raise "Type #{type} not found in #{TYPES}" unless TYPES.include?(type)
31
- copy_file "cell_field/_#{type}.html.erb", File.join("app/views", plural_name, singular_name, 'cell_field', "_#{attr_name}.html.erb")
32
+ copy_file "cell_field/_#{type}.html.erb", File.join(*base_path, 'cell_field', "_#{attr_name}.html.erb")
32
33
  end
33
34
  end
34
35
 
@@ -3,6 +3,7 @@
3
3
  module BaseEditingBootstrap
4
4
  module Generators
5
5
  class FieldOverrideGenerator < ::Rails::Generators::Base
6
+ include BaseEditingBootstrap::GeneratorsHelpers
6
7
  source_root File.expand_path("../../../../app/views/base_editing", __dir__)
7
8
  argument :name, type: :string, banner: "Post", required: true
8
9
  argument :attributes, type: :array, default: [], banner: "field field:type"
@@ -20,15 +21,16 @@ module BaseEditingBootstrap
20
21
  if attributes.empty?
21
22
  say "Need one field"
22
23
  else
23
- singular_name = name.underscore.downcase.singularize
24
- plural_name = singular_name.pluralize
24
+
25
+ base_path = class_to_view_path(name)
26
+
25
27
  attributes.each do |a|
26
28
  attr_name, type = a.split(":")
27
29
 
28
30
  type = :base if type.nil?
29
31
  type = type.to_sym
30
32
  raise "Type #{type} not found in #{TYPES}" unless TYPES.include?(type)
31
- copy_file "form_field/_#{type}.html.erb", File.join("app/views", plural_name, singular_name, 'form_field', "_#{attr_name}.html.erb")
33
+ copy_file "form_field/_#{type}.html.erb", File.join(*base_path,"form_field", "_#{attr_name}.html.erb")
32
34
  end
33
35
  end
34
36
 
@@ -3,6 +3,8 @@
3
3
  module BaseEditingBootstrap
4
4
  module Generators
5
5
  class HeaderOverrideGenerator < ::Rails::Generators::Base
6
+ include BaseEditingBootstrap::GeneratorsHelpers
7
+
6
8
  source_root File.expand_path("../../../../app/views/base_editing", __dir__)
7
9
  argument :name, type: :string, banner: "Post", required: true
8
10
  argument :attributes, type: :array, default: [], banner: "field field:type"
@@ -20,15 +22,15 @@ module BaseEditingBootstrap
20
22
  if attributes.empty?
21
23
  say "Need one field"
22
24
  else
23
- singular_name = name.underscore.downcase.singularize
24
- plural_name = singular_name.pluralize
25
+ base_path = class_to_view_path(name)
26
+
25
27
  attributes.each do |a|
26
28
  attr_name, type = a.split(":")
27
29
 
28
30
  type = :base if type.nil?
29
31
  type = type.to_sym
30
32
  raise "Type #{type} not found in #{TYPES}" unless TYPES.include?(type)
31
- copy_file "header_field/_#{type}.html.erb", File.join("app/views", plural_name, singular_name, 'header_field', "_#{attr_name}.html.erb")
33
+ copy_file "header_field/_#{type}.html.erb", File.join(*base_path, 'header_field', "_#{attr_name}.html.erb")
32
34
  end
33
35
  end
34
36
 
@@ -19,4 +19,12 @@ BaseEditingBootstrap.configure do |config|
19
19
  # possibili valori :edit , :index
20
20
  # config.after_success_create_redirect = :edit
21
21
 
22
+ ##
23
+ # Classe che rappresenta l'utente, solitamente User
24
+ # config.authentication_model_class= "User"
25
+
26
+ ##
27
+ # Factory per la creazione del modello che rappresenta l'auteticazione
28
+ # config.authentication_model_factory= :user
29
+
22
30
  end
@@ -1,17 +1,33 @@
1
1
  class <%= class_name %>Policy < BaseModelPolicy
2
2
 
3
- def editable_attributes = %i[<%= attributes_names.join(" ") %>]
4
- def permitted_attributes = %i[<%= attributes_names.join(" ") %>]
5
- def search_result_fields = %i[<%= attributes_names.join(" ") %>]
3
+ <%- if attributes_names.size > 3 -%>
4
+ <%- ["permitted_attributes","editable_attributes","search_result_fields"].each do |meth| -%>
5
+ def <%= meth %>
6
+ [
7
+ <%- attributes_names.each do |m| -%>
8
+ :<%= m %>,
9
+ <%- end -%>
10
+ ]
11
+ end
12
+
13
+ <%- end -%>
14
+ <%- else -%>
15
+ <%- ["permitted_attributes ","editable_attributes","search_result_fields"].each do |meth| -%>
16
+ def <%= meth %> = %i[<%= attributes_names.join(" ") %>]
17
+ <%- end -%>
18
+ <%- end -%>
6
19
  <%- if @search_attrs.any? -%>
20
+
7
21
  def search_fields
8
22
  %i[<%= @search_attrs.join(" ") %>]
9
23
  end
10
24
  <%- end -%>
11
25
  <%- if @permitted_attributes.any? -%>
26
+
12
27
  # TODO check if correct with search_fields
13
28
  def permitted_attributes_for_ransack
14
29
  %i[<%= @permitted_attributes.join(" ") %>]
15
30
  end
16
31
  <%- end -%>
32
+
17
33
  end
@@ -30,6 +30,8 @@ end
30
30
  # :url_for_create
31
31
  # :url_for_succ_delete
32
32
  # :url_for_fail_delete
33
+ # :url_for_succ_create
34
+ # :url_for_succ_update
33
35
  # :url_for_edit -> Rispetto agli altri questo risulta essere pià complicato in quanto
34
36
  # deve ritornare una proc a cui passiamo il valore dell'istanza persistente
35
37
  # che nei casi del after create non abbiamo a priori.
@@ -57,6 +59,27 @@ RSpec.shared_examples "base editing controller" do |factory: nil, only: [], exce
57
59
  let(:url_for_create) { url_for(model.new) }
58
60
  let(:url_for_succ_delete) { url_for(model) }
59
61
  let(:url_for_fail_delete) { url_for_succ_delete }
62
+
63
+ let(:url_for_succ_create) {
64
+ case BaseEditingBootstrap.after_success_create_redirect
65
+ when :index
66
+ url_for_index
67
+ else
68
+ # edit
69
+ url_for_edit.call(assigns[:object])
70
+ end
71
+ }
72
+
73
+ let(:url_for_succ_update) {
74
+ case BaseEditingBootstrap.after_success_update_redirect
75
+ when :index
76
+ url_for_index
77
+ else
78
+ # edit
79
+ url_for_edit.call(assigns[:object])
80
+ end
81
+ }
82
+
60
83
  let(:url_for_edit) { ->(p = persisted_instance) {
61
84
  url_for([p, action: :edit])
62
85
  } }
@@ -128,13 +151,7 @@ RSpec.shared_examples "base editing controller" do |factory: nil, only: [], exce
128
151
  put url_for_update, params: {param_key => valid_attributes}
129
152
  expect(assigns[:object]).to be_an_instance_of(model)
130
153
  expect(response).to have_http_status(303)
131
- case BaseEditingBootstrap.after_success_update_redirect
132
- when :index
133
- expect(response).to redirect_to(url_for_index)
134
- else
135
- # edit
136
- expect(response).to redirect_to(url_for_edit.call(assigns[:object]))
137
- end
154
+ expect(response).to redirect_to(url_for_succ_update)
138
155
  expect(flash.to_hash).to include("notice" => be_present)
139
156
  end
140
157
 
@@ -153,13 +170,7 @@ RSpec.shared_examples "base editing controller" do |factory: nil, only: [], exce
153
170
  post url_for_create, params: {param_key => valid_attributes}
154
171
  expect(assigns[:object]).to be_an_instance_of(model)
155
172
  expect(response).to have_http_status(303)
156
- case BaseEditingBootstrap.after_success_create_redirect
157
- when :index
158
- expect(response).to redirect_to(url_for_index)
159
- else
160
- # edit
161
- expect(response).to redirect_to(url_for_edit.call(assigns[:object]))
162
- end
173
+ expect(response).to redirect_to(url_for_succ_create)
163
174
  expect(flash.to_hash).to include("notice" => be_present)
164
175
  end
165
176
 
@@ -27,7 +27,7 @@ RSpec.shared_examples "a base model" do |ransack_permitted_attributes: [],
27
27
 
28
28
  ##
29
29
  # Oggetto solitamente di classe User che identifichi l'utente a cui eseguire il check dei permessi
30
- let(:auth_object) { :auth_object }
30
+ let(:auth_object) { BaseEditingBootstrap.authentication_model }
31
31
  let(:new_user_ransack_permitted_attributes) { ransack_permitted_attributes }
32
32
  let(:new_user_ransack_permitted_associations) { ransack_permitted_associations }
33
33
  let(:new_user_ransack_permitted_scopes) { ransack_permitted_scopes }
@@ -52,7 +52,7 @@ RSpec.shared_examples "a base model" do |ransack_permitted_attributes: [],
52
52
 
53
53
  let(:inner_auth_object) { nil }
54
54
  it "new user" do
55
- expect(Pundit).to receive(:policy).with(an_instance_of(User),
55
+ expect(Pundit).to receive(:policy).with(an_instance_of(BaseEditingBootstrap.authentication_model),
56
56
  an_instance_of(described_class)).and_call_original
57
57
 
58
58
  is_expected.to match_array(new_user_result)
@@ -13,6 +13,7 @@ module FactoryBot::Syntax::Methods
13
13
  klass = FactoryBot::Internal.factory_by_name(args.first).build_class
14
14
 
15
15
  klass.reflect_on_all_associations(:belongs_to).each do |r|
16
+ next if r.options.fetch(:optional, false)
16
17
  association = FactoryBot.create(r.class_name.underscore)
17
18
  attributes[:"#{r.name}_id"] = association.id
18
19
  attributes[:"#{r.name}_type"] = association.class.name if r.options[:polymorphic]
@@ -14,7 +14,7 @@ RSpec::Matchers.define :permit_editable_attributes do |*expected_attributes|
14
14
  end
15
15
 
16
16
  RSpec.shared_examples "a standard base model policy" do |factory, check_default_responses: false|
17
- let(:user) { create(:user) }
17
+ let(:user) { create(BaseEditingBootstrap.authentication_model_factory) }
18
18
  let(:instance) { described_class.new(user, build(factory)) }
19
19
 
20
20
  describe "response to all necessary methods" do
@@ -68,10 +68,10 @@ RSpec.shared_examples "a standard base model policy" do |factory, check_default_
68
68
  end
69
69
  end.flatten(1).compact.uniq
70
70
 
71
- elenco_campi_ordinabili_in_relazione.each do |relation,field|
71
+ elenco_campi_ordinabili_in_relazione.each do |relation, field|
72
72
  reflection = klass.reflect_on_association(relation.to_s)
73
73
  policy = Pundit.policy(instance.user, reflection.class_name.constantize.new)
74
- expect(policy.permitted_attributes_for_ransack.collect(&:to_sym).include?(field.to_sym)).to be_truthy, lambda{
74
+ expect(policy.permitted_attributes_for_ransack.collect(&:to_sym).include?(field.to_sym)).to be_truthy, lambda {
75
75
  "Mi aspetto che `#{policy.class.name}#permitted_attributes_for_ransack` includa `#{field}` per permettere l'ordinamento del campo tramite relazione"
76
76
  }
77
77
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: base_editing_bootstrap
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.1
4
+ version: 1.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marino Bonetti
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-03-24 00:00:00.000000000 Z
11
+ date: 2025-07-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -394,6 +394,7 @@ files:
394
394
  - lib/base_editing_bootstrap/base_model.rb
395
395
  - lib/base_editing_bootstrap/engine.rb
396
396
  - lib/base_editing_bootstrap/forms/base.rb
397
+ - lib/base_editing_bootstrap/generators_helpers.rb
397
398
  - lib/base_editing_bootstrap/is_validated.rb
398
399
  - lib/base_editing_bootstrap/resource_finder.rb
399
400
  - lib/base_editing_bootstrap/searches/base.rb