ts_vector_tags 0.0.1

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.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in ts_vector_tags.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,39 @@
1
+ # TsVectorTags
2
+
3
+ A simple tagging library that uses the (fairly exotic) `ts_vector` type in PostgreSQL on top of ActiveRecord.
4
+
5
+ ## Requirements
6
+
7
+ * ActiveRecord
8
+ * a field `tags_vector` of type `tsvector` on the underlying table
9
+
10
+ ## Usage
11
+
12
+ Tags can be set using either an array, or a comma separated list.
13
+
14
+ class Post < ActiveRecord::Base
15
+ include TsVectorTags
16
+
17
+ # ...
18
+ end
19
+
20
+ post = Post.new
21
+
22
+ post.tags = "bing, bong"
23
+ post.tags
24
+ => ['bing', 'bong']
25
+
26
+ post.tags = ['bing', 'bong']
27
+ post.tags
28
+ => ['bing', 'bong']
29
+
30
+ The including class has a scope:
31
+
32
+ Post.with_tags('Paris, Texas')
33
+ Post.with_tags('Paris', 'Texas')
34
+
35
+ Tags are normalized:
36
+
37
+ post.tags = [' wtf#$%^ &*??!']
38
+ post.tags
39
+ => ['wtf']
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,42 @@
1
+ require "ts_vector_tags/version"
2
+
3
+ module TsVectorTags
4
+ class MissingAttributeError < Exception; end
5
+
6
+ module Standardizer
7
+ class << self
8
+ def tagify(tags)
9
+ tags = tags.split(/\s*,\s*/) if tags.is_a?(String)
10
+ tags.map!{ |tag| self.normalize(tag) }
11
+ end
12
+
13
+ def normalize(tag)
14
+ tag.downcase.gsub(/[^[:alnum:]]/, "")
15
+ end
16
+ end
17
+ end
18
+
19
+ def self.included(base)
20
+ unless base.instance_methods.include?(:tags_vector) && base.instance_methods.include?(:tags_vector=)
21
+ msg = "The TsVectorTags mixin assumes that the underlying PostgreSQL table has a field `tags_vector` of type tsvector"
22
+ raise TsVectorTags::MissingAttributeError.new(msg)
23
+ end
24
+
25
+ base.class_eval do
26
+ scope :with_tags, lambda { |tags|
27
+ where("tags_vector @@ to_tsquery('simple', ?) ", TsVectorTags::Standardizer.tagify(tags).join(' & '))
28
+ }
29
+ end
30
+ end
31
+
32
+ def tags=(value)
33
+ return self.tags_vector = "" if value.nil?
34
+ self.tags_vector = TsVectorTags::Standardizer.tagify(value).map{ |tag| "'#{tag}'" }.join(' ')
35
+ end
36
+
37
+ def tags
38
+ return [] unless self.tags_vector
39
+ self.tags_vector.scan(/'(.+?)'/).flatten
40
+ end
41
+
42
+ end
@@ -0,0 +1,3 @@
1
+ module TsVectorTags
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1 @@
1
+ require 'ts_vector_tags'
@@ -0,0 +1,101 @@
1
+ require 'spec_helper'
2
+
3
+ describe TsVectorTags::Standardizer do
4
+ it "normalizes" do
5
+ TsVectorTags::Standardizer.normalize('abc-!@ #$ %^&*()123').should eq('abc123')
6
+ end
7
+
8
+ it "splits and normalizes a string" do
9
+ TsVectorTags::Standardizer.tagify('abc-!@ #$ , %^&*()123').should eq(['abc', '123'])
10
+ end
11
+
12
+ it "normalizes tags in an arrayarray" do
13
+ TsVectorTags::Standardizer.tagify(['abc-!@ #$ ', ' %^&*()123']).should eq(['abc', '123'])
14
+ end
15
+ end
16
+
17
+ class Thing
18
+ def self.scope(name, options = {}); end
19
+
20
+ attr_accessor :tags_vector
21
+ include TsVectorTags
22
+
23
+ end
24
+
25
+ describe TsVectorTags do
26
+ describe "accessors" do
27
+ let(:thing) { Thing.new }
28
+
29
+ describe "deleting tags" do
30
+ before :each do
31
+ thing.tags_vector = "'bing' 'bong'"
32
+ end
33
+
34
+ it "uses nil" do
35
+ thing.tags = nil
36
+ thing.tags.should eq([])
37
+ end
38
+
39
+ it "removes tags with an empty array" do
40
+ thing.tags = []
41
+ thing.tags.should eq([])
42
+ end
43
+
44
+ it "removes tags with an empty string" do
45
+ thing.tags = ""
46
+ thing.tags.should eq([])
47
+ end
48
+ end
49
+
50
+ it "assigns comma-separated strings" do
51
+ thing.tags = "bing, bong"
52
+ thing.tags_vector.should eq("'bing' 'bong'")
53
+ end
54
+
55
+ it "assigns arrays" do
56
+ thing.tags = ["bing", "bong"]
57
+ thing.tags_vector.should eq("'bing' 'bong'")
58
+ end
59
+
60
+ it "reads tag vectors" do
61
+ thing.tags_vector = "'bing' 'bong'"
62
+ thing.tags.should eq(['bing', 'bong'])
63
+ end
64
+ end
65
+
66
+ context "with the required attributes" do
67
+ it "does not raise an exception" do
68
+ lambda {
69
+ class GoodThing
70
+ def self.scope(name, options = {}); end
71
+ attr_accessor :tags_vector
72
+ include TsVectorTags
73
+ end
74
+ }.should_not raise_error
75
+ end
76
+ end
77
+
78
+ context "without a tags_vector attribute" do
79
+ it "raises a helpful exception when no tags_vector writer is present" do
80
+ lambda {
81
+ class OneBadThing
82
+ def self.scope(name, options = {}); end
83
+
84
+ attr_reader :tags_vector
85
+ include TsVectorTags
86
+ end
87
+ }.should raise_error(TsVectorTags::MissingAttributeError)
88
+ end
89
+
90
+ it "raises a helpful exception when no tags_vector reader is pressent" do
91
+ lambda {
92
+ class AnotherBadThing
93
+ def self.scope(name, options = {}); end
94
+
95
+ attr_writer :tags_vector
96
+ include TsVectorTags
97
+ end
98
+ }.should raise_error(TsVectorTags::MissingAttributeError)
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "ts_vector_tags/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "ts_vector_tags"
7
+ s.version = TsVectorTags::VERSION
8
+ s.authors = ["Simen Svale Skogsrud", "Katrina Owen"]
9
+ s.email = ["simen@bengler.no", "katrina@bengler.no"]
10
+ s.homepage = ""
11
+ s.summary = %q{Super simple tag mixin for postgresql and activerecord}
12
+ s.description = %q{Extremely simple, if somewhat exotic, mixin that uses the tsvector feature in postgresql to add tags to an ActiveRecord model.}
13
+
14
+ s.rubyforge_project = "ts_vector_tags"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {spec}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_development_dependency "rspec"
22
+ end
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ts_vector_tags
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Simen Svale Skogsrud
9
+ - Katrina Owen
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2011-11-18 00:00:00.000000000Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rspec
17
+ requirement: &2161651360 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: *2161651360
26
+ description: Extremely simple, if somewhat exotic, mixin that uses the tsvector feature
27
+ in postgresql to add tags to an ActiveRecord model.
28
+ email:
29
+ - simen@bengler.no
30
+ - katrina@bengler.no
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - .gitignore
36
+ - .rspec
37
+ - Gemfile
38
+ - README.md
39
+ - Rakefile
40
+ - lib/ts_vector_tags.rb
41
+ - lib/ts_vector_tags/version.rb
42
+ - spec/spec_helper.rb
43
+ - spec/ts_vector_tags_spec.rb
44
+ - ts_vector_tags.gemspec
45
+ homepage: ''
46
+ licenses: []
47
+ post_install_message:
48
+ rdoc_options: []
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ requirements: []
64
+ rubyforge_project: ts_vector_tags
65
+ rubygems_version: 1.8.10
66
+ signing_key:
67
+ specification_version: 3
68
+ summary: Super simple tag mixin for postgresql and activerecord
69
+ test_files: []