cullender 0.0.1
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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +3 -0
- data/Rakefile +34 -0
- data/app/assets/javascripts/cullender/application.js +13 -0
- data/app/assets/javascripts/cullender/rules.js +46 -0
- data/app/assets/stylesheets/cullender/application.css +13 -0
- data/app/assets/stylesheets/cullender/rules.css.scss +15 -0
- data/app/controllers/cullender/rules_controller.rb +68 -0
- data/app/controllers/cullender_controller.rb +105 -0
- data/app/helpers/cullender/rules_helper.rb +136 -0
- data/app/models/cullender/rule.rb +204 -0
- data/app/views/cullender/rules/_form.html.erb +20 -0
- data/app/views/cullender/rules/_trigger_fields.html.erb +19 -0
- data/app/views/cullender/rules/create.js.erb +3 -0
- data/app/views/cullender/rules/index.html.erb +25 -0
- data/app/views/cullender/rules/new.html.erb +1 -0
- data/app/views/cullender/rules/show.html.erb +3 -0
- data/config/locales/en.yml +12 -0
- data/config/routes.rb +4 -0
- data/lib/cullender.rb +96 -0
- data/lib/cullender/controllers/filter_logic.rb +89 -0
- data/lib/cullender/controllers/scoped_views.rb +17 -0
- data/lib/cullender/core_ext/hash.rb +1 -0
- data/lib/cullender/core_ext/hash/deep_delete.rb +13 -0
- data/lib/cullender/engine.rb +15 -0
- data/lib/cullender/engine/routes.rb +306 -0
- data/lib/cullender/mapping.rb +139 -0
- data/lib/cullender/version.rb +3 -0
- data/lib/generators/cullender/cullender_generator.rb +66 -0
- data/lib/generators/cullender/install_generator.rb +18 -0
- data/lib/generators/cullender/orm_helpers.rb +32 -0
- data/lib/generators/cullender/templates/cullender.rb +3 -0
- data/lib/generators/cullender/templates/cullender_migration.rb +13 -0
- data/lib/tasks/cullender_tasks.rake +4 -0
- data/spec/controllers/cullender/rules_controller_spec.rb +180 -0
- data/spec/cullender/controllers/filter_logic_spec.rb +233 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/javascripts/application.js +17 -0
- data/spec/dummy/app/assets/stylesheets/application.css +14 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/controllers/events_controller.rb +60 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/models/event.rb +16 -0
- data/spec/dummy/app/views/cullender/rules/_form.html.erb +33 -0
- data/spec/dummy/app/views/cullender/rules/index.html.erb +24 -0
- data/spec/dummy/app/views/cullender/rules/new.html.erb +1 -0
- data/spec/dummy/app/views/cullender/rules/show.html.erb +3 -0
- data/spec/dummy/app/views/events/_form.html.erb +21 -0
- data/spec/dummy/app/views/events/edit.html.erb +6 -0
- data/spec/dummy/app/views/events/index.html.erb +27 -0
- data/spec/dummy/app/views/events/new.html.erb +5 -0
- data/spec/dummy/app/views/events/show.html.erb +10 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +23 -0
- data/spec/dummy/config/boot.rb +9 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +27 -0
- data/spec/dummy/config/environments/production.rb +80 -0
- data/spec/dummy/config/environments/test.rb +36 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cullender.rb +3 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +12 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/cullender.en.yml +12 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +5 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/migrate/123344556676_create_cullender_tables.rb +12 -0
- data/spec/dummy/db/schema.rb +24 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/development.log +9987 -0
- data/spec/dummy/log/test.log +19786 -0
- data/spec/dummy/public/404.html +27 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +26 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/268a828ee4997cf5c19106e5f00fcfb8 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/56b2eb9b46b9aca7e86b5132ddf0d9de +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/750887406b3e8dacb2b03f986330932d +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/750b42e431d194c41f5b1cde4a257e47 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/921642fe740290e9e5e88a706e5a562c +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/a967ed3fc5f8406f3ff72180775f1b40 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/ae74bf4fc3fd20e7f7b98860b8ef0f74 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/c7dbd1f5acc2d5bc078363f4f3c70c54 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/d995daf8d6f36c27b6e9d1b4672eaf1e +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
- data/spec/helpers/cullender/rules_helper_spec.rb +360 -0
- data/spec/models/cullender/rule_spec.rb +425 -0
- data/spec/requests/rules_spec.rb +19 -0
- data/spec/spec_helper.rb +60 -0
- metadata +319 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 84cd07f131f0613540f841cfd74fd0d99080ecf5
|
|
4
|
+
data.tar.gz: b6c36dd6ba6f2bf5d51a5682c1f0a2ff2b263760
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 60085f0fc2e0fc7bd4400f4928c14b861b5dde3b3beb38d26c39c3e8900aa4de1a3fbf53a439798376142b4692322429e2d432c9e8641aa62a0aef07d9f1bf48
|
|
7
|
+
data.tar.gz: be7c775c08cf93465cf4fa2cd8f43618bd6030d670a0acf14b005331b4c76d7abadf210f8b6a9bc24c5080985d6a7acef97d48326d1047cf3a9e3c76876db764
|
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright 2013 YOURNAME
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
data/Rakefile
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require 'bundler/setup'
|
|
3
|
+
rescue LoadError
|
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
require 'rdoc/task'
|
|
8
|
+
|
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
11
|
+
rdoc.title = 'Cullender'
|
|
12
|
+
rdoc.options << '--line-numbers'
|
|
13
|
+
rdoc.rdoc_files.include('README.rdoc')
|
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
|
18
|
+
load 'rails/tasks/engine.rake'
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
Bundler::GemHelper.install_tasks
|
|
23
|
+
|
|
24
|
+
require 'rake/testtask'
|
|
25
|
+
|
|
26
|
+
Rake::TestTask.new(:test) do |t|
|
|
27
|
+
t.libs << 'lib'
|
|
28
|
+
t.libs << 'spec'
|
|
29
|
+
t.pattern = 'spec/**/*_spec.rb'
|
|
30
|
+
t.verbose = false
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
task default: :test
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
|
2
|
+
// listed below.
|
|
3
|
+
//
|
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
|
5
|
+
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
|
|
6
|
+
//
|
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
|
8
|
+
// compiled file.
|
|
9
|
+
//
|
|
10
|
+
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
|
|
11
|
+
// GO AFTER THE REQUIRES BELOW.
|
|
12
|
+
//
|
|
13
|
+
//= require_tree .
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// # Place all the behaviors and hooks related to the matching controller here.
|
|
2
|
+
// # All this logic will automatically be available in application.js.
|
|
3
|
+
// # You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
|
|
4
|
+
// # check if there are any rules that have already been applied
|
|
5
|
+
// # if rules have been defined then check if the user is ok if we remove remove them from the form
|
|
6
|
+
//
|
|
7
|
+
// jQuery ->
|
|
8
|
+
// columns = $('#or_raise_field').html()
|
|
9
|
+
// table = $('#rule_table_id :selected').text()
|
|
10
|
+
// escaped_table = table.replace(/([ #;&,.+*~\':"!^$[\]()=>|\/@])/g, '\\$1')
|
|
11
|
+
// options = $(columns).filter("optgroup[label=#{escaped_table}]").html()
|
|
12
|
+
// $('#triggers').hide() unless options
|
|
13
|
+
// $('#rule_table_id').change ->
|
|
14
|
+
// table = $('#rule_table_id :selected').text()
|
|
15
|
+
// escaped_table = table.replace(/([ #;&,.+*~\':"!^$[\]()=>|\/@])/g, '\\$1')
|
|
16
|
+
// options = $(columns).filter("optgroup[label=#{escaped_table}]").html()
|
|
17
|
+
// if options
|
|
18
|
+
// $('.column_select_field').html(options)
|
|
19
|
+
// $('#triggers').show()
|
|
20
|
+
// else
|
|
21
|
+
// $('.column_select_field').empty()
|
|
22
|
+
// $('#triggers').hide()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
// jQuery(function() {
|
|
26
|
+
// var columns;
|
|
27
|
+
// columns = $('#or_raise_field').html();
|
|
28
|
+
// populate_rule_column_options();
|
|
29
|
+
// $('#rule_table_id').change(populate_rule_column_options);
|
|
30
|
+
|
|
31
|
+
// function populate_rule_column_options(){
|
|
32
|
+
// var escaped_table, options, table;
|
|
33
|
+
// table = $('#rule_table_id :selected').text();
|
|
34
|
+
// escaped_table = table.replace(/([ #;&,.+*~\':"!^$[\]()=>|\/@])/g, '\\$1');
|
|
35
|
+
// options = $(columns).filter("optgroup[label=" + escaped_table + "]").html();
|
|
36
|
+
// if (options) {
|
|
37
|
+
// $('.column_select_field').html(options);
|
|
38
|
+
// return $('#triggers').show();
|
|
39
|
+
// } else {
|
|
40
|
+
// $('.column_select_field').empty();
|
|
41
|
+
// return $('#triggers').hide();
|
|
42
|
+
// }
|
|
43
|
+
// }
|
|
44
|
+
// });
|
|
45
|
+
|
|
46
|
+
// TODO javascript without rails ujs
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
|
3
|
+
* listed below.
|
|
4
|
+
*
|
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
|
6
|
+
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
|
|
7
|
+
*
|
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the top of the
|
|
9
|
+
* compiled file, but it's generally better to create a new file per style scope.
|
|
10
|
+
*
|
|
11
|
+
*= require_self
|
|
12
|
+
*= require_tree .
|
|
13
|
+
*/
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Place all the styles related to the rules controller here.
|
|
2
|
+
// They will automatically be included in application.css.
|
|
3
|
+
// You can use Sass (SCSS) here: http://sass-lang.com/
|
|
4
|
+
#rules {
|
|
5
|
+
table{
|
|
6
|
+
td{
|
|
7
|
+
vertical-align:middle;
|
|
8
|
+
}
|
|
9
|
+
.action{
|
|
10
|
+
i{
|
|
11
|
+
margin-right:5px;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
module Cullender
|
|
2
|
+
class RulesController < CullenderController
|
|
3
|
+
before_action :set_rule, only: [:show, :edit, :update, :destroy]
|
|
4
|
+
include Controllers::FilterLogic
|
|
5
|
+
|
|
6
|
+
# TODO should route without resource. ie not event/rules just /rules
|
|
7
|
+
# GET /rules
|
|
8
|
+
def index
|
|
9
|
+
@rules = Cullender::Rule.all
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# GET /rules/1
|
|
13
|
+
def show
|
|
14
|
+
params.deep_merge!({"rule" => {"triggers" => @rule.triggers}})
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# GET /rules/new
|
|
18
|
+
def new
|
|
19
|
+
@rule = Cullender::Rule.new(name: params[:name])
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# POST /rules
|
|
23
|
+
def create
|
|
24
|
+
flag = apply_filter_actions("triggers", params[:rule], params)
|
|
25
|
+
@rule = Cullender::Rule.new(rule_params)
|
|
26
|
+
respond_to do |format|
|
|
27
|
+
if flag
|
|
28
|
+
format.html {redirect_to send("new_#{resource_name}_rule_url".to_sym,params[:rule])}
|
|
29
|
+
format.js { render "create"}
|
|
30
|
+
else
|
|
31
|
+
if @rule.save
|
|
32
|
+
format.html {redirect_to send("#{resource_name}_rules_url".to_sym), notice: 'Rule was successfully created.'}
|
|
33
|
+
format.js {redirect_to send("#{resource_name}_rules_url".to_sym), notice: 'Rule was successfully created.'}
|
|
34
|
+
else
|
|
35
|
+
format.html {render action: 'new'}
|
|
36
|
+
format.js {render action: 'new'}
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# PATCH/PUT /rules/1
|
|
43
|
+
def update
|
|
44
|
+
if !apply_filter_actions("triggers", params[:rule], params) && @rule.update_attributes(rule_params)
|
|
45
|
+
redirect_to send("#{resource_name}_rules_url".to_sym), notice: 'Rule was successfully updated.'
|
|
46
|
+
else
|
|
47
|
+
render action: 'show'
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# DELETE /rules/1
|
|
52
|
+
def destroy
|
|
53
|
+
@rule.destroy
|
|
54
|
+
redirect_to send("#{resource_name}_rules_url".to_sym), notice: 'Rule was successfully destroyed.'
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
# Use callbacks to share common setup or constraints between actions.
|
|
59
|
+
def set_rule
|
|
60
|
+
@rule = Cullender::Rule.find(params[:id])
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Never trust parameters from the scary internet, only allow the white list through.
|
|
64
|
+
def rule_params
|
|
65
|
+
params.require(:rule).permit!#(:name, :triggers => {})
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# All Cullender controllers are inherited from here.
|
|
2
|
+
class CullenderController < Cullender.parent_controller.constantize
|
|
3
|
+
include Cullender::Controllers::ScopedViews
|
|
4
|
+
|
|
5
|
+
helpers = %w(resource scope_name resource_name
|
|
6
|
+
resource_class resource_params cullender_mapping)
|
|
7
|
+
hide_action *helpers
|
|
8
|
+
helper_method *helpers
|
|
9
|
+
|
|
10
|
+
prepend_before_filter :assert_is_cullender_resource!
|
|
11
|
+
respond_to *Mime::SET.map(&:to_sym) if mimes_for_respond_to.empty?
|
|
12
|
+
|
|
13
|
+
# Gets the actual resource stored in the instance variable
|
|
14
|
+
def resource
|
|
15
|
+
instance_variable_get(:"@#{resource_name}")
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Proxy to cullender map name
|
|
19
|
+
def resource_name
|
|
20
|
+
cullender_mapping.name
|
|
21
|
+
end
|
|
22
|
+
alias :scope_name :resource_name
|
|
23
|
+
|
|
24
|
+
# Proxy to cullender map class
|
|
25
|
+
def resource_class
|
|
26
|
+
cullender_mapping.to
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def resource_params
|
|
30
|
+
params[resource_name]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Attempt to find the mapped route for cullender based on request path
|
|
34
|
+
def cullender_mapping
|
|
35
|
+
@cullender_mapping ||= request.env["cullender.mapping"]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Override prefixes to consider the scoped view.
|
|
39
|
+
# Notice we need to check for the request due to a bug in
|
|
40
|
+
# Action Controller tests that forces _prefixes to be
|
|
41
|
+
# loaded before even having a request object.
|
|
42
|
+
def _prefixes #:nodoc:
|
|
43
|
+
@_prefixes ||= if self.class.scoped_views? && request && cullender_mapping
|
|
44
|
+
super.unshift("#{cullender_mapping.scoped_path}/#{controller_name}")
|
|
45
|
+
else
|
|
46
|
+
super
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
hide_action :_prefixes
|
|
51
|
+
|
|
52
|
+
protected
|
|
53
|
+
|
|
54
|
+
# Checks whether it's a cullender mapped resource or not.
|
|
55
|
+
def assert_is_cullender_resource! #:nodoc:
|
|
56
|
+
unknown_action! <<-MESSAGE unless cullender_mapping
|
|
57
|
+
Could not find cullender mapping for path #{request.fullpath.inspect}.
|
|
58
|
+
This may happen for two reasons:
|
|
59
|
+
|
|
60
|
+
1) You forgot to wrap your route inside the scope block. For example:
|
|
61
|
+
|
|
62
|
+
cullender_scope :user do
|
|
63
|
+
match "/some/route" => "some_cullender_controller"
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
2) You are testing a Cullender controller bypassing the router.
|
|
67
|
+
If so, you can explicitly tell Cullender which mapping to use:
|
|
68
|
+
|
|
69
|
+
@request.env["cullender.mapping"] = Cullender.mappings[:user]
|
|
70
|
+
|
|
71
|
+
MESSAGE
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Returns real navigational formats which are supported by Rails
|
|
75
|
+
def navigational_formats
|
|
76
|
+
@navigational_formats ||= Cullender.navigational_formats.select { |format| Mime::EXTENSION_LOOKUP[format.to_s] }
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def unknown_action!(msg)
|
|
80
|
+
logger.debug "[Cullender] #{msg}" if logger
|
|
81
|
+
raise AbstractController::ActionNotFound, msg
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Sets the resource creating an instance variable
|
|
85
|
+
def resource=(new_resource)
|
|
86
|
+
instance_variable_set(:"@#{resource_name}", new_resource)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Build a cullender resource.
|
|
90
|
+
# Assignment bypasses attribute protection when :unsafe option is passed
|
|
91
|
+
def build_resource(hash = nil, options = {})
|
|
92
|
+
hash ||= resource_params || {}
|
|
93
|
+
|
|
94
|
+
if options[:unsafe]
|
|
95
|
+
self.resource = resource_class.new.tap do |resource|
|
|
96
|
+
hash.each do |key, value|
|
|
97
|
+
setter = :"#{key}="
|
|
98
|
+
resource.send(setter, value) if resource.respond_to?(setter)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
else
|
|
102
|
+
self.resource = resource_class.new(hash)
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
module Cullender
|
|
2
|
+
module RulesHelper
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def render_property_tree(name, mapping, hash, options = {}, hierarchy = [], &block)
|
|
6
|
+
options.merge!(:class => "group level_#{hierarchy.length}")
|
|
7
|
+
last_key = hash.keys.last
|
|
8
|
+
html = content_tag :div, options do
|
|
9
|
+
hash.each do |field, value|
|
|
10
|
+
if value.keys.include?("o")
|
|
11
|
+
property_options = mapping.has_key?(field) ? mapping[field] : {}
|
|
12
|
+
block.call property_item(name, field, property_options, value, hierarchy), last_key == field ? 1 : -1, hierarchy
|
|
13
|
+
else
|
|
14
|
+
hierarchy.push(field)
|
|
15
|
+
block.call render_property_tree(name, mapping, value, {}, hierarchy, &block), last_key == field ? 0 : -1, hierarchy
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end if hash.present?
|
|
19
|
+
hierarchy.pop
|
|
20
|
+
html
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def extract_field_type(options)
|
|
24
|
+
options.has_key?(:type) && Cullender::Rule::FIELD_TYPE_MAP.has_key?(options[:type]) ? Cullender::Rule::FIELD_TYPE_MAP[options[:type]] : "text_field"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# type = Event.property_types.has_key?(field) ? Event.property_types[field] : "string" #Event::FIELDTYPE_MAP[column.datatype]
|
|
28
|
+
def property_item(name, field, options, value_hash = {}, hierarchy = [])
|
|
29
|
+
fieldtype = extract_field_type(options)
|
|
30
|
+
prefix = nested_property_prefix(hierarchy, name)
|
|
31
|
+
operator = value_hash['o'] || nil
|
|
32
|
+
value = value_hash['v'] || nil
|
|
33
|
+
content_tag :div, :class => "item #{field.to_s.parameterize}" do
|
|
34
|
+
submit_tag("-", :name => "remove#{nested_property_prefix(hierarchy, "")}[#{field}]", :class => 'btn') +
|
|
35
|
+
label_tag(field, field, {:for => "#{prefix}[#{field}][v]"}) +
|
|
36
|
+
select_tag( "#{prefix}[#{field}][o]", options_for_select(Cullender::Rule::OPERATORS[fieldtype], operator), :class => "operator") +
|
|
37
|
+
property_value_field(field, fieldtype, value, options, prefix)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def link_to_filter(attribute, value, options = {})
|
|
42
|
+
copy_of_params = deep_clone(params)
|
|
43
|
+
copy_of_params.deep_merge!({:filter => {attribute.to_sym => {"v" => value}}})
|
|
44
|
+
link_to_unless( params.has_key?(:filter) && params[:filter].has_key?(attribute), value, copy_of_params, options)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def link_to_remove_filter(attribute, value, options = {})
|
|
48
|
+
condition = params.has_key?(:filter) && params[:filter].has_key?(attribute.to_s) && params[:filter][attribute.to_s]['v'].to_s == value.to_s
|
|
49
|
+
copy_of_params = deep_clone(params)
|
|
50
|
+
copy_of_params[:filter].delete(attribute)
|
|
51
|
+
link_to( text_with_close_btn("#{attribute}=#{value}"), copy_of_params, options)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def remove_filter_link(attribute, value, count, options = {})
|
|
55
|
+
copy_of_params = deep_clone(params)
|
|
56
|
+
if params.has_key?(:filter) && params[:filter].has_key?(attribute.to_s) && params[:filter][attribute.to_s]['v'].to_s == value.to_s
|
|
57
|
+
copy_of_params[:filter].delete(attribute.to_s)
|
|
58
|
+
link_to "remove", copy_of_params, options
|
|
59
|
+
else
|
|
60
|
+
content_tag(:span, count, options)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def cullender_collection_or_select(collection, hierarchy = [], options = {})
|
|
65
|
+
is_base = options.delete(:base)
|
|
66
|
+
prefix = nested_property_prefix(hierarchy)
|
|
67
|
+
content_tag :div, :class => "add_group" do
|
|
68
|
+
select_tag( "or[#{"raise_" if is_base}field]#{prefix}", options_for_select(collection), :class => "column_select_field") +
|
|
69
|
+
submit_tag("OR", :name => "or#{is_base ? "[raise]" : "[commit]"}#{prefix}", :class => 'btn')
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def cullender_collection_and_select(collection, hierarchy = [], options = {})
|
|
75
|
+
prefix = nested_property_prefix(hierarchy)
|
|
76
|
+
content_tag :div, :class => "add_filter" do
|
|
77
|
+
select_tag( "and[field]#{prefix}", options_for_select(collection), :class => "column_select_field") +
|
|
78
|
+
submit_tag("AND", :name => "and[commit]#{prefix}", :class => 'btn')
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def extract_triggers(params)
|
|
83
|
+
if params.has_key?("triggers")
|
|
84
|
+
params["triggers"]
|
|
85
|
+
elsif params.has_key?("rule") && params["rule"].has_key?("triggers")
|
|
86
|
+
params["rule"]["triggers"]
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def property_value_field(field, type, value = nil, options = {}, prefix = '')
|
|
92
|
+
default = options.delete(:default)
|
|
93
|
+
case type
|
|
94
|
+
when "number_field", "range_field", "text_field", "check_box"
|
|
95
|
+
send("#{type}_tag".to_sym, "#{prefix}[#{field}][v]", value, {:class => "value"} )
|
|
96
|
+
when "select"
|
|
97
|
+
select_tag("#{prefix}[#{field}][v]", options_for_select({}, value), {:class => "value"})
|
|
98
|
+
when "datetime"
|
|
99
|
+
select_datetime set_datetime(value, default), {:class => "value", :prefix => "#{prefix}[#{field}][v]"}
|
|
100
|
+
when "date"
|
|
101
|
+
select_date set_date(value, default), {:class => "value", :prefix => "#{prefix}[#{field}][v]"}
|
|
102
|
+
else #this includes Event::TEXT and any other field type
|
|
103
|
+
text_field_tag "#{prefix}[#{field}][v]", value, {:class => "value"}
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def filter_to_s(key, value)
|
|
109
|
+
"#{key} #{Rule::FILTER_MAP[value["o"]]} #{value["v"]}" if value.has_key?("o") && value.has_key?("v")
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# nest is an array of values of the hierarchy
|
|
113
|
+
def nested_property_prefix(hierarchy, prefix = nil)
|
|
114
|
+
"#{prefix}#{hierarchy.inject("") {|result, item| result += "[#{item}]"}}"
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def formatted_triggers(hash)
|
|
118
|
+
ands = []
|
|
119
|
+
ors = []
|
|
120
|
+
hash.each do |key, value|
|
|
121
|
+
if value.keys.include?("o")
|
|
122
|
+
ands << filter_to_s(key, value)
|
|
123
|
+
else
|
|
124
|
+
ors << formatted_triggers(value)
|
|
125
|
+
end
|
|
126
|
+
end if hash.present?
|
|
127
|
+
ors.empty? ? "("+ ands.join(" AND ") + ")" : "(" + ors.join(" OR ") + ")"
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
private
|
|
131
|
+
|
|
132
|
+
def deep_clone(obj)
|
|
133
|
+
Marshal.load(Marshal.dump(obj))
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|