evil_scaffold 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +23 -0
- data/.rspec +2 -0
- data/.travis.yml +3 -0
- data/.zeiger.yml +28 -0
- data/Gemfile +4 -0
- data/MIT-LICENSE.txt +22 -0
- data/README.md +121 -0
- data/Rakefile +7 -0
- data/evil_scaffold.gemspec +23 -0
- data/lib/evil_scaffold.rb +58 -0
- data/lib/evil_scaffold/create_action.rb +44 -0
- data/lib/evil_scaffold/delete_action.rb +14 -0
- data/lib/evil_scaffold/destroy_action.rb +50 -0
- data/lib/evil_scaffold/edit_action.rb +13 -0
- data/lib/evil_scaffold/finder_method.rb +38 -0
- data/lib/evil_scaffold/goto_show_method.rb +16 -0
- data/lib/evil_scaffold/index_action.rb +84 -0
- data/lib/evil_scaffold/index_json.rb +40 -0
- data/lib/evil_scaffold/new_action.rb +17 -0
- data/lib/evil_scaffold/plugin.rb +9 -0
- data/lib/evil_scaffold/return_appropriately_method.rb +16 -0
- data/lib/evil_scaffold/show_action.rb +31 -0
- data/lib/evil_scaffold/update_action.rb +29 -0
- data/lib/evil_scaffold/version.rb +3 -0
- data/spec/evil_scaffold_spec.rb +11 -0
- data/spec/spec_helper.rb +2 -0
- metadata +119 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9bc3bf2eedb12a31b0e2482804cd7d29fe9869f0
|
4
|
+
data.tar.gz: 4d06893c53deb32d6255df734b9f057a6c745b87
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f1d7003f7e89e5e8f1df2ccb89eaeae8064aa79179741c7c0388ceba95d4bb0af1b21d4b015ddaaea464b549be7d214f702dc2f6661cd549d729cadc68d9a2a1
|
7
|
+
data.tar.gz: 4d05c1692d70ae53e2c8b460c980c70ae8652a0d83d8b21ab492e60aa1492e94bb93cef3106ab88c3e37d2696ddef07c0ecb7bd15d5e5c5434eecd9918776656
|
data/.gitignore
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
.#*
|
19
|
+
*.bundle
|
20
|
+
*.so
|
21
|
+
*.o
|
22
|
+
*.a
|
23
|
+
mkmf.log
|
data/.rspec
ADDED
data/.travis.yml
ADDED
data/.zeiger.yml
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
search:
|
2
|
+
- "bin/**/*"
|
3
|
+
- "lib/**/*"
|
4
|
+
- "spec/**/*"
|
5
|
+
- "*.gemspec"
|
6
|
+
- ".*.yml"
|
7
|
+
- ".git?*"
|
8
|
+
- "Gemfile*"
|
9
|
+
- README
|
10
|
+
ignore:
|
11
|
+
- .doc$
|
12
|
+
- .ods$
|
13
|
+
- .gz$
|
14
|
+
- .png$
|
15
|
+
- .gif$
|
16
|
+
- .zip$
|
17
|
+
- .jpg$
|
18
|
+
- .xcf$
|
19
|
+
- .pdf$
|
20
|
+
- /select2/.*.js$
|
21
|
+
stats:
|
22
|
+
nydp:
|
23
|
+
- ".*\\.nydp"
|
24
|
+
code:
|
25
|
+
- "lib/.*\\.(rb|rake)"
|
26
|
+
test:
|
27
|
+
- "spec/.*"
|
28
|
+
- "test/.*"
|
data/Gemfile
ADDED
data/MIT-LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 conanite
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
# EvilScaffold
|
2
|
+
|
3
|
+
This gem provides the `acts_as_evil` method for Rails 4.0 controllers. It may work with later railses, patches welcome if not.
|
4
|
+
|
5
|
+
`acts_as_evil` generates action methods in your controller, and makes a bunch of assumptions about how you want your actions to behave.
|
6
|
+
|
7
|
+
It is evil, because according to some people, you should be able to see all the code in your application.
|
8
|
+
|
9
|
+
Differences between traditional Rails scaffolds, and `acts_as_evil` :
|
10
|
+
|
11
|
+
### `acts_as_evil`
|
12
|
+
|
13
|
+
* Generates code at runtime, so you never see the generated code (unless you debug it)
|
14
|
+
* Makes a bunch of assumptions about how your actions should behave
|
15
|
+
* Has a ton of undocumented configuration options
|
16
|
+
* Requires either a lot of trust, or an inspection of the generated code
|
17
|
+
|
18
|
+
### Rails scaffolds
|
19
|
+
|
20
|
+
* Generate controller class files that you then manipulate at will and check into your code repository
|
21
|
+
* Generate very simple methods that are easy to understand and use
|
22
|
+
* Are better documented
|
23
|
+
|
24
|
+
People will readily agree that traditional Rails scaffolds are better in almost all cases. Here are two strong justifications for using `evil_scaffold` :
|
25
|
+
|
26
|
+
* Either you are the author of the gem and understand its features intimately, remaining blissfully unaware of its defects, or
|
27
|
+
* You have an overwhelming, chronic obsession with minimizing your LOC count and will sacrifice all readability to this end.
|
28
|
+
|
29
|
+
## Installation
|
30
|
+
|
31
|
+
Add this line to your application's Gemfile:
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
gem 'evil_scaffold'
|
35
|
+
```
|
36
|
+
|
37
|
+
And then execute:
|
38
|
+
|
39
|
+
$ bundle
|
40
|
+
|
41
|
+
Or install it yourself as:
|
42
|
+
|
43
|
+
$ gem install evil_scaffold
|
44
|
+
|
45
|
+
## Usage
|
46
|
+
|
47
|
+
Read the code and figure it out. Here are some examples:
|
48
|
+
|
49
|
+
Generate a #new action and a #create action
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
acts_as_evil Post, :new, :create
|
53
|
+
```
|
54
|
+
|
55
|
+
Both actions will instantiate a variable called `@post`. `new` will instantiate a new Post and render the `new` template. `create` will instantiate a new Post, call `save` on it, and then `redirect_to params[:return_to]`
|
56
|
+
|
57
|
+
Here is a more complete example:
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
acts_as_evil Contact, :index, :index_json, :new, :create, :show, :edit, :update, :delete, :destroy, :finder
|
61
|
+
```
|
62
|
+
|
63
|
+
The variable this time is called `@contact`. `index_json` is called from the `index` action when the requested content-type is `json`. `finder` is not an action but rather a one-line `before_filter` (or `before_action`)
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
def find_contact
|
67
|
+
@contact = Contact.find params[:id]
|
68
|
+
end
|
69
|
+
```
|
70
|
+
|
71
|
+
`find_contact` is installed as a `before_filter` for all "member" actions (`show`, `edit`, `delete`)
|
72
|
+
|
73
|
+
You can install your finder as a `before_filter` for other actions in the configuration block:
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
acts_as_evil Comment, :edit, :update, :delete, :destroy, :finder, find_for: %i{ approve }
|
77
|
+
```
|
78
|
+
|
79
|
+
This does not create the `approve` action, but includes it in the line
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
before_filter :find_comment, only: %i{ edit update delete approve }
|
83
|
+
```
|
84
|
+
|
85
|
+
`evil_scaffold` doesn't make any assumptions about the order of items in your `index` action ; it will assign items using the backing store's native ordering. You can control this by telling `acts_as_evil` to call a particular scope definition on your model:
|
86
|
+
|
87
|
+
```ruby
|
88
|
+
acts_as_evil Invoice, :index, order: :order_by_date_desc
|
89
|
+
```
|
90
|
+
|
91
|
+
This will insert somewhere inside your `index` action
|
92
|
+
|
93
|
+
```ruby
|
94
|
+
@invoices = @invoices.order_by_date_desc
|
95
|
+
```
|
96
|
+
|
97
|
+
Finally, if you have a really awkward long model class name, you can avoid embarassment using `model_name`:
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
class Cms::Posts::CommentsController
|
101
|
+
acts_as_evil Cms::Post::Comment, :index, :new, :create, :show, :delete, :destroy, :finder, as: :comment
|
102
|
+
end
|
103
|
+
```
|
104
|
+
|
105
|
+
This will create a variable called `@comment` instead of `@cms_post_comment`, thus avoiding the risk of inviting snickering from your colleagues.
|
106
|
+
|
107
|
+
If you want to see the generated code, use the #evil class attribute:
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
> puts Cms::Posts::CommentsController.evil.code
|
111
|
+
```
|
112
|
+
|
113
|
+
This will spit out all the code that EvilScaffold has generated for you.
|
114
|
+
|
115
|
+
## Contributing
|
116
|
+
|
117
|
+
1. Fork it ( https://github.com/[my-github-username]/evil_scaffold/fork )
|
118
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
119
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
120
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
121
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
lib = File.expand_path('../lib', __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require 'evil_scaffold/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "evil_scaffold"
|
7
|
+
spec.version = EvilScaffold::VERSION
|
8
|
+
spec.authors = ["Conan Dalton"]
|
9
|
+
spec.email = ["conan@conandalton.net"]
|
10
|
+
spec.summary = %q{ Generates mostly-unsurprising controller code at app startup so your codebase is not cluttered with boilerplate @foo.find(params[:id]).update_attributes(params[:foo]) style code }
|
11
|
+
spec.description = %q{ Generates rails controller actions at runtime. Does not generate source code for you to inspect, modify and commit to version control, so requires your blind faith, hence evil. Also does not attempt to generate view code. On the other hand, massively reduces your line count.}
|
12
|
+
spec.homepage = "http://github.com/conanite/evil_scaffold"
|
13
|
+
spec.license = "MIT"
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0")
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
21
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
22
|
+
spec.add_development_dependency 'rspec', '~> 2.9'
|
23
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require "evil_scaffold/version"
|
2
|
+
require 'evil_scaffold/plugin'
|
3
|
+
require 'evil_scaffold/index_action'
|
4
|
+
require 'evil_scaffold/index_json'
|
5
|
+
require 'evil_scaffold/new_action'
|
6
|
+
require 'evil_scaffold/create_action'
|
7
|
+
require 'evil_scaffold/show_action'
|
8
|
+
require 'evil_scaffold/edit_action'
|
9
|
+
require 'evil_scaffold/update_action'
|
10
|
+
require 'evil_scaffold/delete_action'
|
11
|
+
require 'evil_scaffold/destroy_action'
|
12
|
+
require 'evil_scaffold/goto_show_method'
|
13
|
+
require 'evil_scaffold/return_appropriately_method'
|
14
|
+
require 'evil_scaffold/finder_method'
|
15
|
+
|
16
|
+
module EvilScaffold
|
17
|
+
module Configurable
|
18
|
+
attr_accessor :evil
|
19
|
+
end
|
20
|
+
|
21
|
+
class Configuration
|
22
|
+
attr_accessor :klass, :names, :model_name, :models_name, :model_class_name
|
23
|
+
attr_accessor :no_filter, :ordering_scope, :code
|
24
|
+
|
25
|
+
def for? name
|
26
|
+
names.include? name
|
27
|
+
end
|
28
|
+
|
29
|
+
def as name
|
30
|
+
self.model_name = name
|
31
|
+
end
|
32
|
+
|
33
|
+
def order scope_name
|
34
|
+
self.ordering_scope = scope_name
|
35
|
+
end
|
36
|
+
|
37
|
+
def install new_code, file, line
|
38
|
+
self.code = [code.to_s, "\n# #{file}:#{line}", new_code].join("\n")
|
39
|
+
klass.class_eval new_code, file, line
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def acts_as_evil target_model, action_names, options={}
|
44
|
+
extend Configurable
|
45
|
+
self.evil = config = Configuration.new
|
46
|
+
config.klass = self
|
47
|
+
config.names = Set.new action_names
|
48
|
+
config.model_class_name = target_model.name
|
49
|
+
config.model_name = config.model_class_name.underscore
|
50
|
+
GENERATORS.each { |gen| gen.prepare config }
|
51
|
+
|
52
|
+
options.each { |k,v| config.send k, v }
|
53
|
+
yield config if block_given?
|
54
|
+
config.models_name ||= config.model_name.to_s.pluralize
|
55
|
+
|
56
|
+
GENERATORS.each { |gen| gen.install config }
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module EvilScaffold
|
2
|
+
CreateAction = EvilScaffold.add_generator do
|
3
|
+
def self.prepare config ; end
|
4
|
+
|
5
|
+
def self.install config
|
6
|
+
return unless config.for? :create
|
7
|
+
config.install <<ACTION, __FILE__, __LINE__
|
8
|
+
# by default permits all attrs, override if you need to be more selective about your attributes
|
9
|
+
def sanitise_for_create attrs
|
10
|
+
attrs.permit!
|
11
|
+
end
|
12
|
+
|
13
|
+
# override this to respond appropriately in case of a validation error
|
14
|
+
def create_validation_failure thing
|
15
|
+
raise(ActiveRecord::RecordInvalid.new(thing))
|
16
|
+
end
|
17
|
+
|
18
|
+
# override this and raise an error if thing cannot be created for any reason other than validation error
|
19
|
+
def authorise_creation thing
|
20
|
+
thing
|
21
|
+
end
|
22
|
+
|
23
|
+
# this is called after #create for any xhr request
|
24
|
+
def ajax_after_create
|
25
|
+
render "ajax_create", layout: false
|
26
|
+
end
|
27
|
+
|
28
|
+
# this is the #create action
|
29
|
+
def create
|
30
|
+
@#{config.model_name} = authorise_creation #{config.model_class_name}.new sanitise_for_create params[:#{config.model_name}]
|
31
|
+
if @#{config.model_name}.save
|
32
|
+
if request.xhr?
|
33
|
+
ajax_after_create
|
34
|
+
else
|
35
|
+
return_appropriately
|
36
|
+
end
|
37
|
+
else
|
38
|
+
create_validation_failure @#{config.model_name}
|
39
|
+
end
|
40
|
+
end
|
41
|
+
ACTION
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module EvilScaffold
|
2
|
+
DeleteAction = EvilScaffold.add_generator do
|
3
|
+
def self.prepare config ; end
|
4
|
+
def self.install config
|
5
|
+
return unless config.for? :delete
|
6
|
+
|
7
|
+
config.install <<ACTION, __FILE__, __LINE__
|
8
|
+
def delete
|
9
|
+
render layout: !request.xhr?
|
10
|
+
end
|
11
|
+
ACTION
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module EvilScaffold
|
2
|
+
class Configuration
|
3
|
+
attr_accessor :avoid_after_delete
|
4
|
+
def delete_avoid name
|
5
|
+
self.avoid_after_delete = name
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
DestroyAction = EvilScaffold.add_generator do
|
10
|
+
def self.prepare config
|
11
|
+
name = config.klass.name
|
12
|
+
show_path = name.underscore.sub(/_controller$/, '').gsub("/", "_").singularize
|
13
|
+
config.avoid_after_delete = show_path
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.install config
|
17
|
+
return unless config.for? :destroy
|
18
|
+
|
19
|
+
avoidance_clause = <<AVOIDANCE
|
20
|
+
wrong_url = #{config.avoid_after_delete}_path(@#{config.model_name})
|
21
|
+
if params[:return_to] == wrong_url
|
22
|
+
redirect_to action: :index
|
23
|
+
else
|
24
|
+
back
|
25
|
+
end
|
26
|
+
AVOIDANCE
|
27
|
+
|
28
|
+
back_instruction = if config.avoid_after_delete.present?
|
29
|
+
avoidance_clause
|
30
|
+
else
|
31
|
+
"back"
|
32
|
+
end
|
33
|
+
|
34
|
+
config.install <<ACTION, __FILE__, __LINE__
|
35
|
+
def ajax_after_destroy
|
36
|
+
render "ajax_destroy", layout: false
|
37
|
+
end
|
38
|
+
|
39
|
+
def destroy
|
40
|
+
@#{config.model_name}.destroy
|
41
|
+
if request.xhr?
|
42
|
+
ajax_after_destroy
|
43
|
+
else
|
44
|
+
#{back_instruction}
|
45
|
+
end
|
46
|
+
end
|
47
|
+
ACTION
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module EvilScaffold
|
2
|
+
EditAction = EvilScaffold.add_generator do
|
3
|
+
def self.prepare config ; end
|
4
|
+
def self.install config
|
5
|
+
return unless config.for? :edit
|
6
|
+
config.install <<ACTION, __FILE__, __LINE__
|
7
|
+
def edit
|
8
|
+
render layout: !request.xhr?
|
9
|
+
end
|
10
|
+
ACTION
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module EvilScaffold
|
2
|
+
class Configuration
|
3
|
+
attr_accessor :finder_filter_actions
|
4
|
+
def find_for names
|
5
|
+
self.finder_filter_actions += names
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
FinderMethod = EvilScaffold.add_generator do
|
10
|
+
def self.prepare config
|
11
|
+
config.finder_filter_actions = %i{ show edit update delete destroy }
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.install config
|
15
|
+
return unless config.for? :finder
|
16
|
+
|
17
|
+
finder = "find_#{config.model_name}"
|
18
|
+
config.install <<FILTER, __FILE__, __LINE__
|
19
|
+
|
20
|
+
# override this to do something with your model after you've found it. @#{config.model_name} should be set at this point.
|
21
|
+
def after_#{finder}; end
|
22
|
+
|
23
|
+
def #{finder}
|
24
|
+
@#{config.model_name} = #{config.model_class_name}.find params[:id]
|
25
|
+
after_#{finder}
|
26
|
+
end
|
27
|
+
|
28
|
+
# #subject is just a standardised alias for @#{config.model_name}
|
29
|
+
def subject
|
30
|
+
@#{config.model_name}
|
31
|
+
end
|
32
|
+
|
33
|
+
protected :after_#{finder}, :#{finder}, :subject
|
34
|
+
before_filter :#{finder}, only: #{config.finder_filter_actions.inspect}
|
35
|
+
FILTER
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module EvilScaffold
|
2
|
+
GotoShowMethod = EvilScaffold.add_generator do
|
3
|
+
def self.prepare config ; end
|
4
|
+
def self.install config
|
5
|
+
return unless config.for? :goto_show
|
6
|
+
|
7
|
+
method_name = "back_to_#{config.model_name}"
|
8
|
+
config.install <<ACTION, __FILE__, __LINE__
|
9
|
+
def #{method_name}
|
10
|
+
redirect_to action: :show, id: @#{config.model_name}.id
|
11
|
+
end
|
12
|
+
protected :#{method_name}
|
13
|
+
ACTION
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module EvilScaffold
|
2
|
+
module IndexActionHelpers
|
3
|
+
protected
|
4
|
+
|
5
|
+
def index_xls
|
6
|
+
response.headers["Content-Type"] = "application/vnd.ms-excel;charset=iso-8859-1"
|
7
|
+
response.headers["charset"] = 'iso-8859-1'
|
8
|
+
end
|
9
|
+
|
10
|
+
def handle_unique_result results ; false ; end
|
11
|
+
def with_eager_includes results ; results ; end
|
12
|
+
def index_pre_render ; end
|
13
|
+
def index_per_page ; 50 ; end
|
14
|
+
|
15
|
+
def index_paginate items
|
16
|
+
items.paginate(:per_page => index_per_page, :page => params[:page] || 1)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
IndexAction = EvilScaffold.add_generator do
|
21
|
+
def self.prepare config ; end
|
22
|
+
def self.install config
|
23
|
+
return unless config.for? :index
|
24
|
+
|
25
|
+
if config.ordering_scope
|
26
|
+
ordinal_clause = <<ORDINAL
|
27
|
+
@#{config.models_name} = @#{config.models_name}.#{config.ordering_scope}
|
28
|
+
ORDINAL
|
29
|
+
else
|
30
|
+
ordinal_clause = ""
|
31
|
+
end
|
32
|
+
|
33
|
+
if config.no_filter
|
34
|
+
filter_invocation = "@#{config.models_name} = #{config.model_class_name}.all"
|
35
|
+
else
|
36
|
+
filter_invocation = "@#{config.models_name} = filter_#{config.models_name}(#{config.model_class_name}.all)"
|
37
|
+
config.install <<ACTION, __FILE__, __LINE__
|
38
|
+
def filter_#{config.models_name} items
|
39
|
+
items
|
40
|
+
end
|
41
|
+
protected :filter_#{config.models_name}
|
42
|
+
ACTION
|
43
|
+
end
|
44
|
+
|
45
|
+
config.install <<ACTION, __FILE__, __LINE__
|
46
|
+
include EvilScaffold::IndexActionHelpers
|
47
|
+
|
48
|
+
def index_xhr_view_template
|
49
|
+
"index_ajax"
|
50
|
+
end unless method_defined?(:index_xhr_view_template)
|
51
|
+
|
52
|
+
def index_html
|
53
|
+
@#{config.models_name}_count = @#{config.models_name}.size
|
54
|
+
return if !request.xhr? && (@#{config.models_name}_count == 1) && (handle_unique_result(@#{config.models_name}.first))
|
55
|
+
|
56
|
+
index_pre_render
|
57
|
+
|
58
|
+
@#{config.models_name} = with_eager_includes(@#{config.models_name})
|
59
|
+
#{ordinal_clause}
|
60
|
+
@unpaginated_#{config.models_name} = @#{config.models_name}
|
61
|
+
@#{config.models_name} = index_paginate(@#{config.models_name})
|
62
|
+
|
63
|
+
if request.xhr?
|
64
|
+
render index_xhr_view_template, layout: false
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def filter_for_index
|
69
|
+
#{filter_invocation}
|
70
|
+
end
|
71
|
+
|
72
|
+
def index
|
73
|
+
filter_for_index
|
74
|
+
respond_to do |format|
|
75
|
+
format.json { index_json }
|
76
|
+
format.xls { index_xls }
|
77
|
+
format.pdf { index_pdf }
|
78
|
+
format.html { index_html }
|
79
|
+
end
|
80
|
+
end
|
81
|
+
ACTION
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module EvilScaffold
|
2
|
+
IndexJson = EvilScaffold.add_generator do
|
3
|
+
def self.prepare config ; end
|
4
|
+
def self.install config
|
5
|
+
return unless config.for? :index_json
|
6
|
+
item_to_json = "#{config.model_name}_to_json"
|
7
|
+
config.install <<INDEX_JSON, __FILE__, __LINE__
|
8
|
+
protected
|
9
|
+
|
10
|
+
def #{item_to_json} item
|
11
|
+
{ id: item.id, text: item.name }
|
12
|
+
end
|
13
|
+
|
14
|
+
def index_json_optgroups items
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def index_json_per_page
|
19
|
+
20
|
20
|
+
end
|
21
|
+
|
22
|
+
def index_json
|
23
|
+
per_page = isset(:per_page) ? params[:per_page].to_i : index_json_per_page
|
24
|
+
page = isset(:page) ? params[:page].to_i : 1
|
25
|
+
@#{config.models_name} = @#{config.models_name}.paginate page: page, per_page: per_page
|
26
|
+
optgroups = index_json_optgroups @#{config.models_name}
|
27
|
+
results = if optgroups.nil?
|
28
|
+
@#{config.models_name}.map { |item| #{config.model_name}_to_json item }
|
29
|
+
else
|
30
|
+
optgroups.map { |grouping, items|
|
31
|
+
{ text: grouping, children: items.map { |item| #{item_to_json} item } }
|
32
|
+
}
|
33
|
+
end
|
34
|
+
pagination = { more: (page * per_page) < @#{config.models_name}.total_entries }
|
35
|
+
render json: { results: results, pagination: pagination }
|
36
|
+
end
|
37
|
+
INDEX_JSON
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module EvilScaffold
|
2
|
+
NewAction = EvilScaffold.add_generator do
|
3
|
+
def self.prepare config ; end
|
4
|
+
def self.install config
|
5
|
+
return unless config.for? :new
|
6
|
+
config.install <<ACTION, __FILE__, __LINE__
|
7
|
+
def build_new_#{config.model_name}
|
8
|
+
end
|
9
|
+
|
10
|
+
def new
|
11
|
+
build_new_#{config.model_name}
|
12
|
+
render layout: !request.xhr?
|
13
|
+
end
|
14
|
+
ACTION
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module EvilScaffold
|
2
|
+
ReturnAppropriatelyMethod = EvilScaffold.add_generator do
|
3
|
+
def self.prepare config ; end
|
4
|
+
def self.install config
|
5
|
+
config.install <<MAYBE_BACK, __FILE__, __LINE__
|
6
|
+
def return_appropriately
|
7
|
+
if params[:return_to]
|
8
|
+
back
|
9
|
+
else
|
10
|
+
back_to_#{config.model_name}
|
11
|
+
end
|
12
|
+
end
|
13
|
+
MAYBE_BACK
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module EvilScaffold
|
2
|
+
ShowAction = EvilScaffold.add_generator do
|
3
|
+
def self.prepare config ; end
|
4
|
+
def self.install config
|
5
|
+
return unless config.for? :show
|
6
|
+
config.install "def show_html; render layout: !request.xhr?; end", __FILE__, __LINE__
|
7
|
+
config.install "def show_xls; end", __FILE__, __LINE__
|
8
|
+
config.install "def show_vcf; end", __FILE__, __LINE__
|
9
|
+
config.install "def show_pdf; end", __FILE__, __LINE__
|
10
|
+
config.install "def show_zip; end", __FILE__, __LINE__
|
11
|
+
config.install <<ACTION, __FILE__, __LINE__ + 1
|
12
|
+
def show_yaml
|
13
|
+
exporter = Protopack::Exporter.new
|
14
|
+
hsh = exporter.to_package @#{config.model_name}
|
15
|
+
send_data exporter.clean_yaml(hsh), filename: "#{config.model_name}-\#{hsh['id'].gsub(/\s/, '-')}-item.yaml"
|
16
|
+
end
|
17
|
+
|
18
|
+
def show
|
19
|
+
respond_to do |format|
|
20
|
+
format.html { show_html }
|
21
|
+
format.xls { show_xls }
|
22
|
+
format.vcf { show_vcf }
|
23
|
+
format.pdf { show_pdf }
|
24
|
+
format.yaml { show_yaml }
|
25
|
+
format.zip { show_zip }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
ACTION
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module EvilScaffold
|
2
|
+
UpdateAction = EvilScaffold.add_generator do
|
3
|
+
def self.prepare config ; end
|
4
|
+
def self.install config
|
5
|
+
return unless config.for? :update
|
6
|
+
config.install <<ACTION, __FILE__, (__LINE__ + 1)
|
7
|
+
def sanitise_for_update attrs
|
8
|
+
attrs.permit!
|
9
|
+
end
|
10
|
+
|
11
|
+
def ajax_after_update
|
12
|
+
render "ajax_update", layout: false
|
13
|
+
end
|
14
|
+
|
15
|
+
def update
|
16
|
+
if @#{config.model_name}.update_attributes sanitise_for_update params[:#{config.model_name}]
|
17
|
+
if request.xhr?
|
18
|
+
ajax_after_update
|
19
|
+
else
|
20
|
+
return_appropriately
|
21
|
+
end
|
22
|
+
else
|
23
|
+
raise "save failed : \#{@#{config.model_name}.errors.to_yaml}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
ACTION
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: evil_scaffold
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Conan Dalton
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-05-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.7'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2.9'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2.9'
|
55
|
+
description: " Generates rails controller actions at runtime. Does not generate source
|
56
|
+
code for you to inspect, modify and commit to version control, so requires your
|
57
|
+
blind faith, hence evil. Also does not attempt to generate view code. On the other
|
58
|
+
hand, massively reduces your line count."
|
59
|
+
email:
|
60
|
+
- conan@conandalton.net
|
61
|
+
executables: []
|
62
|
+
extensions: []
|
63
|
+
extra_rdoc_files: []
|
64
|
+
files:
|
65
|
+
- ".gitignore"
|
66
|
+
- ".rspec"
|
67
|
+
- ".travis.yml"
|
68
|
+
- ".zeiger.yml"
|
69
|
+
- Gemfile
|
70
|
+
- MIT-LICENSE.txt
|
71
|
+
- README.md
|
72
|
+
- Rakefile
|
73
|
+
- evil_scaffold.gemspec
|
74
|
+
- lib/evil_scaffold.rb
|
75
|
+
- lib/evil_scaffold/create_action.rb
|
76
|
+
- lib/evil_scaffold/delete_action.rb
|
77
|
+
- lib/evil_scaffold/destroy_action.rb
|
78
|
+
- lib/evil_scaffold/edit_action.rb
|
79
|
+
- lib/evil_scaffold/finder_method.rb
|
80
|
+
- lib/evil_scaffold/goto_show_method.rb
|
81
|
+
- lib/evil_scaffold/index_action.rb
|
82
|
+
- lib/evil_scaffold/index_json.rb
|
83
|
+
- lib/evil_scaffold/new_action.rb
|
84
|
+
- lib/evil_scaffold/plugin.rb
|
85
|
+
- lib/evil_scaffold/return_appropriately_method.rb
|
86
|
+
- lib/evil_scaffold/show_action.rb
|
87
|
+
- lib/evil_scaffold/update_action.rb
|
88
|
+
- lib/evil_scaffold/version.rb
|
89
|
+
- spec/evil_scaffold_spec.rb
|
90
|
+
- spec/spec_helper.rb
|
91
|
+
homepage: http://github.com/conanite/evil_scaffold
|
92
|
+
licenses:
|
93
|
+
- MIT
|
94
|
+
metadata: {}
|
95
|
+
post_install_message:
|
96
|
+
rdoc_options: []
|
97
|
+
require_paths:
|
98
|
+
- lib
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
109
|
+
requirements: []
|
110
|
+
rubyforge_project:
|
111
|
+
rubygems_version: 2.5.2.3
|
112
|
+
signing_key:
|
113
|
+
specification_version: 4
|
114
|
+
summary: Generates mostly-unsurprising controller code at app startup so your codebase
|
115
|
+
is not cluttered with boilerplate @foo.find(params[:id]).update_attributes(params[:foo])
|
116
|
+
style code
|
117
|
+
test_files:
|
118
|
+
- spec/evil_scaffold_spec.rb
|
119
|
+
- spec/spec_helper.rb
|