effective_resources 0.2.1 → 0.2.2
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/README.md +22 -2
- data/app/assets/javascripts/effective_resources.js +2 -0
- data/app/assets/javascripts/effective_resources/effective_ujs.js +85 -0
- data/app/controllers/concerns/effective/crud_controller.rb +14 -6
- data/app/helpers/effective_resources_helper.rb +8 -7
- data/app/models/effective/resource.rb +1 -0
- data/app/models/effective/resources/associations.rb +10 -7
- data/app/models/effective/resources/init.rb +6 -4
- data/app/models/effective/resources/instance.rb +55 -0
- data/app/models/effective/resources/klass.rb +13 -1
- data/lib/effective_resources/engine.rb +1 -1
- data/lib/effective_resources/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e0162b9865a0d7b0f8792b361f46f886c905286a
|
4
|
+
data.tar.gz: d3b8a389e8ff5e40860603aa22ed948bde07cc37
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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,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:
|
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
|
-
|
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:
|
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
|
12
|
-
return
|
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(
|
8
|
-
@input_name = _initialize_input_name(
|
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.
|
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
|
-
|
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|
|
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.
|
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-
|
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
|