effective_resources 1.2.0 → 1.2.1

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
  SHA1:
3
- metadata.gz: b51f70289754b04e3b24e87cee9ee5b91348235b
4
- data.tar.gz: ce089db26990688cdf69c8e0beb2a5438f32eccd
3
+ metadata.gz: 435122fff68bc60412b461cd4eadf1b2a1c9543c
4
+ data.tar.gz: 4a5a64cc84f32cf948dfe3b69e799cfcd74b52bd
5
5
  SHA512:
6
- metadata.gz: 80bf7540fa6699c463c1ffdc37d2b58be79e22ae5ee1fbcb1aa9fa28ed4f67002e3927e5995f988970fa7e624eb14d236c69721eb01f59df66f602ecc8f9296e
7
- data.tar.gz: 386f9b28398d7d1b312c8bb5158678cdfea6c1850c3c20309c63402d7b7f0ccd49411278b44ef5f85cdf00e38623e06f3a4d31d7aa1d6ad74098763c544311a2
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} #{resource}")
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 "Failed to #{action}: #{e.message}"
44
- e.backtrace.first(4).each { |line| Rails.logger.info(line) }
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
- raise ActiveRecord::Rollback
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 Effective::Resource
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
- private
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
- EffectiveForm.remote_form_payload = "<%= j render_resource_form(@resource, action: action) %>";
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
@@ -1,3 +1,3 @@
1
1
  module EffectiveResources
2
- VERSION = '1.2.0'.freeze
2
+ VERSION = '1.2.1'.freeze
3
3
  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.0
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-24 00:00:00.000000000 Z
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