effective_resources 0.5.1 → 0.6.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
  SHA1:
3
- metadata.gz: 47f2e4bf5eab9a622f1ab0e66ab3878cf52de399
4
- data.tar.gz: 6f2d1de27bafd3c352aa84f226025c641ab2a75d
3
+ metadata.gz: 835582267c27e57dd956b47f7f4ee16611761471
4
+ data.tar.gz: 6502e8942e9c05ed2f8fa9b4b253540ee6961255
5
5
  SHA512:
6
- metadata.gz: d3783949d96cb00d070b53cedd220129fd2b0609437410d973c6d21802cb9479e5bf4d5e8bc46cfe046e5cdcab28bdec3a9468488a193f8769930340998502f2
7
- data.tar.gz: 46fbb4de8b02aba9553b1c7d5f051cd55d519d54a85d41ab67352a636723fc0cdaaf6f80ad9a768edd240d9090f94d03e732a2907eacfd499f338ba61f4f8454
6
+ metadata.gz: be0a71e0ee416a1c91c8b42e0b9a5194cf469ecde22d73155ba42ff9fb978f63f54ff0ca9c981b87650e2bafe921137963e351b639256fc11b2e48902dcc58e7
7
+ data.tar.gz: c6f43d75ad754c5403ceed17ccf91b07234d7fe82c87a34e8f7c2c8d2ea22b36169d202b49669ee69229eae73e1ab35d30017c43ddfa9ca81086c142190d6e37
@@ -3,12 +3,47 @@ module Effective
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  included do
6
+ class << self
7
+ def member_actions
8
+ @_effective_member_actions ||= {
9
+ 'Save' => { action: :save, data: { disable_with: 'Saving...' }}
10
+ }
11
+ end
12
+ end
6
13
  end
7
14
 
8
15
  module ClassMethods
9
16
  # Add the following to your controller for a simple member action
10
17
  # member_action :print
11
- def member_action(action)
18
+ #
19
+ # Add to your permissions: can :print, Thing
20
+ #
21
+ # If you want to POST and do an action based on this:
22
+ # Make sure your model responds to approve!
23
+ # member_action :approve
24
+ # If you want it to automatically show up in your forms
25
+ # member_action :approve, 'Save and Approve', if: -> { approved? }
26
+ # member_action :approve, 'Save and Approve', unless: -> { !approved? }, redirect: :show
27
+
28
+ def member_action(action, commit = nil, args = {})
29
+ if commit.present?
30
+ raise 'expected args to be a Hash or false' unless args.kind_of?(Hash) || args == false
31
+
32
+ if args == false
33
+ member_actions.delete(commit); return
34
+ end
35
+
36
+ if args.key?(:if) && args[:if].respond_to?(:call) == false
37
+ raise "expected if: to be callable. Try member_action :approve, 'Save and Approve', if: -> { submitted? }"
38
+ end
39
+
40
+ if args.key?(:unless) && args[:unless].respond_to?(:call) == false
41
+ raise "expected unless: to be callable. Try member_action :approve, 'Save and Approve', unless: -> { declined? }"
42
+ end
43
+
44
+ member_actions[commit] = (args || {}).merge(action: action)
45
+ end
46
+
12
47
  define_method(action) do
13
48
  self.resource ||= resource_scope.find(params[:id])
14
49
 
@@ -93,18 +128,19 @@ module Effective
93
128
  end
94
129
 
95
130
  def create
96
- self.resource ||= resource_scope.new(send(resource_params_method_name))
131
+ self.resource ||= resource_scope.new
97
132
 
98
133
  @page_title ||= "New #{resource_name.titleize}"
99
134
  EffectiveResources.authorized?(self, :create, resource)
100
135
 
101
- resource.created_by ||= current_user if resource.respond_to?(:created_by=)
136
+ action = resource_commit_action[:action]
137
+ EffectiveResources.authorized?(self, action, resource) unless action == :save
102
138
 
103
- if resource.save
104
- flash[:success] = flash_success(resource)
139
+ if save_resource(resource, action)
140
+ flash[:success] ||= flash_success(resource, action)
105
141
  redirect_to(resource_redirect_path)
106
142
  else
107
- flash.now[:danger] = flash_danger(resource)
143
+ flash.now[:danger] ||= flash_danger(resource, action)
108
144
  render :new
