acts_as_tokenizable 0.7.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 17eaf4f8283785561ba5703894d935e0c54a527d
4
+ data.tar.gz: a19c66a85adf99293addc2bb3c3214cfc6544c1c
5
+ SHA512:
6
+ metadata.gz: db4f0327800efe794ff813630cb24df22c7852fcdb674851034cca68bb73790de70bad6fc84f5ddbcb57091679879628ce3a66a5b3e19ff727ac4bf634def1f4
7
+ data.tar.gz: 4f2443a43d80f329a32ad65f4b50a0aaea794fe9671a556654c416176cdc1182eb132bc8767e8a9abbe15a9c1e41e324df7af6b976908650b457dea2f874689f
@@ -0,0 +1 @@
1
+ service_name: travis-ci
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ Gemfile.lock
3
+ .byebug_history
4
+
@@ -0,0 +1,3 @@
1
+ ruby:
2
+ config_file: .ruby-style.yml
3
+
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --format progress
@@ -0,0 +1,3 @@
1
+ inherit_from: .rubocop_todo.yml
2
+ Documentation:
3
+ Enabled: false
@@ -0,0 +1,16 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2016-05-16 07:44:12 +0200 using RuboCop version 0.39.0.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 2
10
+ Metrics/AbcSize:
11
+ Max: 22
12
+
13
+ # Offense count: 2
14
+ # Configuration parameters: CountComments.
15
+ Metrics/MethodLength:
16
+ Max: 17
@@ -0,0 +1,7 @@
1
+ Style/StringLiterals:
2
+ Enabled: true
3
+ EnforcedStyle: single_quotes
4
+ Style/DotPosition:
5
+ Enabled: true
6
+ EnforcedStyle: leading
7
+
@@ -0,0 +1,9 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.3
4
+ cache: bundler
5
+ script: bundle exec rake
6
+ addons:
7
+ code_climate:
8
+ repo_token:
9
+ secure: EEQ24se1YhmTSlpHI47yrlAQi1s36WOj9Sk9WDecpKjZFYJ8gSyS0nVhUAPi4rG84KyJARUd0uGNHBOhJ/ZH2YN3Ge4kxzJZEbSKQ9F65MW0VZelcL5DtIsdEoiuZ6BZ1fGM9RYnPnk4jwHn8JeZ/XyVPmSvhmShmwwcWNjY5hqGw2KWHqOvgiw9fWNn/9r1iq+pUQAjqrsjjeih5fC5nrh570mt1sY51ogFbnfI6vO5JpqLcK6v1PO4gejYharfE4zqMiBwWf4HWduyQNUVC/4pKa8ohwh8yQoInieLcweLosOTRPulBuE9Hu3EXSv4JRbNhBtREjRva8YfG7epSlQddlyc5LITwZgpw2nLDLxkGjXH0JZ9g02y5uorCiwcU3amVtrxusqpYmq6zl7o6LxNnPhCbWrMdRveXmTPpS/rL5G8DAKS7/VRylXvy4nrPbbpvwrNicyRJeFrgXREA0KXaYAOTGL4C4yrhY0LPxjbwGzL6goD2U6dxja0SDovyWPbiXIlDxPX4tn09LxdzPMdHBqfFb/oqJiLrn0vp7kn736VrvhMfU3BweLEjlCXbSmLy+h5l8d118EpZOs/BnOdqjqtAb5eztiyBHZaaJG1H6cAxCST40yCx7nhAeEti5Zt/EVyBbUyZFcJiNbvQv5jbbaX7LA4nI4Y4pmduQA=
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in activerecord_reset_pk_sequence.gemspec
4
+ gemspec
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2009 Splendeo
1
+ Copyright (c) 2012 Splendeo
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
@@ -1,9 +1,14 @@
1
1
  = acts_as_tokenizable
2
2
 
