ruby_simple_search 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
data/README.md CHANGED
@@ -1,16 +1,45 @@
1
1
  # RubySimpleSearch
2
2
 
3
- RubySimpleSearch allows to search on the table fields.
4
- e.g. string and text fields.
3
+ RubySimpleSearch allows you to search on the table fields (string and text fields)
4
+ very easily.
5
5
 
6
- Sometimes we want to do search on the post's title and content
7
- or user's email, username and description or on other models but in same way.
8
- For those searches we use MySql's or Postgresql's LIKE operator to get the
9
- results. While doing same thing on the differet models you actually add lots of
10
- duplications in your code.
6
+ Mostly on the admin side, we do have a common text field to search the table
7
+ column's data.
8
+
9
+ Sometimes we want to do a search on the title, content and ratings on the post model or
10
+ email, username and description on the user model. For those searches we use MySQL's
11
+ or PostgreSQL's LIKE operator to get the results. While doing the same thing again and again
12
+ on the different models you actually add lots of duplication in your code.
11
13
 
12
14
  To avoid duplicating the same code, use RubySimpleSearch :)
13
15
 
16
+ #### RubySimpleSearch Features:
17
+ - Added like pattern support ('beginning', 'ending', 'containing', 'underscore', 'plain').
18
+ By default pattern is 'containing'
19
+
20
+ ```Ruby
21
+ simple_search_attributes :name, :address, :pattern => :ending
22
+ # It will search like '%york'
23
+
24
+ simple_search_attributes :name, :address, :pattern => :begining
25
+ # It will search like 'york%'
26
+
27
+ simple_search_attributes :name, :address, :pattern => :containing
28
+ # It will search like '%york%'
29
+
30
+ simple_search_attributes :name, :address, :pattern => :underscore
31
+ # It will search like '_o_'
32
+
33
+ simple_search_attributes :name, :address, :pattern => :plain
34
+ # It will search like 'york'
35
+ ```
36
+ - Added **block** support to simple_search method, so user can extend the query as per
37
+ his/her requirements (Now you can operate on the integer/decimal values also)
38
+
39
+ - Added specs
40
+
41
+ - Added exception handler
42
+
14
43
  ## Installation
15
44
 
16
45
  Add this line to your application's Gemfile:
@@ -33,23 +62,46 @@ Define attributes that you want to search through RubySimpleSearch
33
62
  class Post < ActiveActiveRecord::Base
34
63
  include RubySimpleSearch
35
64
 
36
- simple_search_attributes :title, :description
65
+ simple_search_attributes :title, :description, :pattern => :begining
37
66
  end
38
-
39
- class User < < ActiveActiveRecord::Base
67
+ ```
68
+ ```Ruby
69
+ class User < ActiveActiveRecord::Base
40
70
  include RubySimpleSearch
41
71
 
42
72
  simple_search_attributes :email, :username, :address
43
73
  end
44
-
45
- Post.simple_serach('tutorial')
46
- # => posts which have 'tutorial' text in title or in description fields
47
-
48
- User.simple_search('Mechanciles')
49
- # => users which have 'Mechanicles' text in the email, username and in address
50
-
74
+ ```
75
+ While defining simple_search_attributes, don't add integer/decimal data
76
+ attributes to it, instead of this you can do integer/decimal operation
77
+ by passing block to simple search method
78
+ ```Ruby
79
+ Post.simple_search('tuto')
80
+ # => posts which have 'tuto%' text in the title or in the description fields
81
+ ```
82
+ ```Ruby
83
+ User.simple_search('mechanicles')
84
+ # => users which have 'mechanicles' text in the email, username and in address
85
+ ```
86
+ ```Ruby
87
+ User.simple_search('mechanicles') do |search_term|
88
+ ["and address != ?", search_term]
89
+ end
90
+ # => You can pass block to simple_search method so you can extend it as your
91
+ # wish but you need to return an array of valid parameters like you do in #where
92
+ # method
93
+ ```
94
+ ```Ruby
51
95
  Model.simple_search('string')