109
145
  end
110
146
  end
@@ -129,11 +165,14 @@ module Effective
129
165
  @page_title = "Edit #{resource}"
130
166
  EffectiveResources.authorized?(self, :update, resource)
131
167
 
132
- if resource.update_attributes(send(resource_params_method_name))
133
- flash[:success] = flash_success(resource)
168
+ action = resource_commit_action[:action]
169
+ EffectiveResources.authorized?(self, action, resource) unless action == :save
170
+
171
+ if save_resource(resource, action)
172
+ flash[:success] ||= flash_success(resource, action)
134
173
  redirect_to(resource_redirect_path)
135
174
  else
136
- flash.now[:danger] = flash_danger(resource)
175
+ flash.now[:danger] ||= flash_danger(resource, action)
137
176
  render :edit
138
177
  end
139
178
  end
@@ -145,13 +184,13 @@ module Effective
145
184
  EffectiveResources.authorized?(self, :destroy, resource)
146
185
 
147
186
  if resource.destroy
148
- flash[:success] = flash_success(resource, :delete)
187
+ flash[:success] ||= flash_success(resource, :delete)
149
188
  else
150
- flash[:danger] = flash_danger(resource, :delete)
189
+ flash[:danger] ||= flash_danger(resource, :delete)
151
190
  end
152
191
 
153
- if request.referer.present? && !request.referer.include?(effective_resource.show_path)
154
- redirect_to(request.referer)
192
+ if referer_redirect_path && !request.referer.include?(resource_show_path)
193
+ redirect_to(referer_redirect_path)
155
194
  else
156
195
  redirect_to(resource_index_path)
157
196
  end
@@ -159,36 +198,26 @@ module Effective
159
198
 
160
199
  def member_post_action(action)
161
200
  raise 'expected post, patch or put http action' unless (request.post? || request.patch? || request.put?)
162
- raise "expected @#{resource_name} to respond to #{action}!" unless resource.respond_to?("#{action}!")
163
201
 
164
- begin
165
- resource.public_send("#{action}!") || raise("failed to #{action} #{resource}")
166
-
167
- flash[:success] = flash_success(resource, action)
168
- redirect_back(fallback_location: resource_redirect_path)
169
- rescue => e
170
- flash.now[:danger] = flash_danger(resource, action, e: e)
171
-
172
- referer = request.referer.to_s
202
+ if save_resource(resource, action)
203
+ flash[:success] ||= flash_success(resource, action)
204
+ redirect_to(referer_redirect_path || resource_redirect_path)
205
+ else
206
+ flash.now[:danger] ||= flash_danger(resource, action)
173
207
 
174
- if resource_edit_path && referer.end_with?(resource_edit_path)
208
+ if resource_edit_path && (referer_redirect_path || '').end_with?(resource_edit_path)
175
209
  @page_title ||= "Edit #{resource}"
176
210
  render :edit
177
- elsif resource_new_path && referer.end_with?(resource_new_path)
211
+ elsif resource_new_path && (referer_redirect_path || '').end_with?(resource_new_path)
178
212
  @page_title ||= "New #{resource_name.titleize}"
179
213
  render :new
180
- elsif resource_show_path && referer.end_with?(resource_show_path)
214
+ elsif resource_show_path && (referer_redirect_path || '').end_with?(resource_show_path)
181
215
  @page_title ||= resource_name.titleize
182
216
  render :show
183
217
  else
184
218
  @page_title ||= resource.to_s
185
219
  flash[:danger] = flash.now[:danger]
186
-
187
- if referer.present? && (Rails.application.routes.recognize_path(URI(referer).path) rescue false)
188
- redirect_back(fallback_location: resource_redirect_path)
189
- else
190
- redirect_to(resource_redirect_path)
191
- end
220
+ redirect_to(referer_redirect_path || resource_redirect_path)
192
221
  end
193
222
  end
194
223
  end
@@ -214,9 +243,57 @@ module Effective
214
243
  render json: { status: 200, message: "Successfully #{action_verb(action)} #{successes} / #{resources.length} selected #{resource_plural_name}" }
215
244
  end
216
245
 
