effective_resources 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 25f7989cfcdf5345382d521f94331238f4ecd109
4
- data.tar.gz: 0d2a3d92af2badd786a6d15da1e78daadaa5ffb9
3
+ metadata.gz: e0162b9865a0d7b0f8792b361f46f886c905286a
4
+ data.tar.gz: d3b8a389e8ff5e40860603aa22ed948bde07cc37
5
5
  SHA512:
6
- metadata.gz: 3eb401a0edeef0cda4a3f8eddf9e409f30e8a4e643e62bfa70e8914a4d4f44b69eb20719872d254f96d7afdb98bae7dfb6be20492ba327e3d3d08c4c5c7d315f
7
- data.tar.gz: 847044d382ea15c9b1a06786a09db78d82fe1d16636260d664d6d6f5afc90d2f1bb4a51fbada52b655f2516d719076ef21dfec73ec6a32bcbf0fcfa806fcc97c
6
+ metadata.gz: 7868a5dc8b09f78c1fd044878b9872e65a27e6698a8f52878d6a09a87dbde581c84a33b029d6d0c1869c2e362c24ab446c7b8e3d78ae95fd8e6f071d8c9786e1
7
+ data.tar.gz: 63eb662a68bb241d51b441dad12c2bcbba3cceaa8a04495e2fb868c56cb1aa441a64258ce347e69ccc268d98e7c08f16d345c906f954b92fa1a3e246d44daa07
data/README.md CHANGED
@@ -6,8 +6,6 @@ Implements the 7 RESTful actions as a one-liner on any controller.
6
6
 
7
7
  ## Getting Started
8
8
 
9
- Add to your Gemfile:
10
-
11
9
  ```ruby
12
10
  gem 'effective_resources'
13
11
  ```
@@ -18,6 +16,14 @@ Run the bundle command to install it:
18
16
  bundle install
