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 +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
|