dynamic_query 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +3 -3
- data/Rakefile +30 -39
- data/app/helpers/_combined_result.html.erb +72 -0
- data/app/helpers/{dynamic_query.erb → _dynamic_query.html.erb} +23 -2
- data/app/helpers/_dynamic_result.html.erb +59 -0
- data/app/helpers/dynamic_query_helper.rb +15 -1
- data/lib/dynamic_query/combine_query.rb +144 -0
- data/lib/dynamic_query/helper.rb +15 -1
- data/lib/dynamic_query/joiner.rb +47 -0
- data/lib/dynamic_query/validator.rb +21 -0
- data/lib/dynamic_query/version.rb +5 -7
- data/lib/dynamic_query.rb +4 -18
- data/lib/generators/helper_generator.rb +3 -1
- metadata +57 -53
- data/app/assets/javascripts/dynamic_query.js +0 -16
- data/lib/generators/dynamic_query_generator.rb +0 -9
data/README.md
CHANGED
@@ -8,9 +8,6 @@ Installation:
|
|
8
8
|
## Gemfile for Rails 3
|
9
9
|
gem 'dynamic_query'
|
10
10
|
|
11
|
-
## rails generator
|
12
|
-
rails g dynamic_query
|
13
|
-
|
14
11
|
## you may skip this step unless you want to customize your own helper
|
15
12
|
## Regenerate the helper after upgrade dynamic_query
|
16
13
|
rails g dynamic_query:helper
|
@@ -29,6 +26,9 @@ dq = dynamic_query(List, Entry)
|
|
29
26
|
|
30
27
|
## render query panel in the view:
|
31
28
|
<%= dynamic_query @panel %>
|
29
|
+
|
30
|
+
## render query result in the view:
|
31
|
+
<%= dynamic_result @lists %>
|
32
32
|
```
|
33
33
|
|
34
34
|
## Advanced usage of dynamic_query
|
data/Rakefile
CHANGED
@@ -1,48 +1,39 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require 'rubygems'
|
4
|
-
require 'bundler'
|
1
|
+
#!/usr/bin/env rake
|
5
2
|
begin
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
exit e.status_code
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'bundler/gem_tasks'
|
5
|
+
rescue LoadError
|
6
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
11
7
|
end
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
require '
|
16
|
-
|
17
|
-
|
18
|
-
gem.name = "dynamic_query"
|
19
|
-
gem.homepage = "http://github.com/wnameless/dynamic_query"
|
20
|
-
gem.license = "Apache License, Version 2.0"
|
21
|
-
gem.version = DynamicQuery::Version::STRING
|
22
|
-
gem.summary = "dynamic_query-#{gem.version}"
|
23
|
-
gem.description = %Q{A dynamic query gui for ActiveRecord}
|
24
|
-
gem.email = "wnameless@gmail.com"
|
25
|
-
gem.authors = ["Wei-Ming Wu"]
|
26
|
-
# dependencies defined in Gemfile
|
27
|
-
gem.files = Dir["{app,lib}/**/*"] + ["LICENSE.txt", "Rakefile", "README.md"]
|
8
|
+
begin
|
9
|
+
require 'rdoc/task'
|
10
|
+
rescue LoadError
|
11
|
+
require 'rdoc/rdoc'
|
12
|
+
require 'rake/rdoctask'
|
13
|
+
RDoc::Task = Rake::RDocTask
|
28
14
|
end
|
29
|
-
Jeweler::RubygemsDotOrgTasks.new
|
30
15
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
16
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
17
|
+
rdoc.rdoc_dir = 'rdoc'
|
18
|
+
rdoc.title = 'DynamicQuery'
|
19
|
+
rdoc.options << '--line-numbers'
|
20
|
+
rdoc.rdoc_files.include('README.md')
|
21
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
36
22
|
end
|
37
23
|
|
38
|
-
task :default => :test
|
39
24
|
|
40
|
-
require 'rdoc/task'
|
41
|
-
Rake::RDocTask.new do |rdoc|
|
42
|
-
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
43
25
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
26
|
+
|
27
|
+
Bundler::GemHelper.install_tasks
|
28
|
+
|
29
|
+
require 'rake/testtask'
|
30
|
+
|
31
|
+
Rake::TestTask.new(:test) do |t|
|
32
|
+
t.libs << 'lib'
|
33
|
+
t.libs << 'test'
|
34
|
+
t.pattern = 'test/**/*_test.rb'
|
35
|
+
t.verbose = false
|
48
36
|
end
|
37
|
+
|
38
|
+
|
39
|
+
task :default => :test
|
@@ -0,0 +1,72 @@
|
|
1
|
+
<% completed_row = result.first %>
|
2
|
+
|
3
|
+
<center id="combined_result">
|
4
|
+
|
5
|
+
<table id="combined_result_table" style="text-align: center">
|
6
|
+
<% if completed_row %>
|
7
|
+
<tr>
|
8
|
+
<%= completed_row.map { |record|
|
9
|
+
"<th colspan='#{record.attributes.size}'>#{record.table_name}</th>" }.join.html_safe %>
|
10
|
+
</tr>
|
11
|
+
<tr>
|
12
|
+
<%= completed_row.map{ |rec|
|
13
|
+
rec.attributes.map { |k, _| k } }.flatten.map { |col| "<th>#{col}</th>" }.join.html_safe %>
|
14
|
+
</tr>
|
15
|
+
<% end %>
|
16
|
+
<% result.each do |row| %>
|
17
|
+
<tr>
|
18
|
+
<% row.map { |rec| rec.attributes.map { |k ,v| v } }.flatten.each do |col| %>
|
19
|
+
<td><%= col %></td>
|
20
|
+
<% end %>
|
21
|
+
</tr>
|
22
|
+
<% end %>
|
23
|
+
</table>
|
24
|
+
|
25
|
+
<button id="table2csv">Download CSV</button>
|
26
|
+
|
27
|
+
<script>
|
28
|
+
var regulateCSVCell = function( cell ) {
|
29
|
+
if ( cell.indexOf( ',' ) == -1 ) {
|
30
|
+
return cell;
|
31
|
+
}
|
32
|
+
return '"' + cell + '"';
|
33
|
+
};
|
34
|
+
|
35
|
+
var ary2CSV = function( ary ) {
|
36
|
+
csv = '';
|
37
|
+
for ( var row in ary ) {
|
38
|
+
for ( var col in ary[row] ) {
|
39
|
+
if ( col == 0 ) {
|
40
|
+
csv += regulateCSVCell( ary[row][col] )
|
41
|
+
} else {
|
42
|
+
csv += ',' + regulateCSVCell( ary[row][col] )
|
43
|
+
}
|
44
|
+
}
|
45
|
+
csv += "\n"
|
46
|
+
}
|
47
|
+
return csv;
|
48
|
+
};
|
49
|
+
|
50
|
+
var saveCSV = function( csv ) {
|
51
|
+
var href = 'data:application/csv;charset=utf-8,'
|
52
|
+
href += encodeURIComponent( csv );
|
53
|
+
window.open( href );
|
54
|
+
};
|
55
|
+
|
56
|
+
$( '#table2csv' ).on( 'click', function() {
|
57
|
+
var table = [];
|
58
|
+
$( '#combined_result_table tr' ).each( function( index ) {
|
59
|
+
if ( index > 0 ) {
|
60
|
+
var row = [];
|
61
|
+
$( this ).children().each( function() {
|
62
|
+
row.push( $( this ).text() );
|
63
|
+
});
|
64
|
+
table.push( row );
|
65
|
+
}
|
66
|
+
});
|
67
|
+
|
68
|
+
saveCSV( ary2CSV( table ) );
|
69
|
+
});
|
70
|
+
</script>
|
71
|
+
|
72
|
+
</center>
|
@@ -1,11 +1,14 @@
|
|
1
|
+
<% or_disable = opt[:or_disable]; opt.delete(:or_disable) %>
|
2
|
+
|
1
3
|
<%= form_tag(request.path, { :method => :get, :style => 'text-align: center;' }.merge(opt)) %>
|
4
|
+
<%= html %>
|
2
5
|
<% if panel %>
|
3
6
|
<table style="margin-left: auto; margin-right: auto;">
|
4
7
|
<% panel.select { |k, _| k =~ /^or_\d+$/ }.each_with_index do |(or_key, or_val), idx1| %>
|
5
8
|
<% or_val.each_with_index do |(and_key, and_val), idx2| %>
|
6
9
|
<tr>
|
7
10
|
<td>
|
8
|
-
<%= submit_tag 'ǁ', :name => "query[action][add_or]", :style => 'color: purple;', :title => 'OR' if idx1 == 0 && idx2 == 0 %>
|
11
|
+
<%= submit_tag 'ǁ', :name => "query[action][add_or]", :style => 'color: purple;', :title => 'OR' if idx1 == 0 && idx2 == 0 and !or_disable %>
|
9
12
|
<%= submit_tag '-', :name => "query[action][remove_#{or_key}]", :style => 'color: red;' if idx1 != 0 && idx2 == 0 %>
|
10
13
|
</td>
|
11
14
|
<td><%= select_tag "query[#{or_key}][#{and_key}][column]", options_for_select(panel[:columns], and_val[:column]) %></td>
|
@@ -34,6 +37,24 @@
|
|
34
37
|
<% end %>
|
35
38
|
<% end %>
|
36
39
|
</table>
|
37
|
-
<br />
|
38
40
|
<%= submit_tag 'Query', :style => 'width: 150px;'%>
|
39
41
|
</form>
|
42
|
+
|
43
|
+
<script>
|
44
|
+
$('.query_op').on('change', function() {
|
45
|
+
var _ref, _ref1;
|
46
|
+
if ((_ref = $(this).val()) === 'IS NULL' || _ref === 'IS NOT NULL') {
|
47
|
+
$('#' + $(this).attr('id').split(/_/).slice(0, -1).join('_') + '_value1').val('');
|
48
|
+
$('#' + $(this).attr('id').split(/_/).slice(0, -1).join('_') + '_value2').val('');
|
49
|
+
$('#' + $(this).attr('id').split(/_/).slice(0, -1).join('_') + '_value1').hide();
|
50
|
+
return $('#' + $(this).attr('id').split(/_/).slice(0, -1).join('_') + '_value2').hide();
|
51
|
+
} else if ((_ref1 = $(this).val()) === 'BETWEEN' || _ref1 === 'NOT BETWEEN') {
|
52
|
+
$('#' + $(this).attr('id').split(/_/).slice(0, -1).join('_') + '_value1').show();
|
53
|
+
return $('#' + $(this).attr('id').split(/_/).slice(0, -1).join('_') + '_value2').show();
|
54
|
+
} else {
|
55
|
+
$('#' + $(this).attr('id').split(/_/).slice(0, -1).join('_') + '_value1').show();
|
56
|
+
$('#' + $(this).attr('id').split(/_/).slice(0, -1).join('_') + '_value2').val('');
|
57
|
+
return $('#' + $(this).attr('id').split(/_/).slice(0, -1).join('_') + '_value2').hide();
|
58
|
+
}
|
59
|
+
});
|
60
|
+
</script>
|
@@ -0,0 +1,59 @@
|
|
1
|
+
<center>
|
2
|
+
<table id="dynamic_result_table">
|
3
|
+
<% if result.first %>
|
4
|
+
<tr>
|
5
|
+
<%= result.first.attributes.map { |k, _| "<th>#{k}</th>" }.join.html_safe %>
|
6
|
+
</tr>
|
7
|
+
<% end %>
|
8
|
+
<% result.each do |patient| %>
|
9
|
+
<tr>
|
10
|
+
<%= patient.attributes.map { |_, v| "<td>#{v}</td>" }.join.html_safe %>
|
11
|
+
</tr>
|
12
|
+
<% end if result %>
|
13
|
+
</table>
|
14
|
+
|
15
|
+
<button id="table2csv">Download CSV</button>
|
16
|
+
|
17
|
+
<script>
|
18
|
+
var regulateCSVCell = function( cell ) {
|
19
|
+
if ( cell.indexOf( ',' ) == -1 ) {
|
20
|
+
return cell;
|
21
|
+
}
|
22
|
+
return '"' + cell + '"';
|
23
|
+
};
|
24
|
+
|
25
|
+
var ary2CSV = function( ary ) {
|
26
|
+
csv = '';
|
27
|
+
for( var row in ary ) {
|
28
|
+
for( var col in ary[row] ) {
|
29
|
+
if ( col == 0 ) {
|
30
|
+
csv += regulateCSVCell( ary[row][col] )
|
31
|
+
} else {
|
32
|
+
csv += ',' + regulateCSVCell( ary[row][col] )
|
33
|
+
}
|
34
|
+
}
|
35
|
+
csv += "\n"
|
36
|
+
}
|
37
|
+
return csv;
|
38
|
+
};
|
39
|
+
|
40
|
+
var saveCSV = function( csv ) {
|
41
|
+
var href = 'data:application/csv;charset=utf-8,'
|
42
|
+
href += encodeURIComponent( csv );
|
43
|
+
window.open( href );
|
44
|
+
};
|
45
|
+
|
46
|
+
$( '#table2csv' ).on( 'click', function() {
|
47
|
+
var table = [];
|
48
|
+
$( '#dynamic_result_table tr' ).each( function( index ) {
|
49
|
+
var row = [];
|
50
|
+
$( this ).children().each( function() {
|
51
|
+
row.push( $( this ).text() );
|
52
|
+
});
|
53
|
+
table.push( row );
|
54
|
+
});
|
55
|
+
|
56
|
+
saveCSV( ary2CSV( table ) );
|
57
|
+
});
|
58
|
+
</script>
|
59
|
+
</center>
|
@@ -1,6 +1,20 @@
|
|
1
1
|
module DynamicQueryHelper
|
2
2
|
def dynamic_query(panel, opt = {})
|
3
|
-
|
3
|
+
html = ''
|
4
|
+
yield html if block_given?
|
5
|
+
template = ERB.new(File.read(File.dirname(__FILE__) + '/_dynamic_query.html.erb'))
|
6
|
+
content = template.result(binding)
|
7
|
+
content.html_safe
|
8
|
+
end
|
9
|
+
|
10
|
+
def dynamic_result(result)
|
11
|
+
template = ERB.new(File.read(File.dirname(__FILE__) + '/_dynamic_result.html.erb'))
|
12
|
+
content = template.result(binding)
|
13
|
+
content.html_safe
|
14
|
+
end
|
15
|
+
|
16
|
+
def combined_result(result)
|
17
|
+
template = ERB.new(File.read(File.dirname(__FILE__) + '/_combined_result.html.erb'))
|
4
18
|
content = template.result(binding)
|
5
19
|
content.html_safe
|
6
20
|
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
require 'dynamic_query/validator'
|
2
|
+
require 'dynamic_query/joiner'
|
3
|
+
|
4
|
+
module DynamicQuery
|
5
|
+
module CombineQuery
|
6
|
+
include Validator, Joiner
|
7
|
+
|
8
|
+
def conditions(query, table = nil)
|
9
|
+
query ||= {}
|
10
|
+
query = query.clone
|
11
|
+
query = filter_valid_info(query)
|
12
|
+
|
13
|
+
conditions = []
|
14
|
+
query.each do |_, ands|
|
15
|
+
conditions << ands.map { |_, v| condition_to_pair v }
|
16
|
+
end
|
17
|
+
|
18
|
+
cond = []
|
19
|
+
conditions.each do |condition|
|
20
|
+
c = {}
|
21
|
+
condition.each do |pair|
|
22
|
+
pair.each do |k, v|
|
23
|
+
c[k] ||= []
|
24
|
+
c[k].concat v
|
25
|
+
end
|
26
|
+
end
|
27
|
+
c.keys.each { |k| c[k] = Hash[ c[k].each_slice(2).to_a ] }
|
28
|
+
cond << c
|
29
|
+
end
|
30
|
+
cond.map! { |c| c[table.to_s] } if table
|
31
|
+
cond
|
32
|
+
end
|
33
|
+
|
34
|
+
def combine_query(query, relations, opts = {})
|
35
|
+
conds = conditions(query).first || {}
|
36
|
+
models = relations.each_slice(3).map { |sec| sec.first }
|
37
|
+
foreign_keys = relations - models
|
38
|
+
|
39
|
+
selected_records = filter_conditioned_records(models, foreign_keys, conds)
|
40
|
+
selected_records = remove_unlinked_records(selected_records, foreign_keys)
|
41
|
+
result = join(selected_records, foreign_keys)
|
42
|
+
|
43
|
+
result.delete_if { |row| row.include? nil } unless opts[:accept_null]
|
44
|
+
result.map { |row| row.map { |rec| rec.attributes.keep_if { |k, _| k.to_s !~ /id$/ } } } unless opts[:reveal_id]
|
45
|
+
|
46
|
+
result
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
def remove_unlinked_records(selected_records, foreign_keys)
|
51
|
+
foreign_keys = foreign_keys.clone
|
52
|
+
|
53
|
+
selected_records.each_with_index do |records, idx|
|
54
|
+
unless foreign_keys.empty?
|
55
|
+
delete_unlinked_records(records, foreign_keys.shift, selected_records[idx + 1], foreign_keys.shift)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
selected_records
|
60
|
+
end
|
61
|
+
|
62
|
+
def delete_unlinked_records(tgt, fks1, ref, fks2)
|
63
|
+
ref_val = ref.map { |r| fks2.map { |fk| r.send(fk) } }
|
64
|
+
tgt.keep_if { |t| ref_val.include?(fks1.map { |fk| t.send(fk) }) }
|
65
|
+
end
|
66
|
+
|
67
|
+
def filter_conditioned_records(models, foreign_keys, conds)
|
68
|
+
foreign_keys = foreign_keys.clone
|
69
|
+
|
70
|
+
selected_records = []
|
71
|
+
determinate_values = nil
|
72
|
+
models.each do |m|
|
73
|
+
selected_records << m.where(conds[m.table_name]).all
|
74
|
+
if determinate_values
|
75
|
+
trim_records(selected_records.last, determinate_values, foreign_keys.shift)
|
76
|
+
end
|
77
|
+
if foreign_keys.empty?
|
78
|
+
determinate_values = nil
|
79
|
+
else
|
80
|
+
fks = foreign_keys.shift
|
81
|
+
determinate_values = selected_records.last.map { |r| fks.map { |fk| r.send(fk) } }
|
82
|
+
end
|
83
|
+
end
|
84
|
+
selected_records
|
85
|
+
end
|
86
|
+
|
87
|
+
def trim_records(records, det_val, fks)
|
88
|
+
records.keep_if { |r| det_val.include?(fks.map { |fk| r[fk] }) }
|
89
|
+
end
|
90
|
+
|
91
|
+
def condition_to_pair(cond)
|
92
|
+
table, column = cond[:column].split(/\./)
|
93
|
+
{ table => ["#{column}.#{convert_op cond[:operator]}", convert_val(cond[:operator], cond[:value1], cond[:value2])] }
|
94
|
+
end
|
95
|
+
|
96
|
+
def convert_val(op, val1, val2)
|
97
|
+
case op
|
98
|
+
when 'IN', 'NOT IN'
|
99
|
+
val1.split(/,/).delete_if { |word| word.blank? }.map { |word| word.strip }
|
100
|
+
when 'BETWEEN', 'NOT BETWEEN'
|
101
|
+
[val1, val2]
|
102
|
+
when 'IS NULL', 'IS NOT NULL'
|
103
|
+
nil
|
104
|
+
else
|
105
|
+
val1
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def convert_op(op)
|
110
|
+
case op
|
111
|
+
when '='
|
112
|
+
'eq'
|
113
|
+
when '>'
|
114
|
+
'gt'
|
115
|
+
when '>='
|
116
|
+
'ge'
|
117
|
+
when '<'
|
118
|
+
'lt'
|
119
|
+
when '<='
|
120
|
+
'le'
|
121
|
+
when '!='
|
122
|
+
'not_eq'
|
123
|
+
when 'LIKE'
|
124
|
+
'like'
|
125
|
+
when 'NOT LIKE'
|
126
|
+
'not_like'
|
127
|
+
when 'IN'
|
128
|
+
'in'
|
129
|
+
when 'NOT IN'
|
130
|
+
'not_in'
|
131
|
+
when 'BETWEEN'
|
132
|
+
'btw'
|
133
|
+
when 'NOT BETWEEN'
|
134
|
+
'not_btw'
|
135
|
+
when 'IS NULL'
|
136
|
+
'is'
|
137
|
+
when 'IS NOT NULL'
|
138
|
+
'is_not'
|
139
|
+
else
|
140
|
+
'eq'
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
data/lib/dynamic_query/helper.rb
CHANGED
@@ -1,7 +1,21 @@
|
|
1
1
|
module DynamicQuery
|
2
2
|
module Helper
|
3
3
|
def dynamic_query(panel, opt = {})
|
4
|
-
|
4
|
+
html = ''
|
5
|
+
yield html if block_given?
|
6
|
+
template = ERB.new(File.read(File.dirname(__FILE__) + '/../../app/helpers/_dynamic_query.html.erb'))
|
7
|
+
content = template.result(binding)
|
8
|
+
content.html_safe
|
9
|
+
end
|
10
|
+
|
11
|
+
def dynamic_result(result)
|
12
|
+
template = ERB.new(File.read(File.dirname(__FILE__) + '/../../app/helpers/_dynamic_result.html.erb'))
|
13
|
+
content = template.result(binding)
|
14
|
+
content.html_safe
|
15
|
+
end
|
16
|
+
|
17
|
+
def combined_result(result)
|
18
|
+
template = ERB.new(File.read(File.dirname(__FILE__) + '/../../app/helpers/_combined_result.html.erb'))
|
5
19
|
content = template.result(binding)
|
6
20
|
content.html_safe
|
7
21
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module DynamicQuery
|
2
|
+
module Joiner
|
3
|
+
def join(records, keys)
|
4
|
+
result = []
|
5
|
+
li = find_logest_index(records)
|
6
|
+
result << records[li]
|
7
|
+
(1..li).to_a.reverse.each do |idx|
|
8
|
+
ref_ary = records[idx - 1]
|
9
|
+
new_ary = []
|
10
|
+
result.first.each do |record|
|
11
|
+
tgt_k = keys[idx * 2 - 1]
|
12
|
+
ref_k = keys[idx * 2 - 2]
|
13
|
+
new_ary << ref_ary.find { |r| ref_k.map { |rfk| r[rfk] } == tgt_k.map { |tfk| record[tfk] } }
|
14
|
+
end
|
15
|
+
result.unshift new_ary
|
16
|
+
end if li != 0
|
17
|
+
(li + 1..records.size - 1).each do |idx|
|
18
|
+
ref_ary = records[idx]
|
19
|
+
new_ary = []
|
20
|
+
result.last.each do |record|
|
21
|
+
if record.nil?
|
22
|
+
new_ary << nil
|
23
|
+
next
|
24
|
+
end
|
25
|
+
tgt_k = keys[idx * 2 - 2]
|
26
|
+
ref_k = keys[idx * 2 - 1]
|
27
|
+
new_ary << ref_ary.find { |r| ref_k.map { |rfk| r[rfk] } == tgt_k.map { |tfk| record[tfk] } }
|
28
|
+
end
|
29
|
+
result.unshift << new_ary
|
30
|
+
end
|
31
|
+
result.reduce(:zip).map! { |row| row.flatten }
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
def find_logest_index(records)
|
36
|
+
index = 0
|
37
|
+
max = 0
|
38
|
+
records.each_with_index do |r, idx|
|
39
|
+
if r.size > max
|
40
|
+
max = r.size
|
41
|
+
index = idx
|
42
|
+
end
|
43
|
+
end
|
44
|
+
index
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module DynamicQuery
|
2
|
+
module Validator
|
3
|
+
def filter_valid_info(query)
|
4
|
+
output = {}
|
5
|
+
|
6
|
+
query.each do |or_key, or_val|
|
7
|
+
if or_key =~ /^or_\d+$/ && or_val.kind_of?(Hash)
|
8
|
+
or_val.each do |and_key, and_val|
|
9
|
+
if and_key =~ /^and_\d+$/ && and_val.kind_of?(Hash) &&
|
10
|
+
(['column', 'operator', 'value1', 'value2'] - and_val.keys.map { |k| k.to_s }).empty?
|
11
|
+
output[or_key] ||= {}; output[or_key][and_key] ||= {}
|
12
|
+
output[or_key][and_key] = and_val
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
output
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/dynamic_query.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'dynamic_query/railtie' if defined?(Rails)
|
2
2
|
require 'generators/helper_generator' if defined?(Rails)
|
3
|
+
require 'dynamic_query/combine_query'
|
4
|
+
require 'dynamic_query/validator'
|
3
5
|
|
4
6
|
module DynamicQuery
|
5
7
|
OPERATOR = ['=', '>', '>=', '<', '<=', '!=',
|
@@ -11,6 +13,8 @@ module DynamicQuery
|
|
11
13
|
end
|
12
14
|
|
13
15
|
class DynamicQueryInstance
|
16
|
+
include CombineQuery, Validator
|
17
|
+
|
14
18
|
def initialize(*models, opt)
|
15
19
|
@reveal_keys = false
|
16
20
|
@white_list = []
|
@@ -163,24 +167,6 @@ module DynamicQuery
|
|
163
167
|
end
|
164
168
|
|
165
169
|
private
|
166
|
-
def filter_valid_info(query)
|
167
|
-
output = {}
|
168
|
-
|
169
|
-
query.each do |or_key, or_val|
|
170
|
-
if or_key =~ /^or_\d+$/ && or_val.kind_of?(Hash)
|
171
|
-
or_val.each do |and_key, and_val|
|
172
|
-
if and_key =~ /^and_\d+$/ && and_val.kind_of?(Hash) &&
|
173
|
-
(['column', 'operator', 'value1', 'value2'] - and_val.keys.map { |k| k.to_s }).empty?
|
174
|
-
output[or_key] ||= {}; output[or_key][and_key] ||= {}
|
175
|
-
output[or_key][and_key] = and_val
|
176
|
-
end
|
177
|
-
end
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
output
|
182
|
-
end
|
183
|
-
|
184
170
|
def panel_action(panel, action)
|
185
171
|
case action.keys.first
|
186
172
|
when /^add_or$/
|
@@ -6,7 +6,9 @@ module DynamicQuery
|
|
6
6
|
|
7
7
|
def manifest
|
8
8
|
copy_file 'app/helpers/dynamic_query_helper.rb', 'app/helpers/dynamic_query_helper.rb'
|
9
|
-
copy_file 'app/helpers/
|
9
|
+
copy_file 'app/helpers/_dynamic_query.html.erb', 'app/helpers/_dynamic_query.html.erb'
|
10
|
+
copy_file 'app/helpers/_dynamic_result.html.erb', 'app/helpers/_dynamic_result.html.erb'
|
11
|
+
copy_file 'app/helpers/_combined_result.html.erb', 'app/helpers/_combined_result.html.erb'
|
10
12
|
end
|
11
13
|
end
|
12
14
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dynamic_query
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,140 +9,141 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-02-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
15
|
+
name: rails
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
|
-
- -
|
19
|
+
- - ~>
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version:
|
21
|
+
version: 3.2.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
25
|
none: false
|
26
26
|
requirements:
|
27
|
-
- -
|
27
|
+
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version:
|
29
|
+
version: 3.2.0
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
|
-
name: rails
|
31
|
+
name: jquery-rails
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
33
33
|
none: false
|
34
34
|
requirements:
|
35
|
-
- -
|
35
|
+
- - ~>
|
36
36
|
- !ruby/object:Gem::Version
|
37
|
-
version:
|
37
|
+
version: 2.2.0
|
38
38
|
type: :runtime
|
39
39
|
prerelease: false
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
41
41
|
none: false
|
42
42
|
requirements:
|
43
|
-
- -
|
43
|
+
- - ~>
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
version:
|
45
|
+
version: 2.2.0
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
|
-
name:
|
47
|
+
name: sqlite3
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
49
49
|
none: false
|
50
50
|
requirements:
|
51
|
-
- -
|
51
|
+
- - ~>
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version:
|
53
|
+
version: 1.3.7
|
54
54
|
type: :development
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
57
|
none: false
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ~>
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
61
|
+
version: 1.3.7
|
62
62
|
- !ruby/object:Gem::Dependency
|
63
|
-
name:
|
63
|
+
name: shoulda
|
64
64
|
requirement: !ruby/object:Gem::Requirement
|
65
65
|
none: false
|
66
66
|
requirements:
|
67
|
-
- -
|
67
|
+
- - ~>
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version:
|
69
|
+
version: 3.3.2
|
70
70
|
type: :development
|
71
71
|
prerelease: false
|
72
72
|
version_requirements: !ruby/object:Gem::Requirement
|
73
73
|
none: false
|
74
74
|
requirements:
|
75
|
-
- -
|
75
|
+
- - ~>
|
76
76
|
- !ruby/object:Gem::Version
|
77
|
-
version:
|
77
|
+
version: 3.3.2
|
78
78
|
- !ruby/object:Gem::Dependency
|
79
|
-
name:
|
79
|
+
name: rdoc
|
80
80
|
requirement: !ruby/object:Gem::Requirement
|
81
81
|
none: false
|
82
82
|
requirements:
|
83
|
-
- -
|
83
|
+
- - ~>
|
84
84
|
- !ruby/object:Gem::Version
|
85
|
-
version:
|
85
|
+
version: '3.12'
|
86
86
|
type: :development
|
87
87
|
prerelease: false
|
88
88
|
version_requirements: !ruby/object:Gem::Requirement
|
89
89
|
none: false
|
90
90
|
requirements:
|
91
|
-
- -
|
91
|
+
- - ~>
|
92
92
|
- !ruby/object:Gem::Version
|
93
|
-
version:
|
93
|
+
version: '3.12'
|
94
94
|
- !ruby/object:Gem::Dependency
|
95
|
-
name:
|
95
|
+
name: bundler
|
96
96
|
requirement: !ruby/object:Gem::Requirement
|
97
97
|
none: false
|
98
98
|
requirements:
|
99
|
-
- -
|
99
|
+
- - ~>
|
100
100
|
- !ruby/object:Gem::Version
|
101
|
-
version: 1.
|
101
|
+
version: '1.3'
|
102
102
|
type: :development
|
103
103
|
prerelease: false
|
104
104
|
version_requirements: !ruby/object:Gem::Requirement
|
105
105
|
none: false
|
106
106
|
requirements:
|
107
|
-
- -
|
107
|
+
- - ~>
|
108
108
|
- !ruby/object:Gem::Version
|
109
|
-
version: 1.
|
109
|
+
version: '1.3'
|
110
110
|
- !ruby/object:Gem::Dependency
|
111
|
-
name:
|
111
|
+
name: rake
|
112
112
|
requirement: !ruby/object:Gem::Requirement
|
113
113
|
none: false
|
114
114
|
requirements:
|
115
|
-
- -
|
115
|
+
- - '>='
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version:
|
117
|
+
version: '0'
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
none: false
|
122
122
|
requirements:
|
123
|
-
- -
|
123
|
+
- - '>='
|
124
124
|
- !ruby/object:Gem::Version
|
125
|
-
version:
|
125
|
+
version: '0'
|
126
126
|
description: A dynamic query gui for ActiveRecord
|
127
127
|
email: wnameless@gmail.com
|
128
128
|
executables: []
|
129
129
|
extensions: []
|
130
|
-
extra_rdoc_files:
|
131
|
-
- LICENSE.txt
|
132
|
-
- README.md
|
130
|
+
extra_rdoc_files: []
|
133
131
|
files:
|
134
|
-
-
|
135
|
-
- README.md
|
136
|
-
- Rakefile
|
137
|
-
- app/assets/javascripts/dynamic_query.js
|
138
|
-
- app/helpers/dynamic_query.erb
|
139
|
-
- app/helpers/dynamic_query_helper.rb
|
140
|
-
- lib/dynamic_query.rb
|
132
|
+
- lib/dynamic_query/combine_query.rb
|
141
133
|
- lib/dynamic_query/helper.rb
|
134
|
+
- lib/dynamic_query/joiner.rb
|
142
135
|
- lib/dynamic_query/railtie.rb
|
136
|
+
- lib/dynamic_query/validator.rb
|
143
137
|
- lib/dynamic_query/version.rb
|
144
|
-
- lib/
|
138
|
+
- lib/dynamic_query.rb
|
145
139
|
- lib/generators/helper_generator.rb
|
140
|
+
- app/helpers/_combined_result.html.erb
|
141
|
+
- app/helpers/_dynamic_query.html.erb
|
142
|
+
- app/helpers/_dynamic_result.html.erb
|
143
|
+
- app/helpers/dynamic_query_helper.rb
|
144
|
+
- LICENSE.txt
|
145
|
+
- Rakefile
|
146
|
+
- README.md
|
146
147
|
homepage: http://github.com/wnameless/dynamic_query
|
147
148
|
licenses:
|
148
149
|
- Apache License, Version 2.0
|
@@ -153,22 +154,25 @@ require_paths:
|
|
153
154
|
required_ruby_version: !ruby/object:Gem::Requirement
|
154
155
|
none: false
|
155
156
|
requirements:
|
156
|
-
- -
|
157
|
+
- - '>='
|
157
158
|
- !ruby/object:Gem::Version
|
158
159
|
version: '0'
|
159
160
|
segments:
|
160
161
|
- 0
|
161
|
-
hash:
|
162
|
+
hash: 919103459980238385
|
162
163
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
163
164
|
none: false
|
164
165
|
requirements:
|
165
|
-
- -
|
166
|
+
- - '>='
|
166
167
|
- !ruby/object:Gem::Version
|
167
168
|
version: '0'
|
169
|
+
segments:
|
170
|
+
- 0
|
171
|
+
hash: 919103459980238385
|
168
172
|
requirements: []
|
169
173
|
rubyforge_project:
|
170
|
-
rubygems_version: 1.8.
|
174
|
+
rubygems_version: 1.8.25
|
171
175
|
signing_key:
|
172
176
|
specification_version: 3
|
173
|
-
summary: dynamic_query-0.
|
177
|
+
summary: dynamic_query-0.5.0
|
174
178
|
test_files: []
|
@@ -1,16 +0,0 @@
|
|
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
|
-
});
|
@@ -1,9 +0,0 @@
|
|
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
|
-
end
|