activerecord-auto_filter 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/Gemfile +24 -0
- data/LICENSE.txt +22 -0
- data/README.md +54 -0
- data/Rakefile +1 -0
- data/activerecord-auto_filter.gemspec +24 -0
- data/demo.rb +81 -0
- data/lib/activerecord-auto_filter.rb +134 -0
- data/lib/activerecord-auto_filter/version.rb +5 -0
- data/test/active_record_auto_filter_test.rb +110 -0
- data/test/helpers/data_layer_setup.rb +13 -0
- data/test/helpers/db_setup_helper.rb +25 -0
- data/test/helpers/sample_model_definitions.rb +46 -0
- metadata +89 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 71bbfa7f6d59232176f41f78dda56840e44b1eac
|
4
|
+
data.tar.gz: 98ff34b5a5e4e5a692f348375c63e13e1ffb62e2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 189141eeaeb400717550cfb6da57ea5dbe601506269c67dadb4c0c592122b94e9c9bb44906335a0bf3c0ff83975d66779bbcbf9cc1cf7025048b53693c91b88d
|
7
|
+
data.tar.gz: 756e51cfbdc7f272b4d1c81ebf041b9794050e3e39ba31472df7994cae4dacd6e83982ca49d3077061fecacfaeac014afc1c81862d1bc0b938af20312b14868d
|
data/.gitignore
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in blah.gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
# Database Adapters
|
7
|
+
platforms :ruby do
|
8
|
+
gem "mysql2"
|
9
|
+
end
|
10
|
+
|
11
|
+
platforms :jruby do
|
12
|
+
gem "jdbc-mysql"
|
13
|
+
gem "activerecord-jdbcmysql-adapter"
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
group :test do
|
19
|
+
gem 'test-unit'
|
20
|
+
gem "shoulda", '3.0.1'
|
21
|
+
gem "shoulda-context", '1.0.0'
|
22
|
+
gem "shoulda-matchers", '1.0.0'
|
23
|
+
end
|
24
|
+
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 kaushik
|
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,54 @@
|
|
1
|
+
# Activerecord::AutoFilter
|
2
|
+
|
3
|
+
Configuration based condition building and inclusion handling extension for ActiveRecord::Base
|
4
|
+
|
5
|
+
In case of eager loading of a model and its associations, it may be required to obtain query results based on filter criteria that span across multiple associations. To achieve this, we tend to construct dynamic where clauses based on the presence of certain filter criteria. Since this happens so frequently, it causes code duplication and hence violates the DRY principle. This gem tries to address that concern. Given request param hash and query specification hash, it is capable of emitting the required associations that need to be included, and where conditions that need to applied on a given model, to achieve the desired result or even apply them to the model directly.
|
6
|
+
|
7
|
+
**The primary goal of this gem is to build dynamic query conditions**. It is not limited to catering to the needs of
|
8
|
+
eager loading like above and can also be used to build where conditions on just a model too. All that is required is
|
9
|
+
- request-params
|
10
|
+
- query-specification
|
11
|
+
- proper association definitions(if needed).
|
12
|
+
|
13
|
+
|
14
|
+
|
15
|
+
|
16
|
+
**Notes:**
|
17
|
+
|
18
|
+
1. See activerecord-auto_filter.gemspec for allowed ruby versions.
|
19
|
+
|
20
|
+
2. Following issues will be addressed later
|
21
|
+
|
22
|
+
- Currently it is mysql specific as the condition extraction is based on splitting the Arel::Table query by the word 'WHERE'.
|
23
|
+
- Accept Procs for determining the condition for building where clause, instead of just param value presence. This gives better control for the programmer.
|
24
|
+
|
25
|
+
|
26
|
+
## Installation
|
27
|
+
|
28
|
+
Add this line to your application's Gemfile:
|
29
|
+
|
30
|
+
gem 'activerecord-auto_filter'
|
31
|
+
|
32
|
+
And then execute:
|
33
|
+
|
34
|
+
$ bundle
|
35
|
+
|
36
|
+
Or install it yourself as:
|
37
|
+
|
38
|
+
$ gem install activerecord-auto_filter
|
39
|
+
|
40
|
+
## Demo
|
41
|
+
|
42
|
+
Run demo.rb for usage demo. Steps are below.
|
43
|
+
|
44
|
+
1. Checkout this repo
|
45
|
+
2. Run bundle install
|
46
|
+
3. Run ruby demo.rb
|
47
|
+
|
48
|
+
## Contributing
|
49
|
+
|
50
|
+
1. Fork it
|
51
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
52
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
53
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
54
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'activerecord-auto_filter/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "activerecord-auto_filter"
|
8
|
+
gem.version = Activerecord::AutoFilter::VERSION
|
9
|
+
gem.authors = ["kaushik"]
|
10
|
+
gem.email = ["kaushikd49@gmail.com"]
|
11
|
+
gem.description = %q{Configuration based condition building and inclusion handling extension for ActiveRecord::Base}
|
12
|
+
gem.summary = %q{Inclusions and where-condition building extension for ActiveRecord}
|
13
|
+
gem.homepage = ""
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.required_ruby_version = ">= 1.9.3"
|
21
|
+
|
22
|
+
gem.add_runtime_dependency "activerecord", ">= 3.1.0"
|
23
|
+
gem.add_development_dependency "rake"
|
24
|
+
end
|
data/demo.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require "logger"
|
3
|
+
require "./lib/activerecord-auto_filter"
|
4
|
+
require_relative "test/helpers/data_layer_setup"
|
5
|
+
|
6
|
+
include DataLayerSetup
|
7
|
+
|
8
|
+
QUERY_SPEC = {
|
9
|
+
:self =>
|
10
|
+
{
|
11
|
+
:product_id =>
|
12
|
+
{
|
13
|
+
:filter_operator => :eq, :column => :product_id
|
14
|
+
}
|
15
|
+
},
|
16
|
+
:order_items =>
|
17
|
+
{
|
18
|
+
:state =>
|
19
|
+
{
|
20
|
+
:filter_operator => :eq, :column => :state
|
21
|
+
}
|
22
|
+
},
|
23
|
+
:product =>
|
24
|
+
{
|
25
|
+
:vertical =>
|
26
|
+
{
|
27
|
+
:filter_operator => :eq, :column => :vertical
|
28
|
+
},
|
29
|
+
:price_from =>
|
30
|
+
{
|
31
|
+
:filter_operator => :gteq, :column => :selling_price
|
32
|
+
},
|
33
|
+
:price_to =>
|
34
|
+
{
|
35
|
+
:filter_operator => :lt, :column => :selling_price
|
36
|
+
}
|
37
|
+
},
|
38
|
+
:order_item_units =>
|
39
|
+
{
|
40
|
+
:size =>
|
41
|
+
{
|
42
|
+
:filter_operator => :eq, :column => :size
|
43
|
+
}
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
47
|
+
def demo
|
48
|
+
pretty_print("DB setups started")
|
49
|
+
setup_datalayer(true)
|
50
|
+
pretty_print("DB setups complete")
|
51
|
+
run_demo_with_joins
|
52
|
+
run_demo_with_no_joins
|
53
|
+
end
|
54
|
+
|
55
|
+
def run_demo_with_joins
|
56
|
+
pretty_print("Demo with joins")
|
57
|
+
params = {:vertical => :book, :price_from => 100, :price_to => 600, :size => 100, :state => :approved}
|
58
|
+
generate_demo(params)
|
59
|
+
end
|
60
|
+
|
61
|
+
def run_demo_with_no_joins
|
62
|
+
pretty_print("Demo without joins")
|
63
|
+
params = {:product_id => :f1}
|
64
|
+
generate_demo(params)
|
65
|
+
end
|
66
|
+
|
67
|
+
def generate_demo(params)
|
68
|
+
ar_with_query_builded = Order.apply_includes_and_where_clauses(params, QUERY_SPEC)
|
69
|
+
puts "Params for this demo are #{params}"
|
70
|
+
pretty_print("Final query generated is below")
|
71
|
+
ar_with_query_builded.inspect
|
72
|
+
puts "\n"
|
73
|
+
end
|
74
|
+
|
75
|
+
def pretty_print(string)
|
76
|
+
num_stars = (100-string.size)/2
|
77
|
+
puts "\n" + "*" * num_stars + " #{string} " + "*" * num_stars + "\n"
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
demo()
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require "active_record/version"
|
3
|
+
|
4
|
+
class ActiveRecord::Base
|
5
|
+
|
6
|
+
class << self
|
7
|
+
|
8
|
+
|
9
|
+
################################# Generic where clause and inclusion builder ###########################
|
10
|
+
# Query specification format
|
11
|
+
#
|
12
|
+
# Hash containing association specific query specification,
|
13
|
+
# each of which will map a param field to its param metadata
|
14
|
+
# needed to construct where condition. Param metadata involve
|
15
|
+
# information about the table, column the param maps to and
|
16
|
+
# the operator that need to applied in the query with the
|
17
|
+
# table column for the given param value. The operator passed
|
18
|
+
# is delegated to Arel::Table. So, all operators accepted
|
19
|
+
# by it are allowed (as mentioned in the example below)
|
20
|
+
#
|
21
|
+
# {
|
22
|
+
# :self =>
|
23
|
+
# {
|
24
|
+
# <param_field> =>
|
25
|
+
# {
|
26
|
+
# :column => <col_name_sym>
|
27
|
+
# :filter_operator => <:gt|:lt|:gteq|:lteq|:in|:not_in>,
|
28
|
+
# }
|
29
|
+
# }
|
30
|
+
# :association1 =>
|
31
|
+
# {
|
32
|
+
# <param_field> =>
|
33
|
+
# {
|
34
|
+
# :column => <col_name_sym>
|
35
|
+
# :filter_operator => <:gt|:lt|:gteq|:lteq|:in|:not_in>,
|
36
|
+
# },
|
37
|
+
# ...
|
38
|
+
# :join_filter =>
|
39
|
+
# {
|
40
|
+
# :table1_column => <column_name>, :table2_column => <column_name>,
|
41
|
+
# },
|
42
|
+
# :is_inclusion_mandatory => <true|false>
|
43
|
+
# },
|
44
|
+
# ...
|
45
|
+
# }
|
46
|
+
|
47
|
+
|
48
|
+
# Applies inclusion and where conditions/clauses for the model called upon.
|
49
|
+
# Where conditions are generated based on the presence of a param value.
|
50
|
+
def apply_includes_and_where_clauses(params, query_spec)
|
51
|
+
model = self
|
52
|
+
inclusions, where_clauses = get_inclusions_and_where_clauses(params, query_spec)
|
53
|
+
|
54
|
+
active_record = model.includes(inclusions)
|
55
|
+
where_clauses.each { |e| active_record = active_record.where(e) }
|
56
|
+
active_record
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns association inclusions and where conditions/clauses for the model called upon.
|
60
|
+
# Association inclusion is based on the presence of related where conditions.
|
61
|
+
# Where conditions are generated based on the presence of a param value.
|
62
|
+
def get_inclusions_and_where_clauses(params, query_spec)
|
63
|
+
result = emit_inclusion_and_filter_details(params, query_spec)
|
64
|
+
inclusions = result.keys - [:self]
|
65
|
+
where_clause_filters = result.values.flatten
|
66
|
+
|
67
|
+
[inclusions, where_clause_filters]
|
68
|
+
end
|
69
|
+
|
70
|
+
def emit_inclusion_and_filter_details(params, query_spec)
|
71
|
+
exclusions = [:join_filter, :is_inclusion_mandatory]
|
72
|
+
query_spec.each_with_object({}) do |(association, association_filter_spec), res|
|
73
|
+
join_spec, is_inclusion_mandatory = association_filter_spec.values_at(*exclusions)
|
74
|
+
new_association_filter_spec = association_filter_spec.reject { |e| exclusions.include?(e) }
|
75
|
+
association_model = get_association_model(association)
|
76
|
+
join_filter = get_association_join_filter(join_spec, self, association_model)
|
77
|
+
|
78
|
+
where_clause_filters =
|
79
|
+
new_association_filter_spec.each_with_object([]) do |(param_field, filter_spec), filter_res|
|
80
|
+
value = params[param_field]
|
81
|
+
if value.present?
|
82
|
+
filter_res << get_where_clause_filter(filter_spec, value, association_model)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
if where_clause_filters.present?
|
87
|
+
res[association] = where_clause_filters
|
88
|
+
res[association] << join_filter if join_filter.present?
|
89
|
+
elsif is_inclusion_mandatory
|
90
|
+
res[association] = (join_filter.present?) ? [join_filter] : []
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Obtain ActiveRecord model from the association
|
96
|
+
def get_association_model(association)
|
97
|
+
(association == :self) ? self : self.reflect_on_association(association.to_sym).klass
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
def get_association_join_filter(join_filter, table1, table2)
|
102
|
+
return if join_filter.blank?
|
103
|
+
table1_col, table2_col = join_filter.values_at(:table1_column, :table2_column)
|
104
|
+
get_where_clause_sql(table2.arel_table[table2_col], table1, table1_col, :eq)
|
105
|
+
end
|
106
|
+
|
107
|
+
def get_where_clause_filter(filter_spec, value, table)
|
108
|
+
# Hash filters have good equality query abstractions.
|
109
|
+
# So choosing them over string filters for equality operator
|
110
|
+
if filter_spec[:filter_operator] == :eq
|
111
|
+
construct_hash_filter(value, filter_spec, table)
|
112
|
+
else
|
113
|
+
construct_str_filter(value, filter_spec, table)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def construct_str_filter(arg_value, filter_spec, table)
|
118
|
+
operator, column = filter_spec.values_at(:filter_operator, :column)
|
119
|
+
get_where_clause_sql(arg_value, table, column, operator)
|
120
|
+
end
|
121
|
+
|
122
|
+
def get_where_clause_sql(arg_value, table, column, operator)
|
123
|
+
table_arel = table.arel_table
|
124
|
+
sql = table_arel.where(table_arel[column].send(operator, arg_value)).to_sql
|
125
|
+
sql.split("WHERE").last
|
126
|
+
end
|
127
|
+
|
128
|
+
def construct_hash_filter(arg_value, filter_spec, table)
|
129
|
+
column = filter_spec[:column]
|
130
|
+
hash_filter = {column => arg_value}
|
131
|
+
(table != :self) ? {table.table_name.to_sym => hash_filter} : hash_filter
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "shoulda"
|
3
|
+
require 'test/unit'
|
4
|
+
require 'active_record'
|
5
|
+
require_relative "helpers/data_layer_setup"
|
6
|
+
require_relative "../lib/activerecord-auto_filter"
|
7
|
+
|
8
|
+
class ActiveRecordAutoFilterTest < Test::Unit::TestCase
|
9
|
+
include DataLayerSetup # Arel has a dependency on db connection
|
10
|
+
|
11
|
+
def setup
|
12
|
+
setup_datalayer()
|
13
|
+
end
|
14
|
+
|
15
|
+
context "inclusions check" do
|
16
|
+
should "contain only expected associations for inclusions" do
|
17
|
+
params = {:f1 => :f1_val, :f2 => :f2_val, :f3 => 4, :f4 => 41}
|
18
|
+
assert_associations_are_included(params, :order_items, :product)
|
19
|
+
|
20
|
+
params = {:f1 => :f1_val, :f2 => :f2_val, :f3 => 4}
|
21
|
+
assert_associations_are_included(params, :order_items, :product)
|
22
|
+
|
23
|
+
params = {:f2 => :f2_val, :f3 => 4}
|
24
|
+
assert_associations_are_included(params, :order_items, :product)
|
25
|
+
|
26
|
+
params = {:f3 => 4}
|
27
|
+
assert_associations_are_included(params, :product)
|
28
|
+
|
29
|
+
params = {:f2 => :f2_val}
|
30
|
+
assert_associations_are_included(params, :order_items)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "where clause filter structure check" do
|
35
|
+
should "contain appropriate kind filters - string or hash" do
|
36
|
+
table1_name = Order.table_name.to_sym
|
37
|
+
table2_name = OrderItem.table_name.to_sym
|
38
|
+
table3_name = Product.table_name.to_sym
|
39
|
+
params = {:f1 => :f1_val, :f2 => :f2_val, :f3 => 4}
|
40
|
+
query_details = Order.emit_inclusion_and_filter_details(params, get_sample_query_spec)
|
41
|
+
|
42
|
+
# Check hash filter exists and its structure
|
43
|
+
association_containing_hash_filter = query_details.delete(:order_items)
|
44
|
+
assert_equal([{table2_name => {:c2 => :f2_val}}], association_containing_hash_filter)
|
45
|
+
|
46
|
+
# Check string filter exists and its structure
|
47
|
+
assert(query_details.all? do |association,filter_details|
|
48
|
+
string_where_clause = filter_details.first
|
49
|
+
str_filter_format_regexps = [/#{table1_name}.*c1.*f1_val/, /#{table3_name}.*c3.*4/]
|
50
|
+
str_filter_format_regexps.any?{|r| string_where_clause.match(r)}
|
51
|
+
end)
|
52
|
+
end
|
53
|
+
|
54
|
+
should "contain multiple kind of filters for a given association" do
|
55
|
+
params = {:f1 => :f1_val, :f2 => :f2_val, :f3 => 4, :f4 => 5}
|
56
|
+
query_spec = get_sample_query_spec
|
57
|
+
query_spec[:order_items][:f4] = { :filter_operator => :eq, :column => :c4 }
|
58
|
+
|
59
|
+
result = Order.emit_inclusion_and_filter_details(params, query_spec)
|
60
|
+
assert_equal(2,result[:order_items].size)
|
61
|
+
end
|
62
|
+
|
63
|
+
should "contain join filters" do
|
64
|
+
table1_name = Order.table_name
|
65
|
+
table2_name = OrderItem.table_name
|
66
|
+
query_spec = get_sample_query_spec
|
67
|
+
params = {:f2 => :f2_val, :f3 => 4}
|
68
|
+
|
69
|
+
query_spec[:order_items][:join_filter] = { :table1_column => :col1, :table2_column => :col2 }
|
70
|
+
result = Order.emit_inclusion_and_filter_details(params, query_spec)
|
71
|
+
|
72
|
+
assert_equal(2,result[:order_items].size)
|
73
|
+
assert(result[:order_items].any? do |filter|
|
74
|
+
filter.class == String and filter.match(/#{table1_name}.*col1.*#{table2_name}.*col2.*/)
|
75
|
+
end)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def assert_associations_are_included(params, *expected_inclusions)
|
80
|
+
query_spec = get_sample_query_spec()
|
81
|
+
associations_actually_included, wh_clauses = Order.get_inclusions_and_where_clauses(params, query_spec)
|
82
|
+
assert_equal(expected_inclusions, associations_actually_included)
|
83
|
+
end
|
84
|
+
|
85
|
+
def get_sample_query_spec
|
86
|
+
{
|
87
|
+
:self =>
|
88
|
+
{
|
89
|
+
:f1 =>
|
90
|
+
{
|
91
|
+
:filter_operator => :lt, :column => :c1
|
92
|
+
}
|
93
|
+
},
|
94
|
+
:order_items =>
|
95
|
+
{
|
96
|
+
:f2 =>
|
97
|
+
{
|
98
|
+
:filter_operator => :eq, :column => :c2
|
99
|
+
}
|
100
|
+
},
|
101
|
+
:product =>
|
102
|
+
{
|
103
|
+
:f3 =>
|
104
|
+
{
|
105
|
+
:filter_operator => :gteq, :column => :c3
|
106
|
+
}
|
107
|
+
}
|
108
|
+
}
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require_relative "./sample_model_definitions"
|
2
|
+
require_relative "./db_setup_helper"
|
3
|
+
|
4
|
+
|
5
|
+
module DataLayerSetup
|
6
|
+
include SampleModelDefinitions
|
7
|
+
include DbSetupHelper
|
8
|
+
|
9
|
+
def setup_datalayer(stdout_logging=false)
|
10
|
+
do_db_setups(stdout_logging)
|
11
|
+
create_tables()
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module DbSetupHelper
|
2
|
+
include SampleModelDefinitions
|
3
|
+
|
4
|
+
DATABASE = 'experiments'
|
5
|
+
CONNECTION_SPEC = {adapter: 'mysql2', username: 'root', password: '', host: 'localhost'}
|
6
|
+
|
7
|
+
def do_db_setups(stdout_logging=false)
|
8
|
+
establish_connection_with_no_db(CONNECTION_SPEC)
|
9
|
+
create_database(DATABASE)
|
10
|
+
establish_connection_with_db(DATABASE, CONNECTION_SPEC)
|
11
|
+
ActiveRecord::Base.logger = Logger.new(STDOUT) if stdout_logging
|
12
|
+
end
|
13
|
+
|
14
|
+
def create_database(database)
|
15
|
+
ActiveRecord::Base.connection.create_database(database) rescue nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def establish_connection_with_no_db(connection_spec)
|
19
|
+
ActiveRecord::Base.establish_connection(connection_spec)
|
20
|
+
end
|
21
|
+
|
22
|
+
def establish_connection_with_db(database, connection_spec)
|
23
|
+
ActiveRecord::Base.establish_connection(connection_spec.merge(database: database))
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module SampleModelDefinitions
|
2
|
+
class Order < ActiveRecord::Base
|
3
|
+
has_one :product
|
4
|
+
has_many :order_items
|
5
|
+
has_many :order_item_units, :through => :order_items
|
6
|
+
end
|
7
|
+
|
8
|
+
class OrderItem < ActiveRecord::Base
|
9
|
+
has_many :order_item_units
|
10
|
+
end
|
11
|
+
|
12
|
+
class OrderItemUnit < ActiveRecord::Base
|
13
|
+
end
|
14
|
+
|
15
|
+
class Product < ActiveRecord::Base
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
def create_tables
|
20
|
+
ActiveRecord::Schema.define(:version => 20140124132738) do
|
21
|
+
create_table :orders, :force => true do |t|
|
22
|
+
t.text :user
|
23
|
+
t.string :product_id
|
24
|
+
t.integer :quantity, :default => true
|
25
|
+
end
|
26
|
+
|
27
|
+
create_table :order_items, :force => true do |t|
|
28
|
+
t.string :state
|
29
|
+
t.integer :quantity
|
30
|
+
t.references :order
|
31
|
+
end
|
32
|
+
|
33
|
+
create_table :order_item_units, :force => true do |t|
|
34
|
+
t.integer :size, :default => true
|
35
|
+
t.references :order_item
|
36
|
+
end
|
37
|
+
|
38
|
+
create_table :products, :force => true do |t|
|
39
|
+
t.string :vertical
|
40
|
+
t.integer :selling_price
|
41
|
+
t.references :order
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
metadata
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: activerecord-auto_filter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- kaushik
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-02-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activerecord
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 3.1.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 3.1.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: Configuration based condition building and inclusion handling extension
|
42
|
+
for ActiveRecord::Base
|
43
|
+
email:
|
44
|
+
- kaushikd49@gmail.com
|
45
|
+
executables: []
|
46
|
+
extensions: []
|
47
|
+
extra_rdoc_files: []
|
48
|
+
files:
|
49
|
+
- .gitignore
|
50
|
+
- Gemfile
|
51
|
+
- LICENSE.txt
|
52
|
+
- README.md
|
53
|
+
- Rakefile
|
54
|
+
- activerecord-auto_filter.gemspec
|
55
|
+
- demo.rb
|
56
|
+
- lib/activerecord-auto_filter.rb
|
57
|
+
- lib/activerecord-auto_filter/version.rb
|
58
|
+
- test/active_record_auto_filter_test.rb
|
59
|
+
- test/helpers/data_layer_setup.rb
|
60
|
+
- test/helpers/db_setup_helper.rb
|
61
|
+
- test/helpers/sample_model_definitions.rb
|
62
|
+
homepage: ''
|
63
|
+
licenses: []
|
64
|
+
metadata: {}
|
65
|
+
post_install_message:
|
66
|
+
rdoc_options: []
|
67
|
+
require_paths:
|
68
|
+
- lib
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - '>='
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: 1.9.3
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
requirements: []
|
80
|
+
rubyforge_project:
|
81
|
+
rubygems_version: 2.1.11
|
82
|
+
signing_key:
|
83
|
+
specification_version: 4
|
84
|
+
summary: Inclusions and where-condition building extension for ActiveRecord
|
85
|
+
test_files:
|
86
|
+
- test/active_record_auto_filter_test.rb
|
87
|
+
- test/helpers/data_layer_setup.rb
|
88
|
+
- test/helpers/db_setup_helper.rb
|
89
|
+
- test/helpers/sample_model_definitions.rb
|