pg_rails 7.0.2 → 7.0.3
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 +4 -4
- data/pg_associable/app/helpers/pg_associable/helpers.rb +2 -2
- data/pg_associable/spec/pg_associable/helpers_spec.rb +24 -0
- data/pg_engine/app/controllers/pg_engine/base_controller.rb +0 -283
- data/pg_engine/app/controllers/pg_engine/require_sign_in.rb +9 -0
- data/pg_engine/app/controllers/pg_engine/resource_helper.rb +289 -0
- data/pg_engine/app/helpers/pg_engine/flash_helper.rb +3 -1
- data/pg_engine/app/helpers/pg_engine/route_helper.rb +2 -0
- data/pg_engine/app/views/pg_engine/base/index.html.slim +1 -1
- data/pg_engine/lib/pg_engine/engine.rb +5 -1
- data/pg_engine/lib/pg_engine/route_helpers.rb +12 -0
- data/pg_engine/lib/pg_engine/utils/pg_logger.rb +44 -0
- data/pg_engine/lib/pg_engine.rb +2 -12
- data/pg_layout/app/assets/stylesheets/sidebar.scss +4 -0
- data/pg_layout/app/views/layouts/pg_layout/devise.html.slim +2 -2
- data/pg_layout/app/views/layouts/pg_layout/layout.html.slim +2 -1
- data/pg_layout/app/views/pg_layout/_navbar.html.erb +0 -8
- data/pg_rails/lib/version.rb +1 -1
- data/pg_scaffold/lib/generators/pg_active_record/model/templates/admin.rb +1 -1
- data/pg_scaffold/lib/generators/pg_active_record/model/templates/model.rb +0 -1
- data/pg_scaffold/lib/generators/pg_rspec/scaffold/templates/controller_spec.rb +7 -0
- data/pg_scaffold/lib/generators/pg_scaffold/pg_scaffold_generator.rb +3 -9
- data/pg_scaffold/spec/generators_spec.rb +55 -0
- metadata +8 -4
- data/pg_engine/app/controllers/pg_engine/signed_in_controller.rb +0 -7
- data/pg_engine/lib/pg_engine/utils/logueador.rb +0 -46
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a8cb512a5e5483d9560982aebe0f68c8934f7c6fa63497a2e3701adf7b33ac7b
|
4
|
+
data.tar.gz: ce68d888d08bdbab4ed1e537d1f5d40b94d45c5a2f4d89f0ce99f65e3b9760ad
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3fb3e9557497c249a2960b61996a8e76e5075fab812753d6c09f7215b6155a928d6914a49b431c05a0869a3bc0cc78cfece7f895a4c6f47112a853834b77a122
|
7
|
+
data.tar.gz: 1aa9067316fa32c9aab7cec6aece106e5dbc5f7f89c257d27ccc003c7d497f11fb0af275ca6e3b254d545da261d160876b54486bf429350e29e7d78e1860a1e0
|
@@ -10,10 +10,10 @@ module PgAssociable
|
|
10
10
|
|
11
11
|
def pg_respond_buscar
|
12
12
|
partial = params[:partial] || 'pg_associable/resultados'
|
13
|
-
collection = @clase_modelo.query(params[:query]).limit(6)
|
13
|
+
@collection = policy_scope(@clase_modelo).query(params[:query]).limit(6)
|
14
14
|
render turbo_stream:
|
15
15
|
turbo_stream.update("resultados-#{params[:id]}",
|
16
|
-
partial:, locals: { collection: })
|
16
|
+
partial:, locals: { collection: @collection })
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
describe PgAssociable::Helpers do
|
4
|
+
describe '#pg_respond_buscar' do
|
5
|
+
let(:user) { create :user }
|
6
|
+
let(:ctrl) do
|
7
|
+
clazz = Class.new(PgEngine::BaseController)
|
8
|
+
clazz.new
|
9
|
+
end
|
10
|
+
let!(:cosa) { create :cosa }
|
11
|
+
|
12
|
+
before do
|
13
|
+
allow(ctrl).to receive_messages(current_user: user, params: { id: 123, query: cosa.id })
|
14
|
+
allow(ctrl).to receive(:render)
|
15
|
+
ctrl.instance_variable_set(:@clase_modelo, Cosa)
|
16
|
+
end
|
17
|
+
|
18
|
+
it do
|
19
|
+
ctrl.pg_respond_buscar
|
20
|
+
cosas = ctrl.instance_variable_get(:@collection)
|
21
|
+
expect(cosas).to eq [cosa]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -17,8 +17,6 @@ module PgEngine
|
|
17
17
|
rescue_from Pundit::NotAuthorizedError, with: :not_authorized
|
18
18
|
|
19
19
|
helper_method :mobile_device?
|
20
|
-
helper_method :atributos_para_listar
|
21
|
-
helper_method :atributos_para_mostrar
|
22
20
|
|
23
21
|
layout 'pg_layout/layout'
|
24
22
|
|
@@ -36,251 +34,12 @@ module PgEngine
|
|
36
34
|
@navbar = Navbar.new(current_user)
|
37
35
|
end
|
38
36
|
|
39
|
-
# Public endpoints
|
40
|
-
def abrir_modal
|
41
|
-
pg_respond_abrir_modal
|
42
|
-
end
|
43
|
-
|
44
|
-
def buscar
|
45
|
-
pg_respond_buscar
|
46
|
-
end
|
47
|
-
|
48
|
-
def index
|
49
|
-
@collection = filtros_y_policy atributos_para_buscar
|
50
|
-
@collection = sort_collection(@collection)
|
51
|
-
pg_respond_index
|
52
|
-
end
|
53
|
-
|
54
|
-
def show
|
55
|
-
add_breadcrumb instancia_modelo, instancia_modelo.target_object
|
56
|
-
|
57
|
-
pg_respond_show
|
58
|
-
end
|
59
|
-
|
60
|
-
def new
|
61
|
-
add_breadcrumb "Crear #{@clase_modelo.nombre_singular.downcase}"
|
62
|
-
end
|
63
|
-
|
64
|
-
def edit
|
65
|
-
add_breadcrumb instancia_modelo, instancia_modelo.target_object
|
66
|
-
add_breadcrumb 'Editando'
|
67
|
-
end
|
68
|
-
|
69
|
-
def create
|
70
|
-
pg_respond_create
|
71
|
-
end
|
72
|
-
|
73
|
-
def update
|
74
|
-
pg_respond_update
|
75
|
-
end
|
76
|
-
|
77
|
-
def destroy
|
78
|
-
url = namespaced_path(@clase_modelo)
|
79
|
-
pg_respond_destroy(instancia_modelo, url)
|
80
|
-
end
|
81
|
-
|
82
|
-
# End public endpoints
|
83
|
-
|
84
37
|
def mobile_device?
|
85
38
|
request.user_agent =~ /Mobile|webOS/
|
86
39
|
end
|
87
40
|
|
88
|
-
helper_method :any_filter?
|
89
|
-
|
90
|
-
def any_filter?
|
91
|
-
params.keys.reject { |a| a.in? %w[controller action page page_size order_by order_direction] }.any?
|
92
|
-
end
|
93
|
-
|
94
|
-
helper_method :current_page_size
|
95
|
-
|
96
|
-
def current_page_size
|
97
|
-
if params[:page_size].present?
|
98
|
-
session[:page_size] = params[:page_size]
|
99
|
-
params[:page_size].to_i
|
100
|
-
else
|
101
|
-
default_page_size
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
def default_page_size
|
106
|
-
session[:page_size].present? ? session[:page_size].to_i : 10
|
107
|
-
end
|
108
|
-
|
109
41
|
protected
|
110
42
|
|
111
|
-
def pg_respond_update(object: nil)
|
112
|
-
object ||= instancia_modelo
|
113
|
-
respond_to do |format|
|
114
|
-
if (@saved = object.save)
|
115
|
-
format.html { redirect_to object.decorate.target_object }
|
116
|
-
format.json { render json: object.decorate }
|
117
|
-
else
|
118
|
-
format.html { render :edit, status: :unprocessable_entity }
|
119
|
-
format.json { render json: object.errors, status: :unprocessable_entity }
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
def pg_respond_create(object: nil)
|
125
|
-
object ||= instancia_modelo
|
126
|
-
respond_to do |format|
|
127
|
-
if (@saved = object.save)
|
128
|
-
if params[:asociable]
|
129
|
-
format.turbo_stream do
|
130
|
-
render turbo_stream:
|
131
|
-
turbo_stream.update('pg-associable-form', <<~HTML
|
132
|
-
<div data-modal-target="response" data-response='#{object.decorate.to_json}'></div>
|
133
|
-
HTML
|
134
|
-
)
|
135
|
-
end
|
136
|
-
end
|
137
|
-
format.html do
|
138
|
-
if params[:save_and_next] == 'true'
|
139
|
-
new_path = "#{url_for(@clase_modelo)}/new"
|
140
|
-
redirect_to new_path, notice: "#{@clase_modelo.nombre_singular} creado."
|
141
|
-
else
|
142
|
-
redirect_to object.decorate.target_object
|
143
|
-
end
|
144
|
-
end
|
145
|
-
format.json { render json: object.decorate }
|
146
|
-
else
|
147
|
-
if params[:asociable]
|
148
|
-
format.turbo_stream do
|
149
|
-
render turbo_stream:
|
150
|
-
turbo_stream.update('pg-associable-form', partial: 'form', locals: { asociable: true })
|
151
|
-
end
|
152
|
-
end
|
153
|
-
format.html { render :new, status: :unprocessable_entity }
|
154
|
-
format.json { render json: object.errors.full_messages, status: :unprocessable_entity }
|
155
|
-
end
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
def pg_respond_index
|
160
|
-
respond_to do |format|
|
161
|
-
format.json { render json: @collection }
|
162
|
-
format.html { render_listing }
|
163
|
-
format.xlsx do
|
164
|
-
render xlsx: 'download',
|
165
|
-
filename: "#{@clase_modelo.nombre_plural.gsub(' ', '-').downcase}" \
|
166
|
-
"-#{Time.zone.now.strftime('%Y-%m-%d-%H.%M.%S')}.xlsx"
|
167
|
-
end
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
|
-
def pg_respond_show(object = nil)
|
172
|
-
respond_to do |format|
|
173
|
-
format.json { render json: object || instancia_modelo }
|
174
|
-
format.html
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
def pg_respond_destroy(model, redirect_url = nil)
|
179
|
-
if destroy_model(model)
|
180
|
-
respond_to do |format|
|
181
|
-
format.html do
|
182
|
-
if redirect_url.present?
|
183
|
-
redirect_to redirect_url, notice: 'Elemento borrado.', status: :see_other
|
184
|
-
else
|
185
|
-
redirect_back(fallback_location: root_path, notice: 'Elemento borrado.', status: 303)
|
186
|
-
end
|
187
|
-
end
|
188
|
-
format.json { head :no_content }
|
189
|
-
end
|
190
|
-
else
|
191
|
-
respond_to do |format|
|
192
|
-
format.html do
|
193
|
-
if model.respond_to?(:associated_elements) && model.associated_elements.present?
|
194
|
-
@model = model
|
195
|
-
render destroy_error_details_view
|
196
|
-
else
|
197
|
-
flash[:alert] = @error_message
|
198
|
-
# if redirect_url.present?
|
199
|
-
# redirect_to redirect_url
|
200
|
-
# else
|
201
|
-
redirect_back(fallback_location: root_path, status: 303)
|
202
|
-
# end
|
203
|
-
end
|
204
|
-
end
|
205
|
-
format.json { render json: { error: @error_message }, status: :unprocessable_entity }
|
206
|
-
end
|
207
|
-
end
|
208
|
-
end
|
209
|
-
|
210
|
-
# TODO: crear esta vista en pg_rails
|
211
|
-
def destroy_error_details_view
|
212
|
-
'destroy_error_details'
|
213
|
-
end
|
214
|
-
|
215
|
-
def destroy_model(model)
|
216
|
-
@error_message = 'No se pudo eliminar el registro'
|
217
|
-
begin
|
218
|
-
destroy_method = model.respond_to?(:discard) ? :discard : :destroy
|
219
|
-
return true if model.send(destroy_method)
|
220
|
-
|
221
|
-
@error_message = model.errors.full_messages.join(', ')
|
222
|
-
false
|
223
|
-
rescue ActiveRecord::InvalidForeignKey => e
|
224
|
-
# class_name = /from table \"(?<table_name>[\p{L}_]*)\"/.match(e.message)[:table_name].singularize.camelcase
|
225
|
-
# # pk_id = /from table \"(?<pk_id>[\p{L}_]*)\"/.match(e.message)[:pk_id].singularize.camelcase
|
226
|
-
# clazz = Object.const_get class_name
|
227
|
-
# objects = clazz.where(model.class.table_name.singularize => model)
|
228
|
-
model_name = t("activerecord.models.#{model.class.name.underscore}")
|
229
|
-
@error_message = "#{model_name} no se pudo borrar porque tiene elementos asociados."
|
230
|
-
logger.debug e.message
|
231
|
-
end
|
232
|
-
false
|
233
|
-
end
|
234
|
-
|
235
|
-
def render_listing
|
236
|
-
@collection = @collection.page(params[:page]).per(current_page_size)
|
237
|
-
end
|
238
|
-
|
239
|
-
def buscar_instancia
|
240
|
-
if Object.const_defined?('FriendlyId') && @clase_modelo.is_a?(FriendlyId)
|
241
|
-
@clase_modelo.friendly.find(params[:id])
|
242
|
-
else
|
243
|
-
@clase_modelo.find(params[:id])
|
244
|
-
end
|
245
|
-
end
|
246
|
-
|
247
|
-
def set_instancia_modelo
|
248
|
-
if action_name.in? %w[new create]
|
249
|
-
self.instancia_modelo = @clase_modelo.new(modelo_params)
|
250
|
-
else
|
251
|
-
self.instancia_modelo = buscar_instancia
|
252
|
-
|
253
|
-
instancia_modelo.assign_attributes(modelo_params) if action_name.in? %w[update]
|
254
|
-
end
|
255
|
-
|
256
|
-
instancia_modelo.current_user = send(PgEngine.configuracion.current_user_method)
|
257
|
-
|
258
|
-
authorize instancia_modelo
|
259
|
-
|
260
|
-
# TODO: problema en create y update cuando falla la validacion
|
261
|
-
self.instancia_modelo = instancia_modelo.decorate if action_name.in? %w[show edit new]
|
262
|
-
end
|
263
|
-
|
264
|
-
def instancia_modelo=(val)
|
265
|
-
instance_variable_set(:"@#{nombre_modelo}", val)
|
266
|
-
end
|
267
|
-
|
268
|
-
def instancia_modelo
|
269
|
-
instance_variable_get(:"@#{nombre_modelo}")
|
270
|
-
end
|
271
|
-
|
272
|
-
def modelo_params
|
273
|
-
if action_name == 'new'
|
274
|
-
params.permit(atributos_permitidos)
|
275
|
-
else
|
276
|
-
params.require(nombre_modelo).permit(atributos_permitidos)
|
277
|
-
end
|
278
|
-
end
|
279
|
-
|
280
|
-
def nombre_modelo
|
281
|
-
@clase_modelo.name.underscore
|
282
|
-
end
|
283
|
-
|
284
43
|
def default_url_options(options = {})
|
285
44
|
if Rails.env.production?
|
286
45
|
options.merge(protocol: 'https')
|
@@ -289,48 +48,6 @@ module PgEngine
|
|
289
48
|
end
|
290
49
|
end
|
291
50
|
|
292
|
-
def clase_modelo
|
293
|
-
# agarro la variable o intento con el nombre del controller
|
294
|
-
@clase_modelo ||= self.class.name.singularize.gsub('Controller', '').constantize
|
295
|
-
end
|
296
|
-
|
297
|
-
def filtros_y_policy(campos)
|
298
|
-
@filtros = PgEngine::FiltrosBuilder.new(
|
299
|
-
self, clase_modelo, campos
|
300
|
-
)
|
301
|
-
scope = policy_scope(clase_modelo)
|
302
|
-
|
303
|
-
@filtros.filtrar(scope)
|
304
|
-
end
|
305
|
-
|
306
|
-
def do_sort(scope, field, direction)
|
307
|
-
unless scope.model.column_names.include? field.to_s
|
308
|
-
Utils::Logueador.warning("No existe el campo \"#{field}\"")
|
309
|
-
return scope
|
310
|
-
end
|
311
|
-
scope = scope.order(field => direction)
|
312
|
-
instance_variable_set(:@field, field)
|
313
|
-
instance_variable_set(:@direction, direction)
|
314
|
-
scope
|
315
|
-
rescue ArgumentError => e
|
316
|
-
Utils::Logueador.warning(e.to_s)
|
317
|
-
scope
|
318
|
-
end
|
319
|
-
|
320
|
-
def sort_collection(scope, options = {})
|
321
|
-
if params[:order_by].present?
|
322
|
-
field = params[:order_by]
|
323
|
-
direction = params[:order_direction]
|
324
|
-
do_sort(scope, field, direction)
|
325
|
-
elsif options[:default].present?
|
326
|
-
field = options[:default].first[0]
|
327
|
-
direction = options[:default].first[1]
|
328
|
-
do_sort(scope, field, direction)
|
329
|
-
else
|
330
|
-
scope
|
331
|
-
end
|
332
|
-
end
|
333
|
-
|
334
51
|
def fecha_invalida
|
335
52
|
respond_to do |format|
|
336
53
|
format.json do
|
@@ -0,0 +1,289 @@
|
|
1
|
+
module PgEngine
|
2
|
+
module ResourceHelper
|
3
|
+
def self.included(clazz)
|
4
|
+
clazz.before_action :authenticate_user!
|
5
|
+
clazz.helper_method :atributos_para_listar
|
6
|
+
clazz.helper_method :atributos_para_mostrar
|
7
|
+
clazz.helper_method :current_page_size
|
8
|
+
clazz.helper_method :any_filter?
|
9
|
+
end
|
10
|
+
|
11
|
+
# Public endpoints
|
12
|
+
def abrir_modal
|
13
|
+
pg_respond_abrir_modal
|
14
|
+
end
|
15
|
+
|
16
|
+
def buscar
|
17
|
+
pg_respond_buscar
|
18
|
+
end
|
19
|
+
|
20
|
+
def index
|
21
|
+
@collection = filtros_y_policy atributos_para_buscar
|
22
|
+
@collection = sort_collection(@collection)
|
23
|
+
pg_respond_index
|
24
|
+
end
|
25
|
+
|
26
|
+
def show
|
27
|
+
add_breadcrumb instancia_modelo, instancia_modelo.target_object
|
28
|
+
|
29
|
+
pg_respond_show
|
30
|
+
end
|
31
|
+
|
32
|
+
def new
|
33
|
+
add_breadcrumb "Crear #{@clase_modelo.nombre_singular.downcase}"
|
34
|
+
end
|
35
|
+
|
36
|
+
def edit
|
37
|
+
add_breadcrumb instancia_modelo, instancia_modelo.target_object
|
38
|
+
add_breadcrumb 'Editando'
|
39
|
+
end
|
40
|
+
|
41
|
+
def create
|
42
|
+
pg_respond_create
|
43
|
+
end
|
44
|
+
|
45
|
+
def update
|
46
|
+
pg_respond_update
|
47
|
+
end
|
48
|
+
|
49
|
+
def destroy
|
50
|
+
url = namespaced_path(@clase_modelo)
|
51
|
+
pg_respond_destroy(instancia_modelo, url)
|
52
|
+
end
|
53
|
+
# End public endpoints
|
54
|
+
|
55
|
+
protected
|
56
|
+
|
57
|
+
def any_filter?
|
58
|
+
params.keys.reject { |a| a.in? %w[controller action page page_size order_by order_direction] }.any?
|
59
|
+
end
|
60
|
+
|
61
|
+
def current_page_size
|
62
|
+
if params[:page_size].present?
|
63
|
+
session[:page_size] = params[:page_size]
|
64
|
+
params[:page_size].to_i
|
65
|
+
else
|
66
|
+
default_page_size
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def default_page_size
|
71
|
+
session[:page_size].present? ? session[:page_size].to_i : 10
|
72
|
+
end
|
73
|
+
|
74
|
+
def pg_respond_update(object: nil)
|
75
|
+
object ||= instancia_modelo
|
76
|
+
respond_to do |format|
|
77
|
+
if (@saved = object.save)
|
78
|
+
format.html { redirect_to object.decorate.target_object }
|
79
|
+
format.json { render json: object.decorate }
|
80
|
+
else
|
81
|
+
format.html { render :edit, status: :unprocessable_entity }
|
82
|
+
format.json { render json: object.errors, status: :unprocessable_entity }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def pg_respond_create(object: nil)
|
88
|
+
object ||= instancia_modelo
|
89
|
+
respond_to do |format|
|
90
|
+
if (@saved = object.save)
|
91
|
+
if params[:asociable]
|
92
|
+
format.turbo_stream do
|
93
|
+
render turbo_stream:
|
94
|
+
turbo_stream.update('pg-associable-form', <<~HTML
|
95
|
+
<div data-modal-target="response" data-response='#{object.decorate.to_json}'></div>
|
96
|
+
HTML
|
97
|
+
)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
format.html do
|
101
|
+
if params[:save_and_next] == 'true'
|
102
|
+
new_path = "#{url_for(@clase_modelo)}/new"
|
103
|
+
redirect_to new_path, notice: "#{@clase_modelo.nombre_singular} creado."
|
104
|
+
else
|
105
|
+
redirect_to object.decorate.target_object
|
106
|
+
end
|
107
|
+
end
|
108
|
+
format.json { render json: object.decorate }
|
109
|
+
else
|
110
|
+
if params[:asociable]
|
111
|
+
format.turbo_stream do
|
112
|
+
render turbo_stream:
|
113
|
+
turbo_stream.update('pg-associable-form', partial: 'form', locals: { asociable: true })
|
114
|
+
end
|
115
|
+
end
|
116
|
+
format.html { render :new, status: :unprocessable_entity }
|
117
|
+
format.json { render json: object.errors.full_messages, status: :unprocessable_entity }
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def pg_respond_index
|
123
|
+
respond_to do |format|
|
124
|
+
format.json { render json: @collection }
|
125
|
+
format.html { render_listing }
|
126
|
+
format.xlsx do
|
127
|
+
render xlsx: 'download',
|
128
|
+
filename: "#{@clase_modelo.nombre_plural.gsub(' ', '-').downcase}" \
|
129
|
+
"-#{Time.zone.now.strftime('%Y-%m-%d-%H.%M.%S')}.xlsx"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def pg_respond_show(object = nil)
|
135
|
+
respond_to do |format|
|
136
|
+
format.json { render json: object || instancia_modelo }
|
137
|
+
format.html
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def pg_respond_destroy(model, redirect_url = nil)
|
142
|
+
if destroy_model(model)
|
143
|
+
respond_to do |format|
|
144
|
+
format.html do
|
145
|
+
if redirect_url.present?
|
146
|
+
redirect_to redirect_url, notice: 'Elemento borrado.', status: :see_other
|
147
|
+
else
|
148
|
+
redirect_back(fallback_location: root_path, notice: 'Elemento borrado.', status: 303)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
format.json { head :no_content }
|
152
|
+
end
|
153
|
+
else
|
154
|
+
respond_to do |format|
|
155
|
+
format.html do
|
156
|
+
if model.respond_to?(:associated_elements) && model.associated_elements.present?
|
157
|
+
@model = model
|
158
|
+
render destroy_error_details_view
|
159
|
+
else
|
160
|
+
flash[:alert] = @error_message
|
161
|
+
# if redirect_url.present?
|
162
|
+
# redirect_to redirect_url
|
163
|
+
# else
|
164
|
+
redirect_back(fallback_location: root_path, status: 303)
|
165
|
+
# end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
format.json { render json: { error: @error_message }, status: :unprocessable_entity }
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
# TODO: crear esta vista en pg_rails
|
174
|
+
def destroy_error_details_view
|
175
|
+
'destroy_error_details'
|
176
|
+
end
|
177
|
+
|
178
|
+
def destroy_model(model)
|
179
|
+
@error_message = 'No se pudo eliminar el registro'
|
180
|
+
begin
|
181
|
+
destroy_method = model.respond_to?(:discard) ? :discard : :destroy
|
182
|
+
return true if model.send(destroy_method)
|
183
|
+
|
184
|
+
@error_message = model.errors.full_messages.join(', ')
|
185
|
+
false
|
186
|
+
rescue ActiveRecord::InvalidForeignKey => e
|
187
|
+
# class_name = /from table \"(?<table_name>[\p{L}_]*)\"/.match(e.message)[:table_name].singularize.camelcase
|
188
|
+
# # pk_id = /from table \"(?<pk_id>[\p{L}_]*)\"/.match(e.message)[:pk_id].singularize.camelcase
|
189
|
+
# clazz = Object.const_get class_name
|
190
|
+
# objects = clazz.where(model.class.table_name.singularize => model)
|
191
|
+
model_name = t("activerecord.models.#{model.class.name.underscore}")
|
192
|
+
@error_message = "#{model_name} no se pudo borrar porque tiene elementos asociados."
|
193
|
+
logger.debug e.message
|
194
|
+
end
|
195
|
+
false
|
196
|
+
end
|
197
|
+
|
198
|
+
def render_listing
|
199
|
+
@collection = @collection.page(params[:page]).per(current_page_size)
|
200
|
+
end
|
201
|
+
|
202
|
+
def buscar_instancia
|
203
|
+
if Object.const_defined?('FriendlyId') && @clase_modelo.is_a?(FriendlyId)
|
204
|
+
@clase_modelo.friendly.find(params[:id])
|
205
|
+
else
|
206
|
+
@clase_modelo.find(params[:id])
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def set_instancia_modelo
|
211
|
+
if action_name.in? %w[new create]
|
212
|
+
self.instancia_modelo = @clase_modelo.new(modelo_params)
|
213
|
+
else
|
214
|
+
self.instancia_modelo = buscar_instancia
|
215
|
+
|
216
|
+
instancia_modelo.assign_attributes(modelo_params) if action_name.in? %w[update]
|
217
|
+
end
|
218
|
+
|
219
|
+
instancia_modelo.current_user = send(PgEngine.configuracion.current_user_method)
|
220
|
+
|
221
|
+
authorize instancia_modelo
|
222
|
+
|
223
|
+
# TODO: problema en create y update cuando falla la validacion
|
224
|
+
self.instancia_modelo = instancia_modelo.decorate if action_name.in? %w[show edit new]
|
225
|
+
end
|
226
|
+
|
227
|
+
def instancia_modelo=(val)
|
228
|
+
instance_variable_set(:"@#{nombre_modelo}", val)
|
229
|
+
end
|
230
|
+
|
231
|
+
def instancia_modelo
|
232
|
+
instance_variable_get(:"@#{nombre_modelo}")
|
233
|
+
end
|
234
|
+
|
235
|
+
def modelo_params
|
236
|
+
if action_name == 'new'
|
237
|
+
params.permit(atributos_permitidos)
|
238
|
+
else
|
239
|
+
params.require(nombre_modelo).permit(atributos_permitidos)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def nombre_modelo
|
244
|
+
@clase_modelo.name.underscore
|
245
|
+
end
|
246
|
+
|
247
|
+
def clase_modelo
|
248
|
+
# agarro la variable o intento con el nombre del controller
|
249
|
+
@clase_modelo ||= self.class.name.singularize.gsub('Controller', '').constantize
|
250
|
+
end
|
251
|
+
|
252
|
+
def filtros_y_policy(campos)
|
253
|
+
@filtros = PgEngine::FiltrosBuilder.new(
|
254
|
+
self, clase_modelo, campos
|
255
|
+
)
|
256
|
+
scope = policy_scope(clase_modelo)
|
257
|
+
|
258
|
+
@filtros.filtrar(scope)
|
259
|
+
end
|
260
|
+
|
261
|
+
def do_sort(scope, field, direction)
|
262
|
+
unless scope.model.column_names.include? field.to_s
|
263
|
+
PgLogger.warning("No existe el campo \"#{field}\"")
|
264
|
+
return scope
|
265
|
+
end
|
266
|
+
scope = scope.order(field => direction)
|
267
|
+
instance_variable_set(:@field, field)
|
268
|
+
instance_variable_set(:@direction, direction)
|
269
|
+
scope
|
270
|
+
rescue ArgumentError => e
|
271
|
+
PgLogger.warning(e.to_s)
|
272
|
+
scope
|
273
|
+
end
|
274
|
+
|
275
|
+
def sort_collection(scope, options = {})
|
276
|
+
if params[:order_by].present?
|
277
|
+
field = params[:order_by]
|
278
|
+
direction = params[:order_direction]
|
279
|
+
do_sort(scope, field, direction)
|
280
|
+
elsif options[:default].present?
|
281
|
+
field = options[:default].first[0]
|
282
|
+
direction = options[:default].first[1]
|
283
|
+
do_sort(scope, field, direction)
|
284
|
+
else
|
285
|
+
scope
|
286
|
+
end
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
@@ -5,7 +5,9 @@ module PgEngine
|
|
5
5
|
end
|
6
6
|
|
7
7
|
def render_turbo_stream_title
|
8
|
-
|
8
|
+
# rubocop:disable Rails/SkipsModelValidations
|
9
|
+
turbo_stream.update_all 'title', "#{breadcrumbs.last&.name} - #{Rails.application.class.module_parent_name}"
|
10
|
+
# rubocop:enable Rails/SkipsModelValidations
|
9
11
|
end
|
10
12
|
|
11
13
|
def flash_type_to_class(flash_type)
|
@@ -31,11 +31,15 @@ module PgEngine
|
|
31
31
|
end
|
32
32
|
|
33
33
|
initializer 'byebug_bullet' do
|
34
|
-
if Rails.env.
|
34
|
+
if Rails.env.local?
|
35
35
|
# Byebug
|
36
36
|
require 'byebug/core'
|
37
37
|
begin
|
38
38
|
Byebug.start_server 'localhost', ENV.fetch('BYEBUG_SERVER_PORT', 8989).to_i
|
39
|
+
if ENV.fetch('SLEEP_AFTER_BYEBUG', false)
|
40
|
+
puts 'waiting 3 secs after starting byebug server for connections'
|
41
|
+
sleep 3
|
42
|
+
end
|
39
43
|
rescue Errno::EADDRINUSE
|
40
44
|
Rails.logger.debug 'Byebug server already running'
|
41
45
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rainbow'
|
4
|
+
|
5
|
+
module PgEngine
|
6
|
+
class PgLogger
|
7
|
+
class << self
|
8
|
+
def deprecated(mensaje)
|
9
|
+
titulo = Rainbow(" WARNING en #{caller[1]}").yellow.bold
|
10
|
+
detalles = Rainbow(" #{mensaje}").yellow
|
11
|
+
Rails.logger.warn("#{titulo}\n#{detalles}")
|
12
|
+
Rollbar.warning("#{mensaje}\n\n#{caller.join("\n")}")
|
13
|
+
end
|
14
|
+
|
15
|
+
def excepcion(exception)
|
16
|
+
titulo = Rainbow(" EXCEPCION #{exception.class} en #{caller.first}").red.bold
|
17
|
+
detalles = Rainbow(" #{exception.message}").red
|
18
|
+
Rails.logger.error("#{titulo}\n#{detalles}")
|
19
|
+
Rollbar.error(exception)
|
20
|
+
end
|
21
|
+
|
22
|
+
def error(mensaje)
|
23
|
+
titulo = Rainbow(" ERROR en #{caller.first}").red.bold
|
24
|
+
detalles = Rainbow(" #{mensaje}").red
|
25
|
+
Rails.logger.error("#{titulo}\n#{detalles}")
|
26
|
+
Rollbar.error("#{mensaje}\n\n#{caller.join("\n")}")
|
27
|
+
end
|
28
|
+
|
29
|
+
def warning(mensaje)
|
30
|
+
titulo = Rainbow(" WARNING en #{caller.first}").yellow.bold
|
31
|
+
detalles = Rainbow(" #{mensaje}").yellow
|
32
|
+
Rails.logger.warn("#{titulo}\n#{detalles}")
|
33
|
+
Rollbar.warning("#{mensaje}\n\n#{caller.join("\n")}")
|
34
|
+
end
|
35
|
+
|
36
|
+
def info(mensaje)
|
37
|
+
titulo = Rainbow(" INFO en #{caller.first}").blue.bold
|
38
|
+
detalles = Rainbow(" #{mensaje}").blue
|
39
|
+
Rails.logger.info("#{titulo}\n#{detalles}")
|
40
|
+
Rollbar.info("#{mensaje}\n\n#{caller.join("\n")}")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/pg_engine/lib/pg_engine.rb
CHANGED
@@ -3,7 +3,8 @@
|
|
3
3
|
require_relative 'pg_engine/engine'
|
4
4
|
require_relative 'pg_engine/core_ext'
|
5
5
|
require_relative 'pg_engine/configuracion'
|
6
|
-
require_relative 'pg_engine/
|
6
|
+
require_relative 'pg_engine/route_helpers'
|
7
|
+
require_relative 'pg_engine/utils/pg_logger'
|
7
8
|
|
8
9
|
module PgEngine
|
9
10
|
class << self
|
@@ -20,16 +21,5 @@ module PgEngine
|
|
20
21
|
def configurar
|
21
22
|
yield(configuracion)
|
22
23
|
end
|
23
|
-
|
24
|
-
def resource_route(rails_router, key)
|
25
|
-
rails_router.instance_eval do
|
26
|
-
resources(key) do
|
27
|
-
collection do
|
28
|
-
get :abrir_modal
|
29
|
-
post :buscar
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
24
|
end
|
35
25
|
end
|
@@ -1,14 +1,13 @@
|
|
1
1
|
doctype html
|
2
2
|
html
|
3
3
|
head
|
4
|
-
title
|
4
|
+
title = Rails.application.class.module_parent_name
|
5
5
|
meta name="viewport" content="width=device-width,initial-scale=1"
|
6
6
|
= csrf_meta_tags
|
7
7
|
= csp_meta_tag
|
8
8
|
|
9
9
|
= stylesheet_link_tag 'application', 'data-turbo-track': 'reload'
|
10
10
|
= javascript_include_tag 'application', 'data-turbo-track': 'reload', type: 'module'
|
11
|
-
|
12
11
|
body
|
13
12
|
div
|
14
13
|
.text-center
|
@@ -17,6 +16,7 @@ html
|
|
17
16
|
.container.text-center
|
18
17
|
= yield
|
19
18
|
= render_turbo_stream_title
|
19
|
+
|
20
20
|
css:
|
21
21
|
.pg-form {
|
22
22
|
max-width: 300px;
|
@@ -1,7 +1,7 @@
|
|
1
1
|
doctype html
|
2
2
|
html
|
3
3
|
head
|
4
|
-
title
|
4
|
+
title = Rails.application.class.module_parent_name
|
5
5
|
meta name="viewport" content="width=device-width,initial-scale=1"
|
6
6
|
= csrf_meta_tags
|
7
7
|
= csp_meta_tag
|
@@ -28,3 +28,4 @@ html
|
|
28
28
|
= yield(:actions)
|
29
29
|
hr.my-0
|
30
30
|
= yield
|
31
|
+
= render_turbo_stream_title
|
data/pg_rails/lib/version.rb
CHANGED
@@ -32,7 +32,6 @@ class <%= class_name %> < <%= parent_class_name.classify %>
|
|
32
32
|
enumerize :<%= attribute.name %>, in: { completar: 0, los: 1, valores: 2 }
|
33
33
|
<%- end -%>
|
34
34
|
<%- end -%>
|
35
|
-
|
36
35
|
<%- if attributes.any?(&:required?) -%>
|
37
36
|
|
38
37
|
validates <%= attributes.select(&:required?).map { |at| ":#{at.name}" }.join(', ') %>, presence: true
|
@@ -60,6 +60,13 @@ RSpec.describe <%= controller_class_name %>Controller do
|
|
60
60
|
sign_in user if user.present?
|
61
61
|
end
|
62
62
|
|
63
|
+
describe 'routing' do
|
64
|
+
it 'routes GET index correctly' do
|
65
|
+
route = { get: '/<%= controller_file_path %>' }
|
66
|
+
expect(route).to route_to(controller: '<%= controller_file_path %>', action: 'index')
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
63
70
|
<% unless options[:singleton] -%>
|
64
71
|
describe 'GET #index' do
|
65
72
|
subject do
|
@@ -57,15 +57,9 @@ class PgScaffoldGenerator < Rails::Generators::NamedBase
|
|
57
57
|
|
58
58
|
def parent_controller
|
59
59
|
parts = controller_class_name.split('::')
|
60
|
-
if parts.length > 1
|
61
|
-
|
62
|
-
|
63
|
-
else
|
64
|
-
'PgEngine::SignedInController'
|
65
|
-
end
|
66
|
-
else
|
67
|
-
'PgEngine::SignedInController'
|
68
|
-
end
|
60
|
+
return "#{parts.first}Controller" if parts.length > 1 && (get_class "#{parts.first}Controller")
|
61
|
+
|
62
|
+
raise "#{parts.first}Controller not exists"
|
69
63
|
end
|
70
64
|
|
71
65
|
def atributos_a_filtrar
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
require 'generators/pg_rspec/scaffold/scaffold_generator'
|
4
|
+
require 'generators/pg_decorator/pg_decorator_generator'
|
5
|
+
require 'generators/pg_active_record/model/model_generator'
|
6
|
+
|
7
|
+
DESTINATION_PATH = File.expand_path('./../../tmp/generator_testing', __dir__)
|
8
|
+
|
9
|
+
describe 'Generators' do
|
10
|
+
describe 'PgDecoratorGenerator' do
|
11
|
+
destination DESTINATION_PATH
|
12
|
+
tests PgDecoratorGenerator
|
13
|
+
|
14
|
+
before { prepare_destination }
|
15
|
+
|
16
|
+
it do
|
17
|
+
run_generator(['Frontend/Modelo', 'bla:integer'])
|
18
|
+
|
19
|
+
my_assert_file 'app/decorators/modelo_decorator.rb' do |content|
|
20
|
+
assert_match(/delegate_all/, content)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'ScaffoldGenerator' do
|
26
|
+
destination DESTINATION_PATH
|
27
|
+
tests PgRspec::Generators::ScaffoldGenerator
|
28
|
+
|
29
|
+
before { prepare_destination }
|
30
|
+
|
31
|
+
it do
|
32
|
+
run_generator(['Frontend/Modelo', 'bla:integer'])
|
33
|
+
|
34
|
+
my_assert_file 'spec/controllers/frontend/modelos_controller_spec.rb' do |content|
|
35
|
+
assert_match(/routing/, content)
|
36
|
+
assert_match(/sign_in user/, content)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe PgActiveRecord::ModelGenerator do
|
42
|
+
destination DESTINATION_PATH
|
43
|
+
tests described_class
|
44
|
+
|
45
|
+
before { prepare_destination }
|
46
|
+
|
47
|
+
it do
|
48
|
+
run_generator(['Frontend/Modelo', 'bla:integer', 'cosa:references', '--activeadmin'])
|
49
|
+
|
50
|
+
my_assert_file 'app/admin/modelos.rb' do |content|
|
51
|
+
assert_match(/permit_params.*cosa_id/, content)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pg_rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 7.0.
|
4
|
+
version: 7.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Martín Rosso
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-02-
|
11
|
+
date: 2024-02-08 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Rails goodies.
|
14
14
|
email:
|
@@ -35,10 +35,12 @@ files:
|
|
35
35
|
- pg_associable/lib/pg_associable/engine.rb
|
36
36
|
- pg_associable/lib/pg_associable/simple_form_initializer.rb
|
37
37
|
- pg_associable/lib/tasks/pg_associable_tasks.rake
|
38
|
+
- pg_associable/spec/pg_associable/helpers_spec.rb
|
38
39
|
- pg_engine/app/assets/stylesheets/pg_rails_b5.scss
|
39
40
|
- pg_engine/app/controllers/pg_engine/base_controller.rb
|
40
41
|
- pg_engine/app/controllers/pg_engine/devise_controller.rb
|
41
|
-
- pg_engine/app/controllers/pg_engine/
|
42
|
+
- pg_engine/app/controllers/pg_engine/require_sign_in.rb
|
43
|
+
- pg_engine/app/controllers/pg_engine/resource_helper.rb
|
42
44
|
- pg_engine/app/decorators/pg_engine/base_decorator.rb
|
43
45
|
- pg_engine/app/helpers/pg_engine/flash_helper.rb
|
44
46
|
- pg_engine/app/helpers/pg_engine/form_helper.rb
|
@@ -60,7 +62,8 @@ files:
|
|
60
62
|
- pg_engine/lib/pg_engine/configuracion.rb
|
61
63
|
- pg_engine/lib/pg_engine/core_ext.rb
|
62
64
|
- pg_engine/lib/pg_engine/engine.rb
|
63
|
-
- pg_engine/lib/pg_engine/
|
65
|
+
- pg_engine/lib/pg_engine/route_helpers.rb
|
66
|
+
- pg_engine/lib/pg_engine/utils/pg_logger.rb
|
64
67
|
- pg_engine/lib/tasks/auto_anotar_modelos.rake
|
65
68
|
- pg_engine/lib/templates/activeadmin/audits.rb
|
66
69
|
- pg_engine/lib/templates/activeadmin/users.rb
|
@@ -145,6 +148,7 @@ files:
|
|
145
148
|
- pg_scaffold/lib/pg_scaffold/monkey_patches/mejoras_a_named_base.rb
|
146
149
|
- pg_scaffold/lib/pg_scaffold/monkey_patches/mejoras_de_atributos.rb
|
147
150
|
- pg_scaffold/lib/pg_scaffold/railtie.rb
|
151
|
+
- pg_scaffold/spec/generators_spec.rb
|
148
152
|
homepage: https://github.com/programandoarg/pg_rails
|
149
153
|
licenses:
|
150
154
|
- MIT
|
@@ -1,46 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'rainbow'
|
4
|
-
|
5
|
-
module PgEngine
|
6
|
-
module Utils
|
7
|
-
class Logueador
|
8
|
-
class << self
|
9
|
-
def deprecated(mensaje)
|
10
|
-
titulo = Rainbow(" WARNING en #{caller[1]}").yellow.bold
|
11
|
-
detalles = Rainbow(" #{mensaje}").yellow
|
12
|
-
Rails.logger.warn("#{titulo}\n#{detalles}")
|
13
|
-
Rollbar.warning("#{mensaje}\n\n#{caller.join("\n")}")
|
14
|
-
end
|
15
|
-
|
16
|
-
def excepcion(exception)
|
17
|
-
titulo = Rainbow(" EXCEPCION #{exception.class} en #{caller.first}").red.bold
|
18
|
-
detalles = Rainbow(" #{exception.message}").red
|
19
|
-
Rails.logger.error("#{titulo}\n#{detalles}")
|
20
|
-
Rollbar.error(exception)
|
21
|
-
end
|
22
|
-
|
23
|
-
def error(mensaje)
|
24
|
-
titulo = Rainbow(" ERROR en #{caller.first}").red.bold
|
25
|
-
detalles = Rainbow(" #{mensaje}").red
|
26
|
-
Rails.logger.error("#{titulo}\n#{detalles}")
|
27
|
-
Rollbar.error("#{mensaje}\n\n#{caller.join("\n")}")
|
28
|
-
end
|
29
|
-
|
30
|
-
def warning(mensaje)
|
31
|
-
titulo = Rainbow(" WARNING en #{caller.first}").yellow.bold
|
32
|
-
detalles = Rainbow(" #{mensaje}").yellow
|
33
|
-
Rails.logger.warn("#{titulo}\n#{detalles}")
|
34
|
-
Rollbar.warning("#{mensaje}\n\n#{caller.join("\n")}")
|
35
|
-
end
|
36
|
-
|
37
|
-
def info(mensaje)
|
38
|
-
titulo = Rainbow(" INFO en #{caller.first}").blue.bold
|
39
|
-
detalles = Rainbow(" #{mensaje}").blue
|
40
|
-
Rails.logger.info("#{titulo}\n#{detalles}")
|
41
|
-
Rollbar.info("#{mensaje}\n\n#{caller.join("\n")}")
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|