246
+ # Here we look at all available (class level) member actions, see which ones apply to the current resource
247
+ # This feeds into the helper simple_form_submit(f)
248
+ # Returns a Hash of {'Save': {data-disable-with: 'Saving...'}, 'Save and Continue': {data-disable-with: 'Saving...'}}
249
+ def member_actions_for(obj)
250
+ self.class.member_actions.select do |commit, args|
251
+ (args.key?(:if) ? obj.instance_exec(&args[:if]) : true) &&
252
+ (args.key?(:unless) ? !obj.instance_exec(&args[:unless]) : true)
253
+ end.inject({}) { |h, (commit, args)| h[commit] = args.except(:action, :if, :unless, :redirect); h }
254
+ end
255
+
256
+ # This calls the appropriate member action, probably save!, on the resource.
257
+ def save_resource(resource, action = :save)
258
+ raise "expected @#{resource_name} to respond to #{action}!" unless resource.respond_to?("#{action}!")
259
+
260
+ resource.assign_attributes(send(resource_params_method_name))
261
+
262
+ resource.created_by ||= current_user if resource.respond_to?(:created_by=)
263
+ resource.current_user ||= current_user if resource.respond_to?(:current_user=)
264
+
265
+ resource_klass.transaction do
266
+ begin
267
+ resource.public_send("#{action}!") || raise("failed to #{action} #{resource}")
268
+ return true
269
+ rescue => e
270
+ flash.delete(:success)
271
+ flash.now[:danger] = flash_danger(resource, action, e: e)
272
+ raise ActiveRecord::Rollback
273
+ end
274
+ end
275
+
276
+ false
277
+ end
278
+
217
279
  protected
218
280
 
281
+ def resource_commit_action
282
+ self.class.member_actions[params[:commit].to_s] || self.class.member_actions['Save'] || raise("expected member_actions['Save'] to be present")
283
+ end
284
+
219
285
  def resource_redirect_path
286
+ commit_action_redirect = case resource_commit_action[:redirect]
287
+ when :index ; resource_index_path
288
+ when :edit ; resource_edit_path
289
+ when :show ; resource_show_path
290
+ when :back ; referer_redirect_path
291
+ when nil ; nil
292
+ else ; resource_member_action_path(resource_commit_action[:action])
293
+ end
294
+
295
+ return commit_action_redirect if commit_action_redirect.present?
296
+
220
297
  case params[:commit].to_s
221
298
  when 'Save'
222
299
  [resource_edit_path, resource_show_path, resource_index_path].compact.first
@@ -224,10 +301,14 @@ module Effective
224
301
  [resource_new_path, resource_index_path].compact.first
225
302
  when 'Save and Continue'
226
303
  resource_index_path
227
- when 'Save and Return'
228
- request.referer.present? ? request.referer : resource_index_path
229
304
  else
230
- [resource_edit_path, resource_show_path, resource_index_path].compact.first
305
+ [referer_redirect_path, resource_index_path].compact.first
306
+ end
307
+ end
308
+
309
+ def referer_redirect_path
310
+ if request.referer.present? && (Rails.application.routes.recognize_path(URI(request.referer.to_s).path) rescue false)
311
+ request.referer.to_s
231
312
  end
232
313
  end
233
314
 
@@ -251,6 +332,10 @@ module Effective
251
332
  send(effective_resource.destroy_path, resource) if effective_resource.destroy_path(check: true)
252
333
  end
253
334
 
335
+ def resource_member_action_path(action)
336
+ send(effective_resource.action_path(action), resource) if effective_resource.action_path(action, check: true)
337
+ end
338
+
254
339
  def resource # @thing
255
340
  instance_variable_get("@#{resource_name}")
256
341
  end
@@ -9,7 +9,7 @@ module Effective
9
9
  action ||= :save
10
10
  name ||= resource.class.model_name.human
11
11
 
12
- "#{name.to_s.titleize} was successfully #{action}#{(action.to_s.end_with?('e') ? 'd' : 'ed')}"
12
+ "#{name.to_s.titleize} was successfully #{action}#{(action.to_s == 'submit' ? 't' : '')}#{(action.to_s.end_with?('e') ? 'd' : 'ed')}"
13
13
  end
14
14
 
15
15
  # flash.now[:danger] = flash_danger(@post)
@@ -3,13 +3,18 @@ module EffectiveResourcesHelper
3
3
  def simple_form_submit(form, options = {class: 'form-actions'}, &block)
4
4
  resource = (@_effective_resource || Effective::Resource.new(controller_path))