3
- Description goes here.
3
+ Add this gem to enable a simple analizer on fields suitable for searching.
4
+
5
+ {<img src="https://travis-ci.org/fjuan/acts_as_tokenizable.svg?branch=master" alt="Build Status" />}[https://travis-ci.org/fjuan/acts_as_tokenizable]
6
+ {<img src="https://codeclimate.com/github/fjuan/acts_as_tokenizable/badges/gpa.svg" />}[https://codeclimate.com/github/fjuan/acts_as_tokenizable]
7
+ {<img src="https://gemnasium.com/badges/github.com/fjuan/acts_as_tokenizable.svg" alt="Dependency Status" />}[https://gemnasium.com/github.com/fjuan/acts_as_tokenizable]
8
+ {<img src="https://coveralls.io/repos/github/fjuan/acts_as_tokenizable/badge.svg?branch=master" alt="Coverage Status" />}[https://coveralls.io/github/fjuan/acts_as_tokenizable?branch=master]
4
9
 
5
10
  == Note on Patches/Pull Requests
6
-
11
+
7
12
  * Fork the project.
8
13
  * Make your feature addition or bug fix.
9
14
  * Add tests for it. This is important so I don't break it in a
data/Rakefile CHANGED
@@ -1,52 +1,6 @@
1
- require 'rubygems'
2
- require 'rake'
1
+ require 'rspec/core/rake_task'
2
+ require 'bundler/gem_tasks'
3
3
 
4
- begin
5
- require 'jeweler'
6
- Jeweler::Tasks.new do |gem|
7
- gem.name = "acts_as_tokenizable"
8
- gem.summary = "Acts as tokenizable"
9
- gem.description = "Make ActiveRecord models easily searchable via tokens."
10
- gem.email = "github@splendeo.es"
11
- gem.homepage = "http://github.com/splendeo/acts_as_tokenizable"
12
- gem.authors = ["Enrique Garcia Cota", "Francisco de Juan"]
13
- gem.add_dependency "babosa", "~> 0.3.7"
14
- end
15
- Jeweler::GemcutterTasks.new
16
- rescue LoadError
17
- puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
18
- end
4
+ RSpec::Core::RakeTask.new(:spec)
19
5
 
20
- require 'rake/testtask'
21
- Rake::TestTask.new(:test) do |test|
22
- test.libs << 'lib' << 'test'
23
- test.pattern = 'test/**/test_*.rb'
24
- test.verbose = true
25
- end
26
-
27
- begin
28
- require 'rcov/rcovtask'
29
- Rcov::RcovTask.new do |test|
30
- test.libs << 'test'
31
- test.pattern = 'test/**/test_*.rb'
32
- test.verbose = true
33
- end
34
- rescue LoadError
35
- task :rcov do
36
- abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
37
- end
38
- end
39
-
40
- task :test => :check_dependencies
41
-
42
- task :default => :test
43
-
44
- require 'rake/rdoctask'
45
- Rake::RDocTask.new do |rdoc|
46
- version = File.exist?('VERSION') ? File.read('VERSION') : ""
47
-
48
- rdoc.rdoc_dir = 'rdoc'
49
- rdoc.title = "acts_as_tokenizable #{version}"
50
- rdoc.rdoc_files.include('README*')
51
- rdoc.rdoc_files.include('lib/**/*.rb')
52
- end
6
+ task default: :spec
@@ -1,56 +1,31 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
1
  # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'acts_as_tokenizable/version'
5
5
 
6
- Gem::Specification.new do |s|
7
- s.name = %q{acts_as_tokenizable}
8
- s.version = "0.7.0"
6
+ Gem::Specification.new do |gem|
7
+ gem.authors = ['Enrique Garcia Cota', 'Francisco Juan']
8
+ gem.email = 'francisco.juan@gmail.com'
9
+ gem.description = 'Make ActiveRecord models easily searchable via tokens.'
10
+ gem.summary = 'Acts as tokenizable'
11
+ gem.homepage = 'https://github.com/fjuan/acts_as_tokenizable'
12
+ gem.license = 'MIT'
13
+ gem.extra_rdoc_files = ['README.rdoc']
9
14
 
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = [%q{Enrique Garcia Cota}, %q{Francisco de Juan}]
12
- s.date = %q{2012-03-21}
13
- s.description = %q{Make ActiveRecord models easily searchable via tokens.}
14
- s.email = %q{github@splendeo.es}
15
- s.extra_rdoc_files = [
16
- "LICENSE",
17
- "README",
18
- "README.rdoc"
19
- ]
20
- s.files = [
21
- "LICENSE",
22
- "README",
23
- "README.rdoc",
24
- "Rakefile",
25
- "VERSION",
26
- "acts_as_tokenizable.gemspec",
27
- "init.rb",
28
- "lib/acts_as_tokenizable.rb",
29
- "lib/acts_as_tokenizable/acts_as_tokenizable.rb",
30
- "lib/acts_as_tokenizable/string_utils.rb",
31
- "lib/tasks/acts_as_tokenizable.rake",
32
- "test/helper.rb",
33
- "test/test_acts_as_tokenizable.rb"
34
- ]
35
- s.homepage = %q{http://github.com/splendeo/acts_as_tokenizable}
36
- s.require_paths = [%q{lib}]
37
- s.rubygems_version = %q{1.8.6}
38
- s.summary = %q{Acts as tokenizable}
39
- s.test_files = [
40
- "test/helper.rb",
41
- "test/test_acts_as_tokenizable.rb"
42
- ]
15
+ gem.files = `git ls-files`.split($OUTPUT_RECORD_SEPARATOR)
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.name = 'acts_as_tokenizable'
19
+ gem.require_paths = ['lib']
20
+ gem.version = ActsAsTokenizable::VERSION
43
21
 
44
- if s.respond_to? :specification_version then
45
- s.specification_version = 3
22
+ gem.add_runtime_dependency 'activerecord'
23
+ gem.add_runtime_dependency 'babosa'
46
24
 
47
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
48
- s.add_runtime_dependency(%q<babosa>, ["~> 0.3.7"])
49
- else
50
- s.add_dependency(%q<babosa>, ["~> 0.3.7"])
51
- end
52
- else
53
- s.add_dependency(%q<babosa>, ["~> 0.3.7"])
54
- end
25
+ gem.add_development_dependency 'rake'
26
+ gem.add_development_dependency 'rspec'
27
+ gem.add_development_dependency 'sqlite3'
28
+ gem.add_development_dependency 'coveralls'
29
+ gem.add_development_dependency 'byebug'
30
+ gem.add_development_dependency 'pry-byebug'
55
31
  end
56
-
@@ -1,9 +1,19 @@
1
+ $LOAD_PATH << File.dirname(__FILE__)
2
+
3
+ require 'active_record'
1
4
  require 'acts_as_tokenizable/acts_as_tokenizable'
5
+ require 'acts_as_tokenizable/string_utils'
2
6
 
3
- class ActiveRecord::Base
4
- def self.acts_as_tokenizable(field_name=:token)
5
- include ActsAsTokenizable
6
- self.token_field_name = field_name
7
- self.before_save :tokenize
7
+ module ActsAsTokenizable
8
+ if defined?(Rails::Railtie)
9
+ class Railtie < Rails::Railtie
10
+ initializer 'acts_as_tokenizable.insert_into_active_record' do
11
+ ActiveSupport.on_load :active_record do
12
+ ActiveRecord::Base.send(:include, ActsAsTokenizable)
13
+ end
14
+ end
15
+ end
16
+ elsif defined?(ActiveRecord)
17
+ ActiveRecord::Base.send(:include, ActsAsTokenizable)
8
18
  end
9
19
  end
@@ -1,45 +1,64 @@
1
- require 'acts_as_tokenizable/string_utils'
2
-
3
1
  module ActsAsTokenizable
4
-
5
- # default to_token method. needs to have a "name" property on the object.
6
- # override for more complex token generation
7
- def to_token
8
- raise NoMethodError.new("You must redefine to_token in your model. Example: self.name.to_token()")
9
- end
10
-
11
- #makes self.<token_field_name>=self.to_token
12
- def tokenize
13
- self.send("#{self.class.token_field_name}=", self.to_token)
2
+ def self.included(base)
3
+ base.class_eval { extend ClassMethods }
14
4
  end
15
5
 
16
6
  module ClassMethods
17
7
  attr_accessor :token_field_name
18
8
 
19
- # search_token parameter is used by tokenized_by. This function allows for preparation
20
- # before tokenized_by function is invoked. Usually this means removing
21
- # stop words, replacing words.
9
+ def acts_as_tokenizable(field_name = :token)
10
+ include InstanceMethods
11
+ include TokenizedBy
12
+
13
+ before_save :tokenize
14
+
15
+ self.token_field_name = field_name
16
+ end
17
+
18
+ # search_token parameter is used by tokenized_by. This function allows for
19
+ # preparation before tokenized_by function is invoked. Usually this means
20
+ # removing stop words, replacing words.
22
21
  # By default it tokenizes each word and removes duplicates.
23
22
  def prepare_search_token(search_token)
24
23
  StringUtils.words_to_token(search_token)
25
24
  end
26
25
  end
27
26
 
28
- def self.included(base)
29
- base.class_eval do
30
- extend ClassMethods
27
+ module InstanceMethods
28
+ # default to_token method. needs to have a "name" property on the object.
29
+ # override for more complex token generation
30
+ def to_token
31
+ raise(
32
+ NoMethodError,
33
+ 'You must define to_token in your model. Example: self.name.to_token()'
34
+ )
35
+ end
36
+
37
+ # makes self.<token_field_name>=self.to_token
38
+ def tokenize
39
+ send("#{self.class.token_field_name}=", to_token)
40
+ end
41
+
42
+ def tokenize!
43
+ update_column(self.class.token_field_name, to_token)
44
+ end
45
+ end
46
+
47
+ module TokenizedBy
48
+ extend ActiveSupport::Concern
31
49
 
32
- scope :tokenized_by, lambda {|search_token|
50
+ included do
51
+ scope :tokenized_by, lambda { |search_token|
33
52
  search_strings = []
34
53
  search_values = []
35
- StringUtils.words(prepare_search_token(search_token)).each do |w|
36
- if w[0,1] == '-'
54
+ StringUtils.words(search_token).each do |w|
55
+ if w[0, 1] == '-'
37
56
  search_strings.push("#{table_name}.#{token_field_name} NOT LIKE ?")
38
- search_values.push("%#{w[1,w.length]}%")
39
57
  else
40
58
  search_strings.push("#{table_name}.#{token_field_name} LIKE ?")
41
- search_values.push("%#{w}%")
42
59
  end
60
+ tokenized_word = StringUtils.to_token(w)
61
+ search_values.push("%#{tokenized_word}%")
43
62
  end
44
63
  where([search_strings.join(' AND '), *search_values])
45
64
  }
@@ -1,33 +1,35 @@
1
1
  require 'babosa' # make sure that babosa is loaded
2
2
 
3
3
  module ActsAsTokenizable
4
-
5
4
  module StringUtils
6
-
7
- #returns true if numeric, false, otherwise
5
+ # returns true if numeric, false, otherwise
8
6
  def self.numeric?(str)
9
- true if Float(str) rescue
7
+ true if Float(str)
8
+ rescue
10
9
  false
11
10
  end
12
11
 
13
- #returns an array of strings containing the words on this string. removes spaces, strange chars, etc
12
+ # returns an array of strings containing the words on this string. Removes
13
+ # spaces, strange chars, etc
14
14
  def self.words(str)
15
- str.gsub(/[^\w|-]/, ' ').split
15
+ str.split(/[\s|\.|,]+/)
16
16
  end
17
17
 
18
- #removes certain words from a string.
18
+ # removes certain words from a string.
19
19
  # As a side-effect, all word-separators are converted to the separator char
20
20
  def self.remove_words(str, words_array, separator = ' ')
21
21
  (words(str) - words_array).join separator
22
22
  end
23
23
 
24
- # replaces certain words on a string.
24
+ # replaces certain words on a string.
25
25
  # As a side-effect, all word-separators are converted to the separator char
26
26
  def self.replace_words(str, replacements, separator = ' ')
27
27
  replaced_words = words(str)
28
- replacements.each do |candidates,replacement|
28
+ replacements.each do |candidates, replacement|
29
29
  candidates.each do |candidate|
30
- replaced_words=replaced_words.collect {|w| w==candidate ? replacement : w}
30
+ replaced_words = replaced_words.collect do |w|
31
+ w == candidate ? replacement : w
32
+ end
31
33
  end
32
34
  end
33
35
  replaced_words.join separator
@@ -44,17 +46,23 @@ module ActsAsTokenizable
44
46
  str.split(/(\d+)/).map { |v| v =~ /\d/ ? v.to_i : v }
45
47
  end
46
48
 
47
- #convert into something that can be used as an indexation key
48
- def self.to_token(str, max_length=255)
49
+ # convert into something that can be used as an indexation key
50
+ def self.to_token(str, max_length = 255)
49
51
  # to_slug and normalize are provided by the 'babosa' gem
50
- str = str.to_slug.normalize.strip.downcase.gsub(/[^\w|-]/, '') #remove all non-alphanumeric but hyphen (-)
51
- str = str.squeeze unless numeric?(str) #remove duplicates, except on pure numbers
52
- return str[0..(max_length-1)]
52
+ # remove all non-alphanumeric but hyphen (-)
53
+ str = str.to_slug.normalize.strip.downcase.gsub(/[\s|\.|,]+/, '')
54
+ # remove duplicates, except on pure numbers
55
+ str = str.squeeze unless numeric?(str)
56
+ str[0..(max_length - 1)]
53
57
  end
54
58
 
55
- #tokenizes each word individually, and joins the word with the separator char.
56
- def self.words_to_token(str, max_length=255, separator = ' ')
57
- words(str).collect{|w| to_token(w)}.uniq.join(separator)[0..(max_length-1)]
59
+ # tokenizes each word individually and joins the word with the separator
60
+ def self.words_to_token(str, max_length = 255, separator = ' ')
61
+ words(str)
62
+ .collect { |w| to_token(w) }
63
+ .uniq
64
+ .join(separator)
65
+ .slice(0, max_length)
58
66
  end
59
67
  end
60
68
  end
@@ -0,0 +1,3 @@
1
+ module ActsAsTokenizable
2
+ VERSION = '0.9.0'.freeze
3
+ end
@@ -1,54 +1,52 @@
1
1
  namespace :tokens do
2
- desc "Generates the token for objects without tokens."
3
- task :generate => :environment do
2
+ desc 'Generates the token for objects without tokens.'
3
+ task generate: :environment do
4
4
  tokenize_models
5
5
  end
6
6
 
7
- desc "Re-builds the token for all objects."
8
- task :regenerate => :environment do
7
+ desc 'Re-builds the token for all objects.'
8
+ task regenerate: :environment do
9
9
  tokenize_models(true)
10
10
  end
11
11
  end
12
12
 
13
13
  def array_of_active_record_models
14
- Dir.glob(RAILS_ROOT + '/app/models/*.rb').each { |file| require file }
15
-
16
- models_with_token = ActiveRecord::Base.send(:subclasses).select{|m| m.respond_to?(:tokenized_by)}
14
+ Rails.application.eager_load!
15
+ ActiveRecord::Base.descendants.select { |m| m.respond_to? :tokenized_by }
17
16
  end
18
-
17
+
19
18
  def tokenize_records(records)
20
19
  total_count = records.size
21
-
20
+
22
21
  count = 0
23
-
22
+
24
23
  records.each do |record|
25
- record.tokenize #this generates tokens
26
- record.save false #this saves without checking validations
24
+ record.tokenize!
27
25
  count += 1
28
26
  print "\r#{count}/#{total_count}"
29
- GC.start if count % 1000 == 0 #launch garbage collection each 1000 registers
27
+ # launch garbage collection each 1000 registers
28
+ GC.start if count % 1000 == 0
30
29
  end
31
- puts ""
30
+ puts ''
32
31
  end
33
-
32
+
34
33
  def tokenize_models(regenerate = false)
35
- start = Time.now
36
- puts "Start token generation"
37
- puts "++++++++++++++++++++++++++++++++"
38
-
34
+ start = Time.current
35
+ puts 'Start token generation'
36
+ puts '++++++++++++++++++++++++++++++++'
37
+
39
38
  array_of_active_record_models.each do |model|
40
- puts "Generating new tokens for #{model.name.pluralize}"
41
-
42
- conditions = "#{model.token_field_name} IS NULL OR #{model.token_field_name} = ''" unless regenerate
43
-
44
- records_without_token = model.all(:conditions => conditions)
45
- if records_without_token.size > 0
39
+ puts "Generating new tokens for #{model.name.pluralize}"
40
+ field_name = model.token_field_name
41
+ sql_conds = "#{field_name} IS NULL OR #{field_name} = ''" unless regenerate
42
+
43
+ records_without_token = model.all(conditions: sql_conds)
44
+ if !records_without_token.empty?
46
45
  tokenize_records(records_without_token)
47
46
  else
48
- puts "There are no records without token"
49
- puts "++++++++++++++++++++++++++++++++"
47
+ puts 'There are no records without token'
48
+ puts '++++++++++++++++++++++++++++++++'
50
49
  end
51
50
  end
52
- puts "Elapsed time " + (Time.now - start).seconds.to_s + " seconds"
53
-
51
+ puts "Elapsed time #{(Time.current - start).seconds} seconds"
54
52
  end
@@ -0,0 +1,72 @@
1
+ require 'spec_helper'
2
+ require 'support_helper'
3
+
4
+ describe ActiveRecord do
5
+ describe 'classes with acts_as_tokenizable' do
6
+ it 'respond to `tokenized_by`' do
7
+ expect(Friend.methods).to include(:tokenized_by)
8
+ end
9
+
10
+ it 'raises an error if `to_token` method is not defined' do
11
+ expect { Enemy.to_token }.to raise_error(NoMethodError)
12
+ end
13
+
14
+ describe 'instances' do
15
+ it 'include to_token and tokenize methods' do
16
+ expect(Friend.instance_methods)
17
+ .to include(:tokenize, :tokenize!, :to_token)
18
+ end
19
+
20
+ it 'update the token field after creating an object' do
21
+ friend = Friend.new name: 'John', email: 'john@example.com', age: 30
22
+ expect(friend.token).to be_nil
23
+ friend.save
24
+ expect(friend.token).to eq('john 30')
25
+ end
26
+
27
+ it 'allow different token field name' do
28
+ malmo = City.create name: 'Malmö'
29
+ expect(malmo.tokenized_name).to eq('malmo')
30
+ end
31
+ end
32
+
33
+ describe 'scope tokenized_by' do
34
+ before do
35
+ Friend.delete_all
36
+
37
+ Friend.create name: 'Tomás', age: 31
38
+ Friend.create name: 'Rafa', age: 25
39
+ Friend.create name: 'Matthias', age: 35
40
+ Friend.create name: 'Mamá', age: 30
41
+ end
42
+
43
+ it 'finds records with tokenized string' do
44
+ expect(Friend.tokenized_by('as').count).to eq(2)
45
+ end
46
+
47
+ it 'finds records with tokenized with number' do
48
+ expect(Friend.tokenized_by('3').count).to eq(3)
49
+ end
50
+
51
+ it 'finds records with duplicated characters' do
52
+ expect(Friend.tokenized_by('mathias').count).to eq(1)
53
+ expect(Friend.tokenized_by('matthias').count).to eq(1)
54
+ end
55
+
56
+ it 'excludes records with negative token' do
57
+ expect(Friend.tokenized_by('-To').count).to eq(3)
58
+ end
59
+
60
+ it 'combines tokens' do
61
+ expect(Friend.tokenized_by('-To 5').count).to eq(2)
62
+ end
63
+ end
64
+ end
65
+
66
+ describe 'classes without acts_as_tokenizable' do
67
+ it 'does not include to_token and tokenize methods' do
68
+ expect(Pet.instance_methods)
69
+ .to_not include(:tokenize, :tokenize!, :to_token)
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,7 @@
1
+ require 'coveralls'
2
+ Coveralls.wear!
3
+
4
+ $LOAD_PATH << File.dirname(__FILE__) + '/../lib'
5
+
6
+ require 'acts_as_tokenizable'
7
+ require 'byebug'
@@ -0,0 +1,82 @@
1
+ require 'spec_helper'
2
+
3
+ module ActsAsTokenizable
4
+ describe StringUtils do
5
+ describe '.numeric?' do
6
+ it 'returns true with a float' do
7
+ expect(described_class.numeric?('1.2')).to be_truthy
8
+ end
9
+
10
+ it 'returns true with an integer' do
11
+ expect(described_class.numeric?('1')).to be_truthy
12
+ end
13
+
14
+ it 'returns true with a negative number' do
15
+ expect(described_class.numeric?('-11')).to be_truthy
16
+ end
17
+
18
+ it 'returns false with a string' do
19
+ expect(described_class.numeric?('1a')).to be_falsy
20
+ end
21
+ end
22
+
23
+ describe '.words' do
24
+ it 'splits a string into by word separators' do
25
+ example = 'una mamá española aterrizó en Götemborg-int, Suecia.'
26
+
27
+ expect(described_class.words(example))
28
+ .to match_array %w(una mamá española aterrizó en Götemborg-int Suecia)
29
+ end
30
+ end
31
+
32
+ describe '.remove_words' do
33
+ it 'returns a string without the specified list of words' do
34
+ sentence = 'a b c d e f g'
35
+ words_to_remove = %w(c e f)
36
+ expect(described_class.remove_words(sentence, words_to_remove, ' '))
37
+ .to eq('a b d g')
38
+ end
39
+
40
+ it 'remove multiples occurences of a word' do
41
+ sentence = 'a b a d a f g'
42
+ words_to_remove = %w(a f)
43
+ expect(described_class.remove_words(sentence, words_to_remove, ' '))
44
+ .to eq('b d g')
45
+ end
46
+ end
47
+
48
+ describe '.to_token' do
49
+ it 'transforms tildes and letter modifications' do
50
+ examples = {
51
+ 'mamá' => 'mama',
52
+ 'éxtasis' => 'extasis',
53
+ 'maría' => 'maria',
54
+ 'camión' => 'camion',
55
+ 'Úrsula' => 'ursula',
56
+ 'Umeå' => 'umea',
57
+ 'Gävle' => 'gavle',
58
+ 'Malmö' => 'malmo',
59
+ 'terraza' => 'teraza',
60
+ 'España' => 'espana'
61
+ }
62
+
63
+ examples.each do |string, expected_token|
64
+ expect(described_class.to_token(string)).to eq(expected_token)
65
+ end
66
+ end
67
+
68
+ it 'removes duplicate characters' do
69
+ expect(described_class.to_token('terraza')).to eq('teraza')
70
+ end
71
+ end
72
+
73
+ describe '.words_to_token' do
74
+ it 'converts a string into something that can be used as an index key' do
75
+ example = 'una mamá española aterrizó en Götemborg-int, Suecia.'
76
+
77
+ expect(described_class.words_to_token(example))
78
+ .to eq('una mama espanola aterizo en gotemborg-int suecia')
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,56 @@
1
+ class Pet < ActiveRecord::Base
2
+ end
3
+
4
+ class Enemy < ActiveRecord::Base
5
+ acts_as_tokenizable :token
6
+ end
7
+
8
+ class Friend < ActiveRecord::Base
9
+ acts_as_tokenizable :token
10
+
11
+ def to_token
12
+ string_to_token = [name, age].join(' ')
13
+ ActsAsTokenizable::StringUtils.words_to_token(string_to_token)
14
+ end
15
+ end
16
+
17
+ class City < ActiveRecord::Base
18
+ acts_as_tokenizable :tokenized_name
19
+
20
+ def to_token
21
+ ActsAsTokenizable::StringUtils.words_to_token(name)
22
+ end
23
+ end
24
+
25
+ ActiveRecord::Base.establish_connection(
26
+ adapter: 'sqlite3',
27
+ database: ':memory:'
28
+ )
29
+
30
+ ActiveRecord::Base.logger
31
+ ActiveRecord::Schema.define do
32
+ self.verbose = false
33
+ end
34
+
35
+ ActiveRecord::Schema.define(version: 1) do
36
+ create_table :pets do |t|
37
+ t.column :name, :string
38
+ t.column :owner, :string
39
+ end
40
+ end
41
+
42
+ ActiveRecord::Schema.define(version: 2) do
43
+ create_table :friends do |t|
44
+ t.column :name, :string
45
+ t.column :email, :string
46
+ t.column :age, :integer
47
+ t.column :token, :text
48
+ end
49
+ end
50
+
51
+ ActiveRecord::Schema.define(version: 3) do
52
+ create_table :cities do |t|
53
+ t.column :name, :string
54
+ t.column :tokenized_name, :text
55
+ end
56
+ end
metadata CHANGED
@@ -1,74 +1,183 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acts_as_tokenizable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
5
- prerelease:
4
+ version: 0.9.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Enrique Garcia Cota
9
- - Francisco de Juan
8
+ - Francisco Juan
10
9
  autorequire:
11
10
  bindir: bin
12
11
  cert_chain: []
13
- date: 2012-03-21 00:00:00.000000000Z
12
+ date: 2016-06-26 00:00:00.000000000 Z
14
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activerecord
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
15
28
  - !ruby/object:Gem::Dependency
16
29
  name: babosa
17
- requirement: &17284020 !ruby/object:Gem::Requirement
18
- none: false
30
+ requirement: !ruby/object:Gem::Requirement
19
31
  requirements:
20
- - - ~>
32
+ - - ">="
21
33
  - !ruby/object:Gem::Version
22
- version: 0.3.7
34
+ version: '0'
23
35
  type: :runtime
24
36
  prerelease: false
25
- version_requirements: *17284020
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rake
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: rspec
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: sqlite3
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: coveralls
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ - !ruby/object:Gem::Dependency
99
+ name: byebug
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ - !ruby/object:Gem::Dependency
113
+ name: pry-byebug
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
26
126
  description: Make ActiveRecord models easily searchable via tokens.
27
- email: github@splendeo.es
127
+ email: francisco.juan@gmail.com
28
128
  executables: []
29
129
  extensions: []
30
130
  extra_rdoc_files:
31
- - LICENSE
32
- - README
33
131
  - README.rdoc
34
132
  files:
133
+ - ".coveralls.yml"
134
+ - ".gitignore"
135
+ - ".hound.yml"
136
+ - ".rspec"
137
+ - ".rubocop.yml"
138
+ - ".rubocop_todo.yml"
139
+ - ".ruby-style.yml"
140
+ - ".travis.yml"
141
+ - Gemfile
35
142
  - LICENSE
36
- - README
37
143
  - README.rdoc
38
144
  - Rakefile
39
- - VERSION
40
145
  - acts_as_tokenizable.gemspec
41
- - init.rb
42
146
  - lib/acts_as_tokenizable.rb
43
147
  - lib/acts_as_tokenizable/acts_as_tokenizable.rb
44
148
  - lib/acts_as_tokenizable/string_utils.rb
149
+ - lib/acts_as_tokenizable/version.rb
45
150
  - lib/tasks/acts_as_tokenizable.rake
46
- - test/helper.rb
47
- - test/test_acts_as_tokenizable.rb
48
- homepage: http://github.com/splendeo/acts_as_tokenizable
49
- licenses: []
151
+ - spec/acts_as_tokenizable_spec.rb
152
+ - spec/spec_helper.rb
153
+ - spec/string_utils_spec.rb
154
+ - spec/support_helper.rb
155
+ homepage: https://github.com/fjuan/acts_as_tokenizable
156
+ licenses:
157
+ - MIT
158
+ metadata: {}
50
159
  post_install_message:
51
160
  rdoc_options: []
52
161
  require_paths:
53
162
  - lib
54
163
  required_ruby_version: !ruby/object:Gem::Requirement
55
- none: false
56
164
  requirements:
57
- - - ! '>='
165
+ - - ">="
58
166
  - !ruby/object:Gem::Version
59
167
  version: '0'
60
168
  required_rubygems_version: !ruby/object:Gem::Requirement
61
- none: false
62
169
  requirements:
63
- - - ! '>='
170
+ - - ">="
64
171
  - !ruby/object:Gem::Version
65
172
  version: '0'
66
173
  requirements: []
67
174
  rubyforge_project:
68
- rubygems_version: 1.8.6
175
+ rubygems_version: 2.6.4
69
176
  signing_key:
70
- specification_version: 3
177
+ specification_version: 4
71
178
  summary: Acts as tokenizable
72
179
  test_files:
73
- - test/helper.rb
74
- - test/test_acts_as_tokenizable.rb
180
+ - spec/acts_as_tokenizable_spec.rb
181
+ - spec/spec_helper.rb
182
+ - spec/string_utils_spec.rb
183
+ - spec/support_helper.rb
data/README DELETED
File without changes
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 0.7.0
data/init.rb DELETED
@@ -1 +0,0 @@
1
- require 'acts_as_tokenizable'
@@ -1,10 +0,0 @@
1
- require 'rubygems'
2
- require 'test/unit'
3
- require 'shoulda'
4
-
5
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
- $LOAD_PATH.unshift(File.dirname(__FILE__))
7
- require 'acts_as_tokenizable'
8
-
9
- class Test::Unit::TestCase
10
- end
@@ -1,7 +0,0 @@
1
- require 'helper'
2
-
3
- class TestActsAsTokenizable < Test::Unit::TestCase
4
- should "probably rename this file and start testing for real" do
5
- flunk "hey buddy, you should probably rename this file and start testing for real"
6
- end
7
- end