52
- # => will return ActiveRecord::Relation object
96
+ # => with and without block will return ActiveRecord::Relation object
97
+ ```
98
+ ```Ruby
99
+ Model.simple_search('string').to_sql
100
+ #OR
101
+ User.simple_search('mechanicles') do |search_term|
102
+ ["and address != ?", search_term]
103
+ end.to_sql
104
+ # => will return sql query in string format
53
105
  ```
54
106
  ## Contributing
55
107
 
@@ -1,38 +1,6 @@
1
- # RubySimpleSearch allows to search on the table fields.
2
- # e.g. string and text fields.
3
- #
4
- # Sometimes we want to do search on the post's title and content
5
- # or user's email, username and description or on other models but in same way.
6
- # For those searches we use MySql's or Postgresql's LIKE operator to get the
7
- # results. While doing same thing on the differet models you actually add lots of
8
- # duplications in your code.
9
- #
10
- # To avoid duplicating the same code, use RubySimpleSearch :)
11
- #
12
- # Define attributes that you want to search through RubySimpleSearch
13
- #
14
- # class Post < ActiveActiveRecord::Base
15
- # include RubySimpleSearch
16
- #
17
- # simple_search_attributes :title, :description
18
- # end
19
- #
20
- # class User < < ActiveActiveRecord::Base
21
- # include RubySimpleSearch
22
- #
23
- # simple_search_attributes :email, :username, :address
24
- # end
25
- #
26
- # Post.simple_serach('tutorial')
27
- # # => posts which have tutorial text in title or in description fields
28
- #
29
- # User.simple_search('Mechanciles')
30
- # # => users which have mechanicles text in the email, username and in address
31
- #
32
- # Model.simple_search('string') will return ActiveRecord::Relation object
33
-
34
-
35
1
  require "ruby_simple_search/version"
2
+ require "ruby_simple_search/like_pattern"
3
+ require "ruby_simple_search/errors"
36
4
  require 'active_support/concern'
37
5
 
38
6
  module RubySimpleSearch
@@ -42,30 +10,78 @@ module RubySimpleSearch
42
10
  class_eval do
43
11
  def self.simple_search_attributes(*args)
44
12
  @simple_search_attributes = []
13
+ # default pattern is '%q%'
14
+ @simple_search_pattern = RubySimpleSearch::LIKE_PATTERNS[:containing]
45
15
  args.each do |arg|
46
- @simple_search_attributes << arg
16
+ if !arg.is_a?(Hash)
17
+ @simple_search_attributes << arg
18
+ else
19
+ set_pattern(arg[:pattern]) if arg[:pattern].present?
20
+ end
47
21
  end
48
22
  end
49
23
  end
50
24
  end
51
25
 
52
26
  module ClassMethods
53
- def simple_search(q)
54
- raise ArgumentError, "Argument is not string" unless q.is_a? String
27
+ def simple_search(search_term, &block)
28
+ raise RubySimpleSearch::Error::ATTRIBUTES_MISSING if @simple_search_attributes.blank?
29
+ raise ArgumentError, "Argument is not string" unless search_term.is_a? String
30
+
31
+ sql_query = nil
32
+ extended_query = nil
33
+ sql_query_condition = ""
34
+ sql_query_values = []
55
35
 
56
- query = ""
57
- patterned_text = "%#{q.downcase}%"
36
+ patterned_text = "#{@simple_search_pattern.gsub('q', search_term.try(:downcase))}"
58
37
 
59
38
  @simple_search_attributes.each do |attr|
60
- query += if query == ""
61
- "LOWER(#{attr.to_s}) LIKE ?"
62
- else
63
- " OR LOWER(#{attr.to_s}) LIKE ?"
64
- end
39
+ sql_query_condition << set_sql_query_condition(attr, sql_query_condition)
40
+ sql_query_values << patterned_text
41
+ end
42
+
43
+ if block.is_a? Proc
44
+ sql_query_condition = "(#{sql_query_condition})"
45
+ extended_query = block.call(search_term)
46
+ end
47
+
48
+ if !extended_query.nil?
49
+ sql_query_values, sql_query_condition = extend_simple_search(extended_query,
50
+ sql_query_condition,
51
+ sql_query_values)
52
+ end
53
+ sql_query = [sql_query_condition, sql_query_values]
54
+
55
+ where(sql_query.try(:flatten))
56
+ end
57
+
58
+ private
59
+
60
+ def set_pattern(pattern)
61
+ pattern = RubySimpleSearch::LIKE_PATTERNS[pattern.to_sym] rescue nil
62
+ raise RubySimpleSearch::Error::INVALID_PATTERN if pattern.nil?
63
+ @simple_search_pattern = pattern
64
+ end
65
+
66
+ def extend_simple_search(extended_query, sql_query_condition, sql_query_values)
67
+ raise RubySimpleSearch::Error::INVALID_TYPE unless extended_query.is_a?(Array)
68
+ extended_query_condition = extended_query[0]
69
+ extended_query_values = extended_query - [extended_query[0]]
65
70
 
71
+ if extended_query_condition.count('?') != (extended_query_values.size)
72
+ raise RubySimpleSearch::Error::INVALID_CONDITION
66
73
  end
67
74
 
68
- where([query] + Array.new(@simple_search_attributes.size, patterned_text))
75
+ sql_query_condition = [sql_query_condition, extended_query_condition].join(' ')
76
+ sql_query_values = sql_query_values + extended_query_values
77
+
78
+ [sql_query_values, sql_query_condition]
79
+ end
80
+
81
+ def set_sql_query_condition(attr, sql_query_condition)
82
+ return "LOWER(#{attr.to_s}) LIKE ?" if sql_query_condition.blank?
83
+ " OR LOWER(#{attr.to_s}) LIKE ?"
69
84
  end
85
+
70
86
  end
71
87
  end
@@ -0,0 +1,10 @@
1
+ require "ruby_simple_search/errors"
2
+
3
+ module RubySimpleSearch
4
+ module Error
5
+ ATTRIBUTES_MISSING = "Simple search attributes are missing"
6
+ INVALID_TYPE = "Extended query is not an array type"
7
+ INVALID_CONDITION = "Extended query's array conditions are wrong"
8
+ INVALID_PATTERN = "Pattern is wrong. it should be in the list #{RubySimpleSearch::LIKE_PATTERNS.keys}"
9
+ end
10
+ end
@@ -0,0 +1,4 @@
1
+ module RubySimpleSearch
2
+ LIKE_PATTERNS = { plain: 'q', underscore: '_q_', beginning: 'q%',
3
+ ending: '%q', containing: '%q%'}
4
+ end
@@ -1,3 +1,3 @@
1
1
  module RubySimpleSearch
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -14,6 +14,8 @@ Gem::Specification.new do |gem|
14
14
 
15
15
  gem.add_dependency "activesupport", ">= 3.0.0"
16
16
  gem.add_dependency "activerecord", ">= 3.0.0"
17
+ gem.add_dependency "sqlite3"
18
+ gem.add_development_dependency "rspec"
17
19
 
18
20
  gem.files = `git ls-files`.split($/)
19
21
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
data/spec/lib/user.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'active_record'
2
+ require_relative "../../lib/ruby_simple_search.rb"
3
+
4
+ class User < ActiveRecord::Base
5
+ include RubySimpleSearch
6
+
7
+ simple_search_attributes :name, :email, :contact, :address
8
+ end
data/spec/lib/user2.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'active_record'
2
+ require_relative "../../lib/ruby_simple_search.rb"
3
+
4
+ class User2 < ActiveRecord::Base
5
+ include RubySimpleSearch
6
+ end
@@ -0,0 +1,40 @@
1
+ require 'rspec'
2
+ require 'active_record'
3
+
4
+ ActiveRecord::Migration.verbose = false
5
+
6
+ RSpec.configure do |config|
7
+ config.before(:all) do
8
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
9
+ create_database
10
+ User.create :email => "alice@example.com",
11
+ :name => "alice", :address => "usa",
12
+ :contact => '12345', :age => 60
13
+ User.create :email => "bob@example.com",
14
+ :name => "bob", :address => "usa",
15
+ :contact => "56789", :age => 26
16
+ end
17
+
18
+ config.after(:all) do
19
+ drop_database
20
+ end
21
+ end
22
+
23
+ def create_database
24
+ ActiveRecord::Schema.define(:version => 1) do
25
+ create_table :users do |t|
26
+ t.string :name
27
+ t.text :address
28
+ t.text :contact
29
+ t.string :email
30
+ t.integer :age
31
+ t.timestamps
32
+ end
33
+ end
34
+ end
35
+
36
+ def drop_database
37
+ ActiveRecord::Base.connection.tables.each do |table|
38
+ ActiveRecord::Base.connection.drop_table(table)
39
+ end
40
+ end
data/spec/user_spec.rb ADDED
@@ -0,0 +1,112 @@
1
+ require 'spec_helper'
2
+ require_relative "../spec/lib/user.rb"
3
+ require_relative "../spec/lib/user2.rb"
4
+
5
+ describe User do
6
+
7
+ describe ".simple_search_attributes" do
8
+
9
+ it "returns an exception if simple_search_attributes is not called while loading the model" do
10
+ expect { User2.simple_search('usa') }.to raise_error(RubySimpleSearch::Error::ATTRIBUTES_MISSING)
11
+ end
12
+
13
+ it "sets simple_search_attributes" do
14
+ User2.simple_search_attributes :name, :contact
15
+ expect(User2.instance_variable_get("@simple_search_attributes")).to eq([:name, :contact])
16
+ end
17
+
18
+ it "has default pattern" do
19
+ User2.simple_search_attributes :name, :contact
20
+ expect(User2.instance_variable_get("@simple_search_pattern")).to eq('%q%')
21
+ end
22
+
23
+ it "can have patterns like plain, beginning, ending, containing and underscore" do
24
+ User2.simple_search_attributes :name, :contact, :pattern => :plain
25
+ expect(User2.instance_variable_get("@simple_search_pattern")).to eq('q')
26
+ User2.simple_search_attributes :name, :contact, :pattern => :beginning
27
+ expect(User2.instance_variable_get("@simple_search_pattern")).to eq('q%')
28
+ User2.simple_search_attributes :name, :contact, :pattern => :ending
29
+ expect(User2.instance_variable_get("@simple_search_pattern")).to eq('%q')
30
+ User2.simple_search_attributes :name, :contact, :pattern => :containing
31
+ expect(User2.instance_variable_get("@simple_search_pattern")).to eq('%q%')
32
+ User2.simple_search_attributes :name, :contact, :pattern => :underscore
33
+ expect(User2.instance_variable_get("@simple_search_pattern")).to eq('_q_')
34
+ end
35
+
36
+ it "should raise an exception if pattern is wrong" do
37
+ expect{ User2.simple_search_attributes :name, :pattern => 'wrong' }.to raise_error(RubySimpleSearch::Error::INVALID_PATTERN)
38
+ end
39
+ end
40
+
41
+ describe ".simple_search" do
42
+ context "Simple" do
43
+ it "searches users whose name are 'alice'" do
44
+ user = User.find_by_name('alice')
45
+ users = User.simple_search('alice')
46
+ users.should include(user)
47
+ end
48
+
49
+ it "returns empty records if contact number does not exist" do
50
+ users = User.simple_search('343434')
51
+ users.should be_empty
52
+ end
53
+
54
+ it "searches user records if user belongs to 'USA'" do
55
+ users = User.where(:address => 'usa')
56
+ searched_users = User.simple_search('usa')
57
+ expect(users.to_a).to eq(searched_users.to_a)
58
+ end
59
+
60
+ it "searches the records with beginning pattern" do
61
+ users = User.where("name like ?", 'bo%')
62
+ User.simple_search_attributes :name, :contact, :address, :pattern => :beginning
63
+ searched_users = User.simple_search('bo')
64
+ expect(users.count).to eq(searched_users.count)
65
+ end
66
+
67
+ it "searches the records with ending pattern" do
68
+ users = User.where("name like ?", '%ce')
69
+ User.simple_search_attributes :name, :contact, :address, :pattern => :ending
70
+ searched_users = User.simple_search('ce')
71
+ expect(users.count).to eq(searched_users.count)
72
+ end
73
+
74
+ it "searches the records with underscore pattern" do
75
+ users = User.where("name like ?", 'ce')
76
+ User.simple_search_attributes :name, :contact, :address, :pattern => :underscore
77
+ searched_users = User.simple_search('ce')
78
+ expect(users.count).to eq(searched_users.count)
79
+ end
80
+
81
+ it "searches the records with plain pattern" do
82
+ users = User.where("name like ?", 'bob')
83
+ User.simple_search_attributes :name, :contact, :address, :pattern => :plain
84
+ searched_users = User.simple_search('bob')
85
+ expect(users.count).to eq(searched_users.count)
86
+ end
87
+ end
88
+
89
+ context "Extendable" do
90
+ it "returns users who live in usa and their age shoule be greater than 50" do
91
+ User.simple_search_attributes :name, :contact, :address, :pattern => :plain
92
+ users = User.where(:age => 60)
93
+ searched_users = User.simple_search('usa') do |search_term|
94
+ ['AND age > ?', 50]
95
+ end
96
+ expect(users.to_a).to eq(searched_users.to_a)
97
+ end
98
+
99
+ it "returns exception if array condition is wrong in simple_search block" do
100
+ expect{ User.simple_search('usa') do |search_term|
101
+ ['AND age > ?', 50, 60]
102
+ end }.to raise_error(RubySimpleSearch::Error::INVALID_CONDITION)
103
+ end
104
+
105
+ it "returns exception if return value is not an array type" do
106
+ expect{ User.simple_search('usa') do |search_term|
107
+ "Wrong return"
108
+ end }.to raise_error(RubySimpleSearch::Error::INVALID_TYPE)
109
+ end
110
+ end
111
+ end
112
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_simple_search
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-05-18 00:00:00.000000000 Z
12
+ date: 2013-12-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -43,6 +43,38 @@ dependencies:
43
43
  - - ! '>='
44
44
  - !ruby/object:Gem::Version
45
45
  version: 3.0.0
46
+ - !ruby/object:Gem::Dependency
47
+ name: sqlite3
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rspec
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '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: '0'
46
78
  description: It will search on the attributes that you provided to simple_search_attributes
47
79
  method
48
80
  email:
@@ -52,13 +84,20 @@ extensions: []
52
84
  extra_rdoc_files: []
53
85
  files:
54
86
  - .gitignore
87
+ - .rspec
55
88
  - Gemfile
56
89
  - LICENSE.txt
57
90
  - README.md
58
91
  - Rakefile
59
92
  - lib/ruby_simple_search.rb
93
+ - lib/ruby_simple_search/errors.rb
94
+ - lib/ruby_simple_search/like_pattern.rb
60
95
  - lib/ruby_simple_search/version.rb
61
96
  - ruby_simple_search.gemspec
97
+ - spec/lib/user.rb
98
+ - spec/lib/user2.rb
99
+ - spec/spec_helper.rb
100
+ - spec/user_spec.rb
62
101
  homepage: https://github.com/mechanicles/ruby_simple_search
63
102
  licenses: []
64
103
  post_install_message:
@@ -79,8 +118,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
79
118
  version: '0'
80
119
  requirements: []
81
120
  rubyforge_project:
82
- rubygems_version: 1.8.24
121
+ rubygems_version: 1.8.25
83
122
  signing_key:
84
123
  specification_version: 3
85
124
  summary: Ruby simple search for ActiveRecord
86
- test_files: []
125
+ test_files:
126
+ - spec/lib/user.rb
127
+ - spec/lib/user2.rb
128
+ - spec/spec_helper.rb
129
+ - spec/user_spec.rb