19
17
  ```
20
18
 
19
+ Install the configuration file:
20
+
21
+ ```console
22
+ rails generate effective_resources:install
23
+ ```
24
+
25
+ The generator will install an initializer which describes all configuration options.
26
+
21
27
  ## Usage
22
28
 
23
29
  Add to your contoller:
@@ -26,6 +32,8 @@ Add to your contoller:
26
32
  class PostsController < ApplicationController
27
33
  include Effective::CrudController
28
34
 
35
+ member_action :something
36
+
29
37
  protected
30
38
 
31
39
  def post_scope
@@ -65,6 +73,18 @@ Call `simple_form_submit(f)` like follows:
65
73
 
66
74
  to render 3 submit buttons: `Save`, `Save and Continue`, and `Save and Add New`.
67
75
 
76
+ ### simple_form_save
77
+
78
+ Call `simple_form_save(f)` like follows:
79
+
80
+ ```haml
81
+ = simple_form_for(post) do |f|
82
+ ...
83
+ = simple_form_save(f)
84
+ ```
85
+
86
+ to render just the `Save` button, with appropriate data-disable, title, etc.
87
+
68
88
  ## License
69
89
 
70
90
  MIT License. Copyright [Code and Effect Inc.](http://www.codeandeffect.com/)
@@ -0,0 +1,2 @@
1
+ //= require_tree ./effective_resources
2
+
@@ -0,0 +1,85 @@
1
+ ;(function($, window, document, undefined) {
2
+ 'use strict';
3
+
4
+ var defaults = {};
5
+
6
+ function EffectiveUjs(element, command, options) {
7
+ if(typeof(command) === 'string') { // Convert to camelCase
8
+ command = command.replace(/-([a-z])/g, function (str) { return str[1].toUpperCase(); });
9
+ }
10
+
11
+ if(typeof(this[command]) === 'function') {
12
+ this[command]($(element), $.extend({}, defaults, options));
13
+ }
14
+ }
15
+
16
+ $.extend(EffectiveUjs.prototype, {
17
+
18
+ // Converts all inputs to required fields
19
+ // $('#div-with-inputs').effective('inputs-required')
20
+ // $('input').effective('inputs-required')
21
+ inputsRequired: function(element, options) {
22
+ var elements = (element.first().is(':input') ? element : element.find('input,select,textarea'));
23
+
24
+ elements.each(function(index) {
25
+ var input = $(this);
26
+ var formGroup = input.closest('.form-group');
27
+
28
+ if(input.attr('type') == 'hidden') { return; }
29
+ if(input.hasClass('optional') && (input.attr('name') || '').indexOf('[address2]') > -1) { return; } // EffectiveAddresses
30
+
31
+ // Require the input
32
+ input.prop('required', true);
33
+
34
+ // Add the *
35
+ formGroup.find('abbr').remove();
36
+ input.parent().find('abbr').remove();
37
+
38
+ if(input.parent().is('label')) {
39
+ input.after("<abbr title='required'>*</abbr> ");
40
+ } else if(formGroup.length > 0) {
41
+ formGroup.find('label').prepend("<abbr title='required'>*</abbr> ");
42
+ } else {
43
+ input.parent().find('label').prepend("<abbr title='required'>*</abbr> ");
44
+ }
45
+
46
+ if(formGroup.length > 0) {
47
+ formGroup.removeClass('optional').addClass('required');
48
+ formGroup.find('.optional').removeClass('optional').addClass('required');
49
+ }
50
+ });
51
+ },
52
+
53
+ // Converts all inputs to non-required fields
54
+ // $('#div-with-inputs').effective('inputs-optional')
55
+ // $('input').effective('inputs-optional')
56
+ inputsOptional: function(element, options) {
57
+ var elements = (element.first().is(':input') ? element : element.find('input,select,textarea'));
58
+
59
+ elements.each(function(index) {
60
+ var input = $(this);
61
+ var formGroup = input.closest('.form-group');
62
+
63
+ if(input.attr('type') == 'hidden') { return; }
64
+
65
+ // Un-require the input
66
+ input.prop('required', false).removeAttr('required');
67
+
68
+ // Remove the *
69
+ formGroup.find('abbr').remove();
70
+ input.parent().find('abbr').remove();
71
+
72
+ if(formGroup.length > 0) {
73
+ formGroup.removeClass('required').addClass('optional');
74
+ formGroup.find('.required').removeClass('required').addClass('optional');
75
+ }
76
+ });
77
+ }
78
+
79
+ });
80
+
81
+ $.fn.effective = function(command, options) {
82
+ return this.each(function() { new EffectiveUjs(this, command, options); });
83
+ };
84
+
85
+ })(jQuery, window, document);
@@ -6,6 +6,16 @@ module Effective
6
6
  end
7
7
 
8
8
  module ClassMethods
9
+ # Add the following to your controller for a simple member action
10
+ # member_action :print
11
+ def member_action(action)
12
+ define_method(action) do
13
+ self.resource ||= resource_class.find(params[:id])
14
+
15
+ @page_title ||= resource.to_s
16
+ EffectiveResources.authorized?(self, action, resource)
17
+ end
18
+ end
9
19
  end
10
20
 
11
21
  def index
@@ -114,6 +124,10 @@ module Effective
114
124
 
115
125
  private
116
126
 
127
+ def effective_resource
128
+ @_effective_resource ||= Effective::Resource.new(controller_path)
129
+ end
130
+
117
131
  def resource_name # 'thing'
118
132
  effective_resource.name
119
133
  end
@@ -167,11 +181,5 @@ module Effective
167
181
  effective_resource.index_path
168
182
  end
169
183
 
170
- private
171
-
172
- def effective_resource
173
- @_effective_resource ||= Effective::Resource.new(controller_path)
174
- end
175
-
176
184
  end
177
185
  end
@@ -1,18 +1,19 @@
1
1
  module EffectiveResourcesHelper
2
2
 
3
- def simple_form_submit(form)
4
- content_tag(:p, class: 'text-right') do
3
+ def simple_form_submit(form, options = {class: 'text-right'}, &block)
4
+ content_tag(:p, class: options[:class]) do
5
5
  [
6
6
  form.button(:submit, 'Save', data: { disable_with: 'Saving...' }),
7
7
  form.button(:submit, 'Save and Continue', data: { disable_with: 'Saving...' }),
8
- form.button(:submit, 'Save and Add New', data: { disable_with: 'Saving...' })
9
- ].join(' ').html_safe
8
+ form.button(:submit, 'Save and Add New', data: { disable_with: 'Saving...' }),
9
+ (capture(&block) if block_given?)
10
+ ].compact.join(' ').html_safe
10
11
  end
11
12
  end
12
13
 
13
- def simple_form_save(form)
14
- content_tag(:p, class: 'text-right') do
15
- form.button(:submit, 'Save', data: { disable_with: 'Saving...' })
14
+ def simple_form_save(form, options = {class: 'text-right'}, &block)
15
+ content_tag(:p, class: options[:class]) do
16
+ form.button(:submit, 'Save', data: { disable_with: 'Saving...' }) + (capture(&:block) if block_given?)
16
17
  end
17
18
  end
18
19
 
@@ -3,6 +3,7 @@ module Effective
3
3
  include Effective::Resources::Associations
4
4
  include Effective::Resources::Attributes
5
5
  include Effective::Resources::Init
6
+ include Effective::Resources::Instance
6
7
  include Effective::Resources::Klass
7
8
  include Effective::Resources::Naming
8
9
  include Effective::Resources::Paths
@@ -4,19 +4,22 @@ module Effective
4
4
 
5
5
  def belong_tos
6
6
  return [] unless klass.respond_to?(:reflect_on_all_associations)
7
-
8
7
  @belong_tos ||= klass.reflect_on_all_associations(:belongs_to)
9
8
  end
10
9
 
11
- def nested_resources
12
- return {} unless klass.respond_to?(:reflect_on_all_autosave_associations)
13
-
14
- @nested ||= klass.reflect_on_all_autosave_associations.inject({}) do |hash, reference|
15
- hash[reference] = Effective::Resource.new(reference); hash
16
- end
10
+ def has_ones
11
+ return [] unless klass.respond_to?(:reflect_on_all_associations)
12
+ @has_ones ||= klass.reflect_on_all_associations(:has_one)
17
13
  end
18
14
 
19
15
  def has_manys
16
+ return [] unless klass.respond_to?(:reflect_on_all_associations)
17
+ @has_manys ||= klass.reflect_on_all_associations(:has_many).reject { |association| association.options[:autosave] }
18
+ end
19
+
20
+ def nested_resources
21
+ return [] unless klass.respond_to?(:reflect_on_all_associations)
22
+ @nested_resources ||= klass.reflect_on_all_associations(:has_many).select { |association| association.options[:autosave] }
20
23
  end
21
24
 
22
25
  def scopes
@@ -4,8 +4,9 @@ module Effective
4
4
 
5
5
  private
6
6
 
7
- def _initialize(input)
8
- @input_name = _initialize_input_name(input)
7
+ def _initialize(obj)
8
+ @input_name = _initialize_input_name(obj)
9
+ @instance = obj if (klass && obj.instance_of?(klass))
9
10
  end
10
11
 
11
12
  def _initialize_input_name(input)
@@ -13,10 +14,11 @@ module Effective
13
14
  when String ; input
14
15
  when Symbol ; input
15
16
  when Class ; input.name
16
- when ActiveRecord::Reflection::MacroReflection ; input.name
17
+ when (ActiveRecord::Reflection::MacroReflection rescue false); input.name
18
+ when (ActionDispatch::Journey::Route rescue false); input.defaults[:controller]
17
19
  when nil ; raise 'expected a string or class'
18
20
  else ; input.class.name
19
- end.to_s.downcase
21
+ end.to_s.underscore
20
22
  end
21
23
 
22
24
  # Lazy initialized
@@ -0,0 +1,55 @@
1
+ module Effective
2
+ module Resources
3
+ module Instance
4
+ attr_reader :instance
5
+
6
+ # This is written for use by effective_logging and effective_trash
7
+
8
+ def instance_attributes
9
+ return {} unless instance.present?
10
+
11
+ attributes = { attributes: instance.attributes }
12
+
13
+ # Collect to_s representations of all belongs_to associations
14
+ belong_tos.each do |association|
15
+ attributes[association.name] = instance.send(association.name).to_s
16
+ end
17
+
18
+ has_ones.each do |association|
19
+ attributes[association.name] = instance.send(association.name).to_s
20
+ end
21
+
22
+ nested_resources.each do |association|
23
+ attributes[association.name] = {}
24
+
25
+ Array(instance.send(association.name)).each_with_index do |child, index|
26
+ resource = Effective::Resource.new(child)
27
+ attributes[association.name][index] = resource.instance_attributes
28
+ end
29
+ end
30
+
31
+ attributes.delete_if { |_, value| value.blank? }
32
+ end
33
+
34
+ def instance_changes
35
+ return {} unless instance.present?
36
+
37
+ changes = instance.changes
38
+
39
+ # Log to_s changes on all belongs_to associations
40
+ belong_tos.each do |association|
41
+ if (change = changes.delete(association.foreign_key)).present?
42
+ changes[association.name] = [(association.klass.find_by_id(change.first) if changes.first), instance.send(association.name)]
43
+ end
44
+ end
45
+
46
+ changes
47
+ end
48
+
49
+ end
50
+ end
51
+ end
52
+
53
+
54
+
55
+
@@ -3,7 +3,11 @@ module Effective
3
3
  module Klass
4
4
 
5
5
  def klass
6
- namespaced_class_name.safe_constantize || class_name.safe_constantize || name.safe_constantize
6
+ @model_klass ||= (
7
+ namespaced_class_name.safe_constantize ||
8
+ class_name.safe_constantize ||
9
+ name.classify.safe_constantize
10
+ )
7
11
  end
8
12
 
9
13
  def datatable_klass
@@ -17,6 +21,14 @@ module Effective
17
21
  end
18
22
  end
19
23
 
24
+ def controller_klass
25
+ @controller_klass ||= (
26
+ "#{namespaced_class_name.pluralize}Controller".safe_constantize ||
27
+ "#{class_name.pluralize.classify}Controller".safe_constantize ||
28
+ "#{name.pluralize.classify}Controller".safe_constantize
29
+ )
30
+ end
31
+
20
32
  end
21
33
  end
22
34
  end
@@ -2,7 +2,7 @@ module EffectiveResources
2
2
  class Engine < ::Rails::Engine
3
3
  engine_name 'effective_resources'
4
4
 
5
- config.autoload_paths += Dir["#{config.root}/lib/"]
5
+ config.autoload_paths += Dir["#{config.root}/lib/", "#{config.root}/app/controllers/concerns/effective/"]
6
6
 
7
7
  # Set up our default configuration options.
8
8
  initializer 'effective_resources.defaults', before: :load_config_initializers do |app|
@@ -1,3 +1,3 @@
1
1
  module EffectiveResources
2
- VERSION = '0.2.1'.freeze
2
+ VERSION = '0.2.2'.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.2.1
4
+ version: 0.2.2
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-01-26 00:00:00.000000000 Z
11
+ date: 2017-02-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -33,6 +33,8 @@ extra_rdoc_files: []
33
33
  files:
34
34
  - MIT-LICENSE
35
35
  - README.md
36
+ - app/assets/javascripts/effective_resources.js
37
+ - app/assets/javascripts/effective_resources/effective_ujs.js
36
38
  - app/controllers/concerns/effective/crud_controller.rb
37
39
  - app/helpers/effective_resources_helper.rb
38
40
  - app/models/effective/access_denied.rb
@@ -42,6 +44,7 @@ files:
42
44
  - app/models/effective/resources/associations.rb
43
45
  - app/models/effective/resources/attributes.rb
44
46
  - app/models/effective/resources/init.rb
47
+ - app/models/effective/resources/instance.rb
45
48
  - app/models/effective/resources/klass.rb
46
49
  - app/models/effective/resources/naming.rb
47
50
  - app/models/effective/resources/paths.rb