dynamic_query 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE.txt ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2012 Wei-Ming Wu
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License"); you
4
+ may not use this file except in compliance with the License. You may
5
+ obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12
+ implied. See the License for the specific language governing
13
+ permissions and limitations under the License.
data/README.md ADDED
@@ -0,0 +1,19 @@
1
+ = dynamic_query
2
+
3
+ Description goes here.
4
+
5
+ == Contributing to dynamic_query
6
+
7
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
8
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
9
+ * Fork the project.
10
+ * Start a feature/bugfix branch.
11
+ * Commit and push until you are happy with your contribution.
12
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
13
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2012 Wei-Ming Wu. See LICENSE.txt for
18
+ further details.
19
+
data/Rakefile ADDED
@@ -0,0 +1,57 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ require './lib/dynamic_query/version.rb'
6
+
7
+ begin
8
+ Bundler.setup(:default, :development)
9
+ rescue Bundler::BundlerError => e
10
+ $stderr.puts e.message
11
+ $stderr.puts "Run `bundle install` to install missing gems"
12
+ exit e.status_code
13
+ end
14
+ require 'rake'
15
+
16
+ require 'jeweler'
17
+ Jeweler::Tasks.new do |gem|
18
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
19
+ gem.version = DynamicQuery::Version::STRING
20
+ gem.name = "dynamic_query"
21
+ gem.homepage = "http://github.com/wnameless/dynamic_query"
22
+ gem.license = "Apache License, Version 2.0"
23
+ gem.summary = "dynamic_query-#{gem.version}"
24
+ gem.description = %Q{A dynamic query gui for ActiveRecord}
25
+ gem.email = "wnameless@gmail.com"
26
+ gem.authors = ["Wei-Ming Wu"]
27
+ # dependencies defined in Gemfile
28
+ gem.files = Dir["{app,lib}/**/*"] + ["LICENSE.txt", "Rakefile", "README.md"]
29
+ end
30
+ Jeweler::RubygemsDotOrgTasks.new
31
+
32
+ require 'rake/testtask'
33
+ Rake::TestTask.new(:test) do |test|
34
+ test.libs << 'lib' << 'test'
35
+ test.pattern = 'test/**/test_*.rb'
36
+ test.verbose = true
37
+ end
38
+
39
+ require 'rcov/rcovtask'
40
+ Rcov::RcovTask.new do |test|
41
+ test.libs << 'test'
42
+ test.pattern = 'test/**/test_*.rb'
43
+ test.verbose = true
44
+ test.rcov_opts << '--exclude "gems/*"'
45
+ end
46
+
47
+ task :default => :test
48
+
49
+ require 'rdoc/task'
50
+ Rake::RDocTask.new do |rdoc|
51
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
52
+
53
+ rdoc.rdoc_dir = 'rdoc'
54
+ rdoc.title = "dynamic_query #{version}"
55
+ rdoc.rdoc_files.include('README*')
56
+ rdoc.rdoc_files.include('lib/**/*.rb')
57
+ end
@@ -0,0 +1,16 @@
1
+ $('.query_op').live('change', function() {
2
+ var _ref, _ref1;
3
+ if ((_ref = $(this).val()) === 'IS NULL' || _ref === 'IS NOT NULL') {
4
+ $('#' + $(this).attr('id').split(/_/).slice(0, -1).join('_') + '_value1').val('');
5
+ $('#' + $(this).attr('id').split(/_/).slice(0, -1).join('_') + '_value2').val('');
6
+ $('#' + $(this).attr('id').split(/_/).slice(0, -1).join('_') + '_value1').hide();
7
+ return $('#' + $(this).attr('id').split(/_/).slice(0, -1).join('_') + '_value2').hide();
8
+ } else if ((_ref1 = $(this).val()) === 'BETWEEN' || _ref1 === 'NOT BETWEEN') {
9
+ $('#' + $(this).attr('id').split(/_/).slice(0, -1).join('_') + '_value1').show();
10
+ return $('#' + $(this).attr('id').split(/_/).slice(0, -1).join('_') + '_value2').show();
11
+ } else {
12
+ $('#' + $(this).attr('id').split(/_/).slice(0, -1).join('_') + '_value1').show();
13
+ $('#' + $(this).attr('id').split(/_/).slice(0, -1).join('_') + '_value2').val('');
14
+ return $('#' + $(this).attr('id').split(/_/).slice(0, -1).join('_') + '_value2').hide();
15
+ }
16
+ });
@@ -0,0 +1,172 @@
1
+ require 'dynamic_query/railtie' if defined?(Rails)
2
+
3
+ module DynamicQuery
4
+ OPERATOR = ['=', '>', '>=', '<', '<=', '!=',
5
+ 'LIKE', 'NOT LIKE', 'IN', 'NOT IN',
6
+ 'BETWEEN', 'NOT BETWEEN', 'IS NULL', 'IS NOT NULL']
7
+
8
+ def dynamic_query(*models, opt)
9
+ DynamicQueryInstance.new(*models, opt)
10
+ end
11
+
12
+ class DynamicQueryInstance
13
+
14
+ def initialize(*models, opt)
15
+ @reveal_keys = false
16
+ @white_list = []
17
+ @black_list = []
18
+
19
+ if opt.kind_of?(Array)
20
+ models = models + opt
21
+ opt = {}
22
+ end
23
+
24
+ unless opt.kind_of?(Hash)
25
+ models << opt
26
+ opt = {}
27
+ end
28
+
29
+ opt.each do |key, val|
30
+ @reveal_keys = true if key == :reveal_keys && val
31
+
32
+ if key == :accept
33
+ val.each do |model, columns|
34
+ if models.include?(model)
35
+ model = model.to_s.split(/_/).map { |word| word.capitalize }.join.constantize
36
+ columns.each { |col| @white_list << "#{model.table_name}.#{col}" }
37
+ end
38
+ end
39
+ end
40
+
41
+ if key == :reject
42
+ val.each do |model, columns|
43
+ if models.include?(model)
44
+ model = model.to_s.split(/_/).map { |word| word.capitalize }.join.constantize
45
+ columns.each { |col| @black_list << "#{model.table_name}.#{col}" }
46
+ end
47
+ end
48
+ end
49
+ end if opt.kind_of?(Hash)
50
+
51
+ @columns = {}
52
+ models.each do |model|
53
+ model = model.to_s.split(/_/).map { |word| word.capitalize }.join.constantize
54
+ model = model.columns.map { |col| { "#{model.table_name}.#{col.name}" => col.type } }.reduce(:merge)
55
+ @columns.merge!(model)
56
+ end
57
+
58
+ unless @reveal_keys
59
+ @columns.keys.each do |key|
60
+ @columns.delete(key) if key =~ /.id$/ || key =~ /_id$/
61
+ end
62
+ end
63
+
64
+ unless @white_list.empty?
65
+ selected_columns = {}
66
+ @white_list.each do |white|
67
+ selected_columns[white] = @columns[white] if @columns.keys.include?(white)
68
+ end
69
+ @columns = selected_columns
70
+ end
71
+
72
+ @black_list.each { |black| @columns.delete(black) }
73
+ end
74
+
75
+ def panel(query)
76
+ query ||= { 'or_1' => { 'and_1' => { :column => '', :operator => '', :value1 => '', :value2 => '' } } }
77
+ add_and_condition(query)
78
+ add_or_condition(query)
79
+ remove_and_condition(query)
80
+ remove_or_condition(query)
81
+ query[:columns] = @columns
82
+ query
83
+ end
84
+
85
+ def statement(query)
86
+ query ||= { 'or_1' => { 'and_1' => { :column => '', :operator => '', :value1 => '', :value2 => '' } } }
87
+ or_stat = []
88
+ query.select { |k, _| k =~ /^or_\d+$/ }.each do |or_key, or_val|
89
+ and_stat = []
90
+ or_val.each do |and_key, and_val|
91
+ case and_val[:operator]
92
+ when '=', '>', '>=', '<', '<=', '!=', 'LIKE', 'NOT LIKE'
93
+ and_stat << "#{and_val[:column]} #{and_val[:operator]} '#{and_val[:value1]}'" unless and_val[:value1].blank?
94
+ when 'IN', 'NOT IN'
95
+ and_stat << "#{and_val[:column]} #{and_val[:operator]} (#{and_val[:value1].split(/,/).select { |word| !word.strip.empty? }.map { |word| "'" + word.strip + "'" }.join(',')})" unless and_val[:value1].delete(',').blank?
96
+ when 'BETWEEN', 'NOT BETWEEN'
97
+ and_stat << "#{and_val[:column]} #{and_val[:operator]} '#{and_val[:value1]}' AND '#{and_val[:value2]}'" unless and_val[:value1].blank? || and_val[:value2].blank?
98
+ when 'IS NULL', 'IS NOT NULL'
99
+ and_stat << "#{and_val[:column]} #{and_val[:operator]}"
100
+ end
101
+ end
102
+
103
+ and_stat_str = and_stat.join(' AND ')
104
+ or_stat << "(#{and_stat_str})" unless and_stat_str.empty?
105
+ end
106
+
107
+ or_stat = or_stat.join(' OR ')
108
+ end
109
+
110
+
111
+ private
112
+
113
+
114
+ def remove_or_condition(query)
115
+ query.each do |key, val|
116
+ if key =~ /^remove_or_\d+$/
117
+ query.delete("or_#{key.match(/\d+/)[0]}")
118
+ break
119
+ end
120
+ end
121
+ end
122
+
123
+ def remove_and_condition(query)
124
+ query.each do |key, val|
125
+ if key =~ /^or_\d+-and_\d+$/
126
+ query["or_#{key.scan(/\d+/)[0]}"].delete("and_#{key.scan(/\d+/)[1]}")
127
+ break
128
+ end
129
+ end
130
+ end
131
+
132
+ def add_or_condition(query)
133
+ or_key = nil
134
+
135
+ query.each do |key, val|
136
+ if key =~ /^add_or$/
137
+ or_key = get_new_or_condition_key(query)
138
+ break
139
+ end
140
+ end
141
+
142
+ if or_key
143
+ query[or_key] = {}
144
+ query[or_key]['and_1'] = { :column => '', :operator => '', :value1 => '', :value2 => '' }
145
+ end
146
+ end
147
+
148
+
149
+ def add_and_condition(query)
150
+ query.each do |key, val|
151
+ if key =~ /^or_\d+-and$/
152
+ and_key = get_new_and_condition_key(query["or_#{key.match(/\d+/)[0]}"])
153
+ query["or_#{key.match(/\d+/)[0]}"][and_key] = { :column => '', :operator => '', :value1 => '', :value2 => '' }
154
+ break
155
+ end
156
+ end
157
+ end
158
+
159
+ def get_new_or_condition_key(query)
160
+ count = query.keys.select { |i| i =~ /\d+$/ }.map { |key| key.match(/\d+/)[0].to_i }.max.to_i + 1
161
+ p count
162
+ "or_#{count}"
163
+ end
164
+
165
+ def get_new_and_condition_key(or_condition)
166
+ count = or_condition.keys.map { |key| key.match(/\d+/)[0].to_i }.max.to_i + 1
167
+ "and_#{count}"
168
+ end
169
+
170
+ end
171
+
172
+ end
@@ -0,0 +1,39 @@
1
+ <%= form_tag(request.url, opt.merge(:style => 'text-align: center;')) %>
2
+ <% if panel %>
3
+ <table style="margin-left: auto; margin-right: auto;">
4
+ <% panel.select { |k, _| k =~ /^or_\d+$/ }.each_with_index do |(or_key, or_val), idx1| %>
5
+ <% or_val.each_with_index do |(and_key, and_val), idx2| %>
6
+ <tr>
7
+ <td>
8
+ <%= submit_tag '∇', :name => "query[add_or]", :style => 'color: purple;' if idx1 == 0 && idx2 == 0 %>
9
+ <%= submit_tag '-', :name => "query[remove_#{or_key}]", :style => 'color: red;' if idx1 != 0 && idx2 == 0 %>
10
+ </td>
11
+ <td><%= select_tag "query[#{or_key}][#{and_key}][column]", options_for_select(panel[:columns].keys, and_val[:column]) %></td>
12
+ <td><%= select_tag "query[#{or_key}][#{and_key}][operator]", options_for_select(OPERATOR, and_val[:operator]), :class => 'query_op' %></td>
13
+ <td>
14
+ <% if ['IS NULL', 'IS NOT NULL'].include? and_val[:operator] %>
15
+ <%= text_field_tag "query[#{or_key}][#{and_key}][value1]", '', :style => 'display: none;' %>
16
+ <% else %>
17
+ <%= text_field_tag "query[#{or_key}][#{and_key}][value1]", and_val[:value1] %>
18
+ <% end %>
19
+ </td>
20
+ <td>
21
+ <% if ['BETWEEN', 'NOT BETWEEN'].include? and_val[:operator] %>
22
+ <%= text_field_tag "query[#{or_key}][#{and_key}][value2]", and_val[:value2] %>
23
+ <% else %>
24
+ <%= text_field_tag "query[#{or_key}][#{and_key}][value2]", '', :style => 'display: none;' %>
25
+ <% end %>
26
+ </td>
27
+ <td>
28
+ <%= submit_tag '+', :name => "query[#{or_key}-and]", :style => 'color: blue;' if idx2 == 0 %>
29
+ <%= submit_tag 'x', :name => "query[#{or_key}-#{and_key}]", :style => 'color: green;' if idx2 != 0 %>
30
+ </td>
31
+ </tr>
32
+ <% end %>
33
+ <tr style="height: 10px;"></tr>
34
+ <% end %>
35
+ <% end %>
36
+ </table>
37
+ <br />
38
+ <%= submit_tag 'Query', :style => 'width: 150px;'%>
39
+ </form>
@@ -0,0 +1,13 @@
1
+ module DynamicQuery
2
+
3
+ module Helper
4
+
5
+ def dynamic_query(panel, opt = {})
6
+ template = ERB.new(File.read(File.dirname(__FILE__) + '/dynamic_query.erb'))
7
+ content = template.result(binding)
8
+ content.html_safe
9
+ end
10
+
11
+ end
12
+
13
+ end
@@ -0,0 +1,17 @@
1
+ require 'dynamic_query/helper'
2
+
3
+ module DynamicQuery
4
+
5
+ class Railtie < Rails::Railtie
6
+
7
+ initializer "dynamic_query" do
8
+ ActionController::Base.send :include, DynamicQuery
9
+ end
10
+
11
+ initializer "dynamic_query.helper" do
12
+ ActionView::Base.send :include, Helper
13
+ end
14
+
15
+ end
16
+
17
+ end
@@ -0,0 +1,11 @@
1
+ class DynamicQuery
2
+
3
+ module Version
4
+ MAJOR = 0
5
+ MINOR = 1
6
+ PATCH = 0
7
+
8
+ STRING = [MAJOR, MINOR, PATCH].compact.join('.')
9
+ end
10
+
11
+ end
@@ -0,0 +1,10 @@
1
+ require 'rails/generators'
2
+
3
+ class DynamicQueryGenerator < Rails::Generators::Base
4
+ source_root File.expand_path("../../../", __FILE__)
5
+
6
+ def manifest
7
+ copy_file "app/assets/javascripts/dynamic_query.js", "app/assets/javascripts/dynamic_query.js"
8
+ end
9
+
10
+ end
metadata ADDED
@@ -0,0 +1,156 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dynamic_query
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Wei-Ming Wu
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-10-20 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: shoulda
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rdoc
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '3.12'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '3.12'
62
+ - !ruby/object:Gem::Dependency
63
+ name: bundler
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: 1.0.0
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: 1.0.0
78
+ - !ruby/object:Gem::Dependency
79
+ name: jeweler
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: 1.8.4
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: 1.8.4
94
+ - !ruby/object:Gem::Dependency
95
+ name: rcov
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ~>
100
+ - !ruby/object:Gem::Version
101
+ version: 0.9.11
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: 0.9.11
110
+ description: A dynamic query gui for ActiveRecord
111
+ email: wnameless@gmail.com
112
+ executables: []
113
+ extensions: []
114
+ extra_rdoc_files:
115
+ - LICENSE.txt
116
+ - README.md
117
+ files:
118
+ - LICENSE.txt
119
+ - README.md
120
+ - Rakefile
121
+ - app/assets/javascripts/dynamic_query.js
122
+ - lib/dynamic_query.rb
123
+ - lib/dynamic_query/dynamic_query.erb
124
+ - lib/dynamic_query/helper.rb
125
+ - lib/dynamic_query/railtie.rb
126
+ - lib/dynamic_query/version.rb
127
+ - lib/generators/dynamic_query_generator.rb
128
+ homepage: http://github.com/wnameless/dynamic_query
129
+ licenses:
130
+ - Apache License, Version 2.0
131
+ post_install_message:
132
+ rdoc_options: []
133
+ require_paths:
134
+ - lib
135
+ required_ruby_version: !ruby/object:Gem::Requirement
136
+ none: false
137
+ requirements:
138
+ - - ! '>='
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ segments:
142
+ - 0
143
+ hash: -611360296909739504
144
+ required_rubygems_version: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ requirements: []
151
+ rubyforge_project:
152
+ rubygems_version: 1.8.24
153
+ signing_key:
154
+ specification_version: 3
155
+ summary: dynamic_query-0.1.0
156
+ test_files: []