acts_as_tokenizable 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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