effective_resources 1.2.0 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/concerns/effective/crud_controller/permitted_params.rb +1 -1
- data/app/controllers/concerns/effective/crud_controller/save.rb +12 -4
- data/app/helpers/effective_resources_helper.rb +1 -2
- data/app/models/concerns/acts_as_archived.rb +9 -0
- data/app/models/concerns/acts_as_statused.rb +63 -0
- data/app/models/effective/action_failed.rb +15 -0
- data/app/models/effective/resources/instance.rb +7 -0
- data/app/models/effective/resources/sql.rb +3 -5
- data/app/views/application/member_action.js.erb +4 -1
- data/lib/effective_resources/engine.rb +15 -0
- data/lib/effective_resources/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 435122fff68bc60412b461cd4eadf1b2a1c9543c
|
4
|
+
data.tar.gz: 4a5a64cc84f32cf948dfe3b69e799cfcd74b52bd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6675a98f388897cf2b97cd93177f8fc15927b7d85eae40ed1be4b9ac5a45e4ea767c8232994609f469daaec3b84853e0a8dd153693a71a3d78fc9c8ebbdd2b9c
|
7
|
+
data.tar.gz: efc25566f103fd524994ccf0c7f1bd11578ff748311e75ea034e5ca49a15de60cfcbe0fb6080bb77f26615a368855831291076e12261bda73adb8251be788b5d
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Effective
|
2
2
|
module CrudController
|
3
3
|
module PermittedParams
|
4
|
-
BLACKLIST = [:created_at, :updated_at]
|
4
|
+
BLACKLIST = [:created_at, :updated_at, :logged_change_ids]
|
5
5
|
|
6
6
|
# This is only available to models that use the effective_resource do ... end attributes block
|
7
7
|
# It will be called last, and only for those resources
|
@@ -30,7 +30,7 @@ module Effective
|
|
30
30
|
run_callbacks(:resource_before_save)
|
31
31
|
|
32
32
|
if resource.public_send("#{save_action}!") == false
|
33
|
-
raise("failed to #{action}
|
33
|
+
raise Effective::ActionFailed.new("failed to #{action}")
|
34
34
|
end
|
35
35
|
|
36
36
|
yield if block_given?
|
@@ -40,8 +40,9 @@ module Effective
|
|
40
40
|
return true
|
41
41
|
rescue => e
|
42
42
|
if Rails.env.development?
|
43
|
-
Rails.logger.info "
|
44
|
-
|
43
|
+
Rails.logger.info " \e[31m\e[1mFAILED\e[0m\e[22m" # bold red
|
44
|
+
Rails.logger.info " Unable to #{action} #{resource} - #{e.class} #{e}"
|
45
|
+
e.backtrace.first(5).each { |line| Rails.logger.info(' ' + line) }
|
45
46
|
end
|
46
47
|
|
47
48
|
if resource.respond_to?(:restore_attributes) && resource.persisted?
|
@@ -49,7 +50,14 @@ module Effective
|
|
49
50
|
end
|
50
51
|
|
51
52
|
flash.now[:danger] = resource_flash(:danger, resource, action, e: e)
|
52
|
-
|
53
|
+
|
54
|
+
case e
|
55
|
+
when Effective::ActionFailed, ActiveRecord::RecordInvalid, RuntimeError
|
56
|
+
raise(ActiveRecord::Rollback) # This is a soft error, we want to display the flash message to user
|
57
|
+
else
|
58
|
+
raise(e) # This is a real error that should be sent to 500. Client should not see the message.
|
59
|
+
end
|
60
|
+
|
53
61
|
end
|
54
62
|
end
|
55
63
|
|
@@ -50,8 +50,7 @@ module EffectiveResourcesHelper
|
|
50
50
|
end
|
51
51
|
|
52
52
|
# Renders the effective/resource view partial for this resource
|
53
|
-
# resource is an
|
54
|
-
# instance is an ActiveRecord thing, an Array of ActiveRecord things, or nil
|
53
|
+
# resource is an ActiveRecord thing, an Array of ActiveRecord things, or nil
|
55
54
|
# Atts are everything else. Interesting ones include:
|
56
55
|
|
57
56
|
# partial: :dropleft|:glyphicons|string
|
@@ -42,6 +42,15 @@ module ActsAsArchived
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
+
module CanCan
|
46
|
+
def acts_as_archived(klass)
|
47
|
+
raise "klass does not implement acts_as_archived" unless klass.acts_as_archived?
|
48
|
+
|
49
|
+
can(:archive, klass) { |obj| !obj.archived? }
|
50
|
+
can(:unarchive, klass) { |obj| obj.archived? }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
45
54
|
module RoutesConcern
|
46
55
|
def acts_as_archived
|
47
56
|
concern :acts_as_archived do
|
@@ -24,6 +24,67 @@ module ActsAsStatused
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
+
module CanCan
|
28
|
+
# The idea here is you can go forward but you can't go back.
|
29
|
+
def acts_as_statused(klass, only: nil, except: nil)
|
30
|
+
raise "klass does not implement acts_as_statused" unless klass.acts_as_statused?
|
31
|
+
|
32
|
+
statuses = klass.const_get(:STATUSES)
|
33
|
+
instance = klass.new
|
34
|
+
|
35
|
+
only = Array(only).compact
|
36
|
+
except = Array(except).compact
|
37
|
+
|
38
|
+
statuses.each_with_index do |status, index|
|
39
|
+
action = status_active_verb(status, instance)
|
40
|
+
|
41
|
+
next if action.blank?
|
42
|
+
next if only.present? && !only.include?(action)
|
43
|
+
next if except.present? && except.include?(action)
|
44
|
+
|
45
|
+
if index == 0
|
46
|
+
can(action, klass) and next
|
47
|
+
end
|
48
|
+
|
49
|
+
if status == :approved && statuses.include?(:declined)
|
50
|
+
if (position = statuses.index { |status| (status == :approved || status == :declined) }) > 0
|
51
|
+
can(action, klass) { |obj| obj.public_send("#{statuses[position-1]}?") || obj.declined? }
|
52
|
+
next
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
if status == :declined && statuses.include?(:approved)
|
57
|
+
if (position = statuses.index { |status| (status == :approved || status == :declined) }) > 0
|
58
|
+
can(action, klass) { |obj| obj.public_send("#{statuses[position-1]}?") }
|
59
|
+
next
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
can(action, klass) { |obj| obj.public_send("#{statuses[index-1]}?") }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
# requested -> request, approved -> approve, declined -> decline, pending -> pending
|
70
|
+
def status_active_verb(status, instance)
|
71
|
+
status = status.to_s.strip
|
72
|
+
|
73
|
+
if status.end_with?('ied')
|
74
|
+
action = status[0...-3] + 'y'
|
75
|
+
return action.to_sym if instance.respond_to?(action + '!')
|
76
|
+
end
|
77
|
+
|
78
|
+
# ed, e, ing
|
79
|
+
[-1, -2, -3].each do |index|
|
80
|
+
action = status[0...index]
|
81
|
+
return action.to_sym if instance.respond_to?(action + '!')
|
82
|
+
end
|
83
|
+
|
84
|
+
nil
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
27
88
|
included do
|
28
89
|
acts_as_statused_options = @acts_as_statused_options
|
29
90
|
|
@@ -77,6 +138,8 @@ module ActsAsStatused
|
|
77
138
|
|
78
139
|
status_steps.delete("#{sym}_at".to_sym)
|
79
140
|
status_steps.delete("#{sym}_by".to_sym)
|
141
|
+
|
142
|
+
true
|
80
143
|
end
|
81
144
|
|
82
145
|
scope(sym, -> { where(status: sym.to_s) })
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Effective
|
2
|
+
class ActionFailed < StandardError
|
3
|
+
attr_reader :action, :subject
|
4
|
+
|
5
|
+
def initialize(message = nil, action = nil, subject = nil)
|
6
|
+
@message = message
|
7
|
+
@action = action
|
8
|
+
@subject = subject
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_s
|
12
|
+
@message || I18n.t(:'unauthorized.default', :default => 'Action Failed')
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -4,6 +4,7 @@ module Effective
|
|
4
4
|
attr_accessor :instance
|
5
5
|
|
6
6
|
# This is written for use by effective_logging and effective_trash
|
7
|
+
BLACKLIST = [:logged_changes, :trash]
|
7
8
|
|
8
9
|
def instance
|
9
10
|
@instance || klass.new
|
@@ -18,12 +19,15 @@ module Effective
|
|
18
19
|
# Collect to_s representations of all belongs_to associations
|
19
20
|
if include_associated
|
20
21
|
belong_tos.each do |association|
|
22
|
+
next if BLACKLIST.include?(association.name)
|
21
23
|
attributes[association.name] = instance.send(association.name).to_s
|
22
24
|
end
|
23
25
|
end
|
24
26
|
|
25
27
|
if include_associated || include_nested
|
26
28
|
nested_resources.each do |association|
|
29
|
+
next if BLACKLIST.include?(association.name)
|
30
|
+
|
27
31
|
attributes[association.name] ||= {}
|
28
32
|
|
29
33
|
next if association.options[:through]
|
@@ -39,14 +43,17 @@ module Effective
|
|
39
43
|
|
40
44
|
if include_associated
|
41
45
|
has_ones.each do |association|
|
46
|
+
next if BLACKLIST.include?(association.name)
|
42
47
|
attributes[association.name] = instance.send(association.name).to_s
|
43
48
|
end
|
44
49
|
|
45
50
|
has_manys.each do |association|
|
51
|
+
next if BLACKLIST.include?(association.name)
|
46
52
|
attributes[association.name] = instance.send(association.name).map { |obj| obj.to_s }
|
47
53
|
end
|
48
54
|
|
49
55
|
has_and_belongs_to_manys.each do |association|
|
56
|
+
next if BLACKLIST.include?(association.name)
|
50
57
|
attributes[association.name] = instance.send(association.name).map { |obj| obj.to_s }
|
51
58
|
end
|
52
59
|
end
|
@@ -96,7 +96,9 @@ module Effective
|
|
96
96
|
@_search_columns = names
|
97
97
|
end
|
98
98
|
|
99
|
-
|
99
|
+
def ilike
|
100
|
+
@ilike ||= (postgres? ? 'ILIKE' : 'LIKE') # Only Postgres supports ILIKE, Mysql and Sqlite3 use LIKE
|
101
|
+
end
|
100
102
|
|
101
103
|
def postgres?
|
102
104
|
return @postgres unless @postgres.nil?
|
@@ -108,10 +110,6 @@ module Effective
|
|
108
110
|
@mysql ||= (klass.connection.kind_of?(ActiveRecord::ConnectionAdapters::Mysql2Adapter) rescue false)
|
109
111
|
end
|
110
112
|
|
111
|
-
def ilike
|
112
|
-
@ilike ||= (postgres? ? 'ILIKE' : 'LIKE') # Only Postgres supports ILIKE, Mysql and Sqlite3 use LIKE
|
113
|
-
end
|
114
|
-
|
115
113
|
def is_null(sql_column)
|
116
114
|
mysql? == true ? "ISNULL(#{sql_column})" : "#{sql_column} IS NULL"
|
117
115
|
end
|
@@ -1,7 +1,10 @@
|
|
1
1
|
<% resource = (@_effective_resource || Effective::Resource.new(controller_path)) %>
|
2
2
|
<% @resource = instance_variable_get('@' + resource.name) if resource.name %>
|
3
3
|
|
4
|
-
|
4
|
+
<% unless params[:_datatable_action] %>
|
5
|
+
EffectiveForm.remote_form_payload = "<%= j render_resource_form(@resource, action: action) %>";
|
6
|
+
<% end %>
|
7
|
+
|
5
8
|
EffectiveForm.remote_form_flash = <%= raw flash.to_json %>;
|
6
9
|
|
7
10
|
<% if @resource.respond_to?(:refresh_datatables) && @resource.refresh_datatables.present? %>
|
@@ -33,5 +33,20 @@ module EffectiveResources
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
+
initializer 'effective_resources.cancancan' do |app|
|
37
|
+
if defined?(CanCan::Ability)
|
38
|
+
CanCan::Ability.module_eval do
|
39
|
+
CRUD_ACTIONS = [:index, :new, :create, :edit, :update, :show, :destroy]
|
40
|
+
|
41
|
+
def crud
|
42
|
+
CRUD_ACTIONS
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
CanCan::Ability.include(ActsAsArchived::CanCan)
|
47
|
+
CanCan::Ability.include(ActsAsStatused::CanCan)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
36
51
|
end
|
37
52
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: effective_resources
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Code and Effect
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-01-
|
11
|
+
date: 2019-01-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -52,6 +52,7 @@ files:
|
|
52
52
|
- app/models/concerns/acts_as_tokened.rb
|
53
53
|
- app/models/concerns/effective_resource.rb
|
54
54
|
- app/models/effective/access_denied.rb
|
55
|
+
- app/models/effective/action_failed.rb
|
55
56
|
- app/models/effective/attribute.rb
|
56
57
|
- app/models/effective/code_reader.rb
|
57
58
|
- app/models/effective/model_reader.rb
|