activerecord-multiconditions 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
@@ -0,0 +1,5 @@
1
+ = Changelog
2
+
3
+ == Release 0.1.0
4
+
5
+ * Initial public release.
data/MIT-LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2008 Simone Carletti <weppos@weppos.net>
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.
21
+
data/Manifest ADDED
@@ -0,0 +1,13 @@
1
+ CHANGELOG
2
+ lib/multi_conditions.rb
3
+ MIT-LICENSE
4
+ Rakefile
5
+ README
6
+ setup.rb
7
+ test/db/test.sqlite3
8
+ test/helper.rb
9
+ test/helper_database.rb
10
+ test/test_all.rb
11
+ test/unit/multi_conditions_test.rb
12
+ TODO
13
+ Manifest
data/README ADDED
@@ -0,0 +1,189 @@
1
+ = ActiveRecord::MultiConditions
2
+
3
+ MultiConditions is a simple ActiveRecord plugin for storing ActiveRecord query conditions and make complex queries painless.
4
+
5
+
6
+ == Overview
7
+
8
+ This plugin doesn't replace ActiveRecord#with_scope method,
9
+ nor the basic :condition usage but extends it with the ability
10
+ of storing illimitate conditions in multiple step.
11
+
12
+ conditions = MultiConditions.new
13
+ # ... do some elaboration
14
+ conditions.append_condition(['active = ? AND query LIKE ?', true, '%foo']
15
+ # ... other elaboration
16
+ conditions.append_condition(['name = ?', 'aname']
17
+
18
+ conditions.to_conditions
19
+ # => "active = true AND query LIKE '%foo' AND name = 'aname'"
20
+
21
+
22
+ == Dependencies
23
+
24
+ * Ruby 1.8.6
25
+ * ActiveRecord 2.0 (or greater)
26
+
27
+ If you want to run the test suite:
28
+
29
+ * sqlite3-ruby
30
+
31
+
32
+ == Source
33
+
34
+ MultiConditions source code is managed via GIT and hosted at GitHub: http://github.com/weppos/activerecord-multiconditions/.
35
+
36
+
37
+ == Download and Installation
38
+
39
+ Installing ActiveRecord MultiConditions as a GEM is probably the best and easiest way. You must have {RubyGems}[http://rubyforge.org/projects/rubygems/] installed for the following instruction to work:
40
+
41
+ $ sudo gem install activerecord-multiconditions
42
+
43
+ To install the library manually grab the source code from the website, navigate to the root library directory and enter:
44
+
45
+ $ sudo ruby setup.rb
46
+
47
+ If you need the latest development version you can download the source code from the GIT repositories listed above. Beware that the code might not as stable as the official release.
48
+
49
+
50
+ == Usage
51
+
52
+ First, don't forget to require the library.
53
+
54
+ gem 'activerecord-multiconditions'
55
+ require 'multi_conditions'
56
+
57
+ Now +MultiConditions+ object is automatically available as subclass of any ActiveRecord object.
58
+
59
+ class Task < ActiveRecord::Base; end
60
+
61
+ multiconditions = Task::Multiconditions.new
62
+ # => new instance
63
+
64
+ === Create a new instance
65
+
66
+ As stated by the Important section above, you first need a valid ActiveRecord model
67
+ to create a MultiConditions instance.
68
+ Because MultiConditions helps you to deal with ActiveRecord queries,
69
+ it's easy to understand why you *MUST* establish a valid database connection
70
+ and have at least one table (mapped with a Model) to query.
71
+
72
+ If you use ActiveRecord from Rails, this is just a matter of creating a new Model.
73
+
74
+ # create the Task model
75
+ class Task < ActiveRecord::Base
76
+ end
77
+
78
+ Now MultiConditions is automatically available within your Task namespace.
79
+ You can use it in whatever class method, for example:
80
+
81
+ class Task < ActiveRecord::Base
82
+
83
+ def complex_search()
84
+ c = MultiConditions.new(:foo => 'bar')
85
+ Task.find(:all, c.to_conditions)
86
+ end
87
+
88
+ end
89
+
90
+ But you can also create a new instance from an other library, class or model.
91
+ Just remember to initialize MultiConditions from its own namespace.
92
+
93
+ class Foo
94
+ class << self
95
+ def my_cool_conditions
96
+ Task::MultiConditions.new(:foo => 1).to_conditions
97
+ end
98
+ end
99
+ end
100
+
101
+ Foo.my_cool_conditions
102
+ # => 'foo = 1'
103
+
104
+ === Appending conditions
105
+
106
+ You can append new conditions calling
107
+
108
+ * #append_condition
109
+ * #prepend_condition
110
+
111
+ and passing the conditions you want to append or prepend.
112
+ See Condition Types section to lean more about supported objects.
113
+
114
+ conditions = MultiConditions.new
115
+ conditions.append_condition(['active = ? AND query LIKE ?', true, '%foo']
116
+ conditions.prepend_condition(['name = ?', 'aname']
117
+
118
+ conditions.to_conditions
119
+ # => "name = 'aname' AND active = true AND query LIKE '%foo'"
120
+
121
+
122
+ === Condition types
123
+
124
+ The MultiConditions object accepts any type of conditions supported by ActiveRecord,
125
+ including Strings, Arrays and Hashes, and merges them alltogether
126
+ just before sending the final :condition value to ActiveRecord search method.
127
+
128
+ conditions = MultiConditions.new
129
+ conditions.append_conditions(:foo => 1, :bar => 2)
130
+ conditions.append_conditions('active = 1')
131
+ conditions.append_conditions(['name LIKE ?', '%foo'])
132
+
133
+ conditions.to_conditions
134
+ # => 'foo = 1 AND :bar = 2 AND active = 1 AND name LIKE '%foo'
135
+
136
+ See ActiveRecord::Base#find documentation for more conditions examples.
137
+
138
+
139
+
140
+ == Important
141
+
142
+ Once loaded, this library become part of ActiveRecord package and
143
+ creates its own namespace at ActiveRecord::Base::MultiConditions.
144
+
145
+ require 'multi_conditions'
146
+
147
+ For various reason, you cannot initialize a new ActiveRecord::Base::MultiConditions
148
+ but you *MUST* initialize a MultiConditions instance from a Model.
149
+
150
+ # The wrong way
151
+ # raises Message: <"undefined method `abstract_class?' for Object:Class">
152
+ ActiveRecord::Base::MultiConditions.new
153
+
154
+ # The right way
155
+ class Model < ActiveRecord::Base
156
+
157
+ def a_method()
158
+ c = MultiConditions.new
159
+ find(:all, :conditions => c.to_conditions)
160
+ end
161
+
162
+ end
163
+
164
+
165
+ == Author
166
+
167
+ * {Simone Carletti}[http://www.simonecarletti.com/] <weppos@weppos.net>
168
+
169
+ If you like this software, please {recommend me}[http://www.workingwithrails.com/person/11967-simone-carletti] at Working with Rails.
170
+
171
+
172
+ == Website and Project Home
173
+
174
+ * {Project Homepage}[http://code.simonecarletti.com/activerecord-multiconditions]
175
+ * {At GitHub}[http://github.com/weppos/activerecord-multiconditions/]
176
+
177
+
178
+ == FeedBack and Bug reports
179
+
180
+ Feel free to email {Simone Carletti}[mailto:weppos@weppos.net]
181
+ with any questions or feedback.
182
+
183
+ Please submit your bug reports to the Redmine installation for MultiConditions
184
+ available at http://code.simonecarletti.com/activerecord-multiconditions.
185
+
186
+
187
+ == Changelog
188
+
189
+ See CHANGELOG file.
data/Rakefile ADDED
@@ -0,0 +1,58 @@
1
+ require 'rubygems'
2
+ require 'echoe'
3
+
4
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + "/lib")
5
+ require 'multi_conditions'
6
+
7
+
8
+ # Common package properties
9
+ PKG_NAME = ENV['PKG_NAME'] || ActiveRecord::Base::MultiConditions::GEM
10
+ PKG_VERSION = ENV['PKG_VERSION'] || ActiveRecord::Base::MultiConditions::VERSION
11
+ PKG_SUMMARY = "An ActiveRecord plugin for dealing with complex search :conditions."
12
+ PKG_FILES = FileList.new("{lib,test}/**/*.rb") do |fl|
13
+ fl.exclude 'TODO'
14
+ fl.include %w(README.rdoc README CHANGELOG MIT-LICENSE)
15
+ fl.include %w(Rakefile setup.rb)
16
+ end
17
+ RUBYFORGE_PROJECT = 'activerecord-multiconditions'
18
+
19
+ if ENV['SNAPSHOT'].to_i == 1
20
+ PKG_VERSION << "." << Time.now.utc.strftime("%Y%m%d%H%M%S")
21
+ end
22
+
23
+
24
+ Echoe.new(PKG_NAME, PKG_VERSION) do |p|
25
+ p.author = "Simone Carletti"
26
+ p.email = "weppos@weppos.net"
27
+ p.summary = PKG_SUMMARY
28
+ p.description = <<-EOF
29
+ MultiConditions is a simple ActiveRecord plugin \
30
+ for storing ActiveRecord query conditions and make complex queries painless.
31
+ EOF
32
+ p.url = "http://code.simonecarletti.com/activerecord-multiconditions"
33
+
34
+ p.version = PKG_VERSION
35
+ p.changes = ''
36
+
37
+ p.dependencies = ['activerecord >=2.0.0']
38
+ p.rcov_options = ["-xRakefile"]
39
+
40
+ p.need_zip = true
41
+ p.include_rakefile = true
42
+
43
+ p.project = RUBYFORGE_PROJECT
44
+
45
+ p.rdoc_pattern = /^(lib|CHANGELOG|MIT\-LICENSE|README)/
46
+ end
47
+
48
+
49
+ begin
50
+ require 'code_statistics'
51
+ desc "Show library's code statistics"
52
+ task :stats do
53
+ CodeStatistics.new(["MultiConditions", "lib"],
54
+ ["Tests", "test"]).to_s
55
+ end
56
+ rescue LoadError
57
+ puts "CodeStatistics (Rails) is not available"
58
+ end
data/TODO ADDED
@@ -0,0 +1,9 @@
1
+ = TODO
2
+
3
+ * improve tests in order to use real queries instead of simple statements
4
+
5
+ * add tests for different ActiveRecord versions
6
+
7
+ * ... more
8
+
9
+ * configure a Redmine installation to store TODO list! :)
@@ -0,0 +1,90 @@
1
+
2
+ # Gem::Specification for Activerecord-multiconditions-0.1.0
3
+ # Originally generated by Echoe
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = %q{activerecord-multiconditions}
7
+ s.version = "0.1.0"
8
+
9
+ s.specification_version = 2 if s.respond_to? :specification_version=
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.authors = ["Simone Carletti"]
13
+ s.date = %q{2008-06-10}
14
+ s.description = %q{MultiConditions is a simple ActiveRecord plugin for storing ActiveRecord query conditions and make complex queries painless.}
15
+ s.email = %q{weppos@weppos.net}
16
+ s.extra_rdoc_files = ["CHANGELOG", "lib/multi_conditions.rb", "MIT-LICENSE", "README"]
17
+ s.files = ["CHANGELOG", "lib/multi_conditions.rb", "MIT-LICENSE", "Rakefile", "README", "setup.rb", "test/db/test.sqlite3", "test/helper.rb", "test/helper_database.rb", "test/test_all.rb", "test/unit/multi_conditions_test.rb", "TODO", "Manifest", "activerecord-multiconditions.gemspec"]
18
+ s.has_rdoc = true
19
+ s.homepage = %q{http://code.simonecarletti.com/activerecord-multiconditions}
20
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Activerecord-multiconditions", "--main", "README"]
21
+ s.require_paths = ["lib"]
22
+ s.rubyforge_project = %q{activerecord-multiconditions}
23
+ s.rubygems_version = %q{1.1.1}
24
+ s.summary = %q{An ActiveRecord plugin for dealing with complex search :conditions.}
25
+ s.test_files = ["test/test_all.rb"]
26
+
27
+ s.add_dependency(%q<activerecord>, [">= 2.0.0"])
28
+ end
29
+
30
+
31
+ # # Original Rakefile source (requires the Echoe gem):
32
+ #
33
+ # require 'rubygems'
34
+ # require 'echoe'
35
+ #
36
+ # $LOAD_PATH.unshift(File.dirname(__FILE__) + "/lib")
37
+ # require 'multi_conditions'
38
+ #
39
+ #
40
+ # # Common package properties
41
+ # PKG_NAME = ENV['PKG_NAME'] || ActiveRecord::Base::MultiConditions::GEM
42
+ # PKG_VERSION = ENV['PKG_VERSION'] || ActiveRecord::Base::MultiConditions::VERSION
43
+ # PKG_SUMMARY = "An ActiveRecord plugin for dealing with complex search :conditions."
44
+ # PKG_FILES = FileList.new("{lib,test}/**/*.rb") do |fl|
45
+ # fl.exclude 'TODO'
46
+ # fl.include %w(README.rdoc README CHANGELOG MIT-LICENSE)
47
+ # fl.include %w(Rakefile setup.rb)
48
+ # end
49
+ # RUBYFORGE_PROJECT = 'activerecord-multiconditions'
50
+ #
51
+ # if ENV['SNAPSHOT'].to_i == 1
52
+ # PKG_VERSION << "." << Time.now.utc.strftime("%Y%m%d%H%M%S")
53
+ # end
54
+ #
55
+ #
56
+ # Echoe.new(PKG_NAME, PKG_VERSION) do |p|
57
+ # p.author = "Simone Carletti"
58
+ # p.email = "weppos@weppos.net"
59
+ # p.summary = PKG_SUMMARY
60
+ # p.description = <<-EOF
61
+ # MultiConditions is a simple ActiveRecord plugin \
62
+ # for storing ActiveRecord query conditions and make complex queries painless.
63
+ # EOF
64
+ # p.url = "http://code.simonecarletti.com/activerecord-multiconditions"
65
+ #
66
+ # p.version = PKG_VERSION
67
+ # p.changes = ''
68
+ #
69
+ # p.dependencies = ['activerecord >=2.0.0']
70
+ # p.rcov_options = ["-xRakefile"]
71
+ #
72
+ # p.need_zip = true
73
+ # p.include_rakefile = true
74
+ #
75
+ # p.project = RUBYFORGE_PROJECT
76
+ #
77
+ # p.rdoc_pattern = /^(lib|CHANGELOG|MIT\-LICENSE|README)/
78
+ # end
79
+ #
80
+ #
81
+ # begin
82
+ # require 'code_statistics'
83
+ # desc "Show library's code statistics"
84
+ # task :stats do
85
+ # CodeStatistics.new(["MultiConditions", "lib"],
86
+ # ["Tests", "test"]).to_s
87
+ # end
88
+ # rescue LoadError
89
+ # puts "CodeStatistics (Rails) is not available"
90
+ # end
@@ -0,0 +1,167 @@
1
+ #
2
+ # = ActiveRecord::MultiConditions
3
+ #
4
+ # An ActiveRecord plugin for dealing with complex search :conditions.
5
+ #
6
+ #
7
+ # Category:: ActiveRecord
8
+ # Package:: ActiveRecord::MultiConditions
9
+ # Author:: Simone Carletti <weppos@weppos.net>
10
+ #
11
+ #--
12
+ # SVN: $Id$
13
+ #++
14
+
15
+
16
+ module ActiveRecord
17
+ class Base
18
+
19
+ #
20
+ # = ActiveRecord::MultiConditions
21
+ #
22
+ # MultiConditions is a simple ActiveRecord plugin for storing ActiveRecord
23
+ # query and make complex queries painless.
24
+ #
25
+ # This plugin doesn't replace ActiveRecord#with_scope method,
26
+ # nor the basic :condition usage but extends it with the ability
27
+ # of storing illimitate conditions in multiple step.
28
+ #
29
+ # conditions = MultiConditions.new
30
+ # # ... do some elaboration
31
+ # conditions.append_condition(['active = ? AND query LIKE ?', true, '%foo']
32
+ # # ... other elaboration
33
+ # conditions.append_condition(['name = ?', 'aname']
34
+ #
35
+ # conditions.to_conditions
36
+ # # => "active = true AND query LIKE '%foo' AND name = 'aname'"
37
+ #
38
+ # The MultiConditions object accepts any type of conditions supported by ActiveRecord,
39
+ # including Strings, Arrays and Hashes, and merges them alltogether
40
+ # just before sending the final :condition value to ActiveRecord search method.
41
+ #
42
+ # conditions = MultiConditions.new
43
+ # conditions.append_conditions(:foo => 1, :bar => 2)
44
+ # conditions.append_conditions('active = 1')
45
+ # conditions.append_conditions(['name LIKE ?', '%foo'])
46
+ #
47
+ # conditions.to_conditions
48
+ # # => 'foo = 1 AND :bar = 2 AND active = 1 AND name LIKE '%foo'
49
+ #
50
+ # See ActiveRecord::Base#find documentation for more conditions examples.
51
+ #
52
+ #
53
+ # == Important
54
+ #
55
+ # Once loaded, this library become part of ActiveRecord package and
56
+ # creates its own namespace at ActiveRecord::Base::MultiConditions.
57
+ #
58
+ # For various reason, you cannot initialize a new ActiveRecord::Base::MultiConditions
59
+ # but you *MUST* initialize a MultiConditions instance from a Model.
60
+ #
61
+ # # The wrong way
62
+ # # raises Message: <"undefined method `abstract_class?' for Object:Class">
63
+ # ActiveRecord::Base::MultiConditions.new
64
+ #
65
+ # # The right way
66
+ # class Model < ActiveRecord::Base
67
+ #
68
+ # def a_method()
69
+ # c = MultiConditions.new
70
+ # find(:all, :conditions => c.to_conditions)
71
+ # end
72
+ #
73
+ # end
74
+ #
75
+ #
76
+ class MultiConditions
77
+
78
+ module Version #:nodoc:
79
+ MAJOR = 0
80
+ MINOR = 1
81
+ TINY = 0
82
+
83
+ STRING = [MAJOR, MINOR, TINY].join('.')
84
+ end
85
+
86
+ NAME = 'ActiveRecord::MultiConditions'
87
+ GEM = 'activerecord-multiconditions'
88
+ AUTHOR = 'Simone Carletti <weppos@weppos.net>'
89
+ VERSION = defined?(Version) ? Version::STRING : nil
90
+ STATUS = 'alpha'
91
+ BUILD = ''.match(/(\d+)/).to_a.first
92
+
93
+
94
+ # Conditions collection
95
+ attr_reader :conditions
96
+
97
+ #
98
+ # Creates a new MultiConditions instance and initializes it with +conditions+.
99
+ #
100
+ # # empty instance
101
+ # c = MultiConditions.new
102
+ #
103
+ # # new instance with a first value
104
+ # c = MultiConditions.new(['condition = ?', 'value'])
105
+ #
106
+ # # initialization with block
107
+ # c = MultiConditions.new do |condition|
108
+ # condition.append_condition('foo = 1')
109
+ # condition.append_condition('bar = 2')
110
+ # condition.append_condition(:baz => 3)
111
+ # end
112
+ #
113
+ def initialize(condition = nil, &block) # :yields: self
114
+ @conditions = []
115
+ append_condition(condition)
116
+ yield(self) if block_given?
117
+ self
118
+ end
119
+
120
+ #
121
+ # Appends a new condition at the end of condition list.
122
+ #
123
+ def append_condition(condition)
124
+ @conditions.push(prepare_condition(condition)) unless condition.nil?
125
+ end
126
+
127
+ #
128
+ # Prepends a new condition at the beginning of condition list.
129
+ #
130
+ def prepend_condition(condition)
131
+ @conditions.unshift(prepare_condition(condition)) unless condition.nil?
132
+ end
133
+
134
+ #
135
+ # Returns a :conditions suitable representation of this object
136
+ #
137
+ # c = MultiConditions.new do |condition|
138
+ # condition.append_condition('foo = 1')
139
+ # condition.append_condition('bar = 2')
140
+ # condition.append_condition(:baz => 3)
141
+ # end
142
+ #
143
+ # c.to_conditions
144
+ # # => 'foo = 1 AND bar = 2 AND baz = 3'
145
+ #
146
+ # # Example usage
147
+ # find(:all, :conditions => c.to_conditions)
148
+ #
149
+ def to_conditions
150
+ @conditions.join(' AND ')
151
+ end
152
+ alias :to_s :to_conditions
153
+
154
+
155
+ protected
156
+
157
+ # normalize conditions to be stored
158
+ # for now use active record :sanitize_sql_for_conditions
159
+ # instead of dealing with custom methods.
160
+ def prepare_condition(condition)
161
+ Task.send(:sanitize_sql_for_conditions, condition)
162
+ end
163
+
164
+ end
165
+
166
+ end
167
+ end