5
5
 
6
+ actions = if controller.respond_to?(:member_actions_for)
7
+ controller.member_actions_for(form.object)
8
+ else
9
+ {}.tap do |actions|
10
+ actions['Save'] = { data: { disable_with: 'Saving...' }}
11
+ actions['Save and Continue'] = { data: { disable_with: 'Saving...' }} if resource.index_path(check: true)
12
+ actions['Save and Add New'] = { data: { disable_with: 'Saving...' }} if resource.new_path(check: true)
13
+ end
14
+ end
15
+
6
16
  content_tag(:div, class: options[:class]) do
7
- [
8
- form.button(:submit, 'Save', data: { disable_with: 'Saving...' }),
9
- (form.button(:submit, 'Save and Continue', data: { disable_with: 'Saving...' }) if resource.index_path(check: true)),
10
- (form.button(:submit, 'Save and Add New', data: { disable_with: 'Saving...' }) if resource.new_path(check: true)),
11
- (capture(&block) if block_given?)
12
- ].compact.join(' ').html_safe
17
+ (actions.map { |action| form.button(:submit, *action.to_a) } + [(capture(&block) if block_given?)]).compact.join(' ').html_safe
13
18
  end
14
19
  end
15
20
 
@@ -41,6 +41,7 @@ module Effective
41
41
  when :resource ; :resource
42
42
  when :string ; :string
43
43
  when :text ; :text
44
+ when :time ; :time
44
45
  when FalseClass ; :boolean
45
46
  when Fixnum ; :integer
46
47
  when Float ; :decimal
@@ -73,6 +74,11 @@ module Effective
73
74
  date = Time.zone.local(*digits)
74
75
  name.to_s.start_with?('end_') ? date.end_of_day : date
75
76
  end
77
+ when :time
78
+ if (digits = value.to_s.scan(/(\d+)/).flatten).present?
79
+ now = Time.zone.now
80
+ Time.zone.local(now.year, now.month, now.day, *digits)
81
+ end
76
82
  when :decimal, :currency
77
83
  (value.kind_of?(String) ? value.gsub(/[^0-9|\-|\.]/, '') : value).to_f
78
84
  when :duration
@@ -32,6 +32,8 @@ module Effective
32
32
  { as: :number }
33
33
  when :text
34
34
  { as: :text }
35
+ when :time
36
+ { as: :time }
35
37
  when ActiveRecord::Base
36
38
  { as: :select }.merge(Effective::Resource.new(type).search_form_field_collection)
37
39
  else
@@ -41,6 +41,9 @@ module Effective
41
41
  when :string, :text
42
42
  relation
43
43
  .order(("ISNULL(#{sql_column}), " if mysql?).to_s + "#{sql_column}='' ASC, #{sql_column} #{sql_direction}" + (" NULLS LAST" if postgres?).to_s)
44
+ when :time
45
+ relation
46
+ .order(("ISNULL(#{sql_column}), " if mysql?).to_s + "EXTRACT(hour from #{sql_column}) #{sql_direction}, EXTRACT(minute from #{sql_column}) #{sql_direction}" + (" NULLS LAST" if postgres?).to_s)
44
47
  else
45
48
  relation
46
49
  .order(("ISNULL(#{sql_column}), " if mysql?).to_s + "#{sql_column} #{sql_direction}" + (" NULLS LAST" if postgres?).to_s)
@@ -101,6 +104,10 @@ module Effective
101
104
  end
102
105
  )
103
106
  relation.where("#{sql_column} >= ? AND #{sql_column} <= ?", term, end_at)
107
+ when :time
108
+ timed = relation.where("EXTRACT(hour from #{sql_column}) = ?", term.utc.hour)
109
+ timed = timed.where("EXTRACT(minute from #{sql_column}) = ?", term.utc.min) if term.min > 0
110
+ timed
104
111
  when :decimal, :currency
105
112
  if fuzzy && (term.round(0) == term) && value.to_s.include?('.') == false
106
113
  if term < 0
@@ -1,3 +1,3 @@
1
1
  module EffectiveResources
2
- VERSION = '0.5.1'.freeze
2
+ VERSION = '0.6.0'.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: 0.5.1
4
+ version: 0.6.0
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: 2017-10-20 00:00:00.000000000 Z
11
+ date: 2017-10-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails