tagtical 1.1.1 → 1.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/lib/tagtical/tag.rb +10 -11
- data/lib/tagtical/tag_list.rb +26 -12
- data/lib/tagtical/taggable/cache.rb +2 -2
- data/lib/tagtical/taggable/core.rb +28 -14
- data/lib/tagtical/taggable.rb +10 -9
- data/spec/tagtical/tag_list_spec.rb +33 -4
- data/spec/tagtical/tag_spec.rb +2 -2
- data/spec/tagtical/taggable_spec.rb +34 -6
- metadata +14 -14
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.1.
|
1
|
+
1.1.2
|
data/lib/tagtical/tag.rb
CHANGED
@@ -227,25 +227,24 @@ module Tagtical
|
|
227
227
|
# <tt>only</tt> - An array of the following: :parents, :current, :children. Will construct conditions to query the current, parent, and/or children STI classes.
|
228
228
|
#
|
229
229
|
def finder_type_condition(*args)
|
230
|
-
options = convert_finder_type_arguments(*args)
|
231
|
-
type = convert_type_options(options[:scope])
|
230
|
+
scopes, options = convert_finder_type_arguments(*args)
|
232
231
|
|
233
232
|
# If we want [:current, :children] or [:current, :children, :parents] and we don't need the finder type condition,
|
234
233
|
# then that means we don't need a condition at all since we are at the top-level sti class and we are essentially
|
235
234
|
# searching the whole range of sti classes.
|
236
235
|
if klass && !klass.finder_needs_type_condition?
|
237
|
-
|
238
|
-
|
236
|
+
scopes.delete(:parents) # we are at the topmost level.
|
237
|
+
scopes = [] if scopes.sort==[:current, :children].sort # no condition is required if we want the current AND the children.
|
239
238
|
end
|
240
239
|
|
241
240
|
sti_names = []
|
242
|
-
if
|
241
|
+
if scopes.include?(:current)
|
243
242
|
sti_names << klass.sti_name
|
244
243
|
end
|
245
|
-
if
|
244
|
+
if scopes.include?(:children) && klass
|
246
245
|
sti_names.concat(klass.descendants.map(&:sti_name))
|
247
246
|
end
|
248
|
-
if
|
247
|
+
if scopes.include?(:parents) && klass # include searches up the STI chain
|
249
248
|
parent_class = klass.superclass
|
250
249
|
while parent_class <= Tagtical::Tag
|
251
250
|
sti_names << parent_class.sti_name
|
@@ -340,8 +339,8 @@ module Tagtical
|
|
340
339
|
end
|
341
340
|
|
342
341
|
# Take operator types (ie <, >, =) and convert them into :children, :current, or :parents.
|
343
|
-
def
|
344
|
-
Array.wrap(input ||
|
342
|
+
def convert_scope_options(input)
|
343
|
+
Array.wrap(input || [:current, :children]).map do |type|
|
345
344
|
if (t = type.to_s)=~/^[=><]+$/
|
346
345
|
{"=" => :current, ">" => :parents, "<" => :children}.map do |operator, val|
|
347
346
|
val if t.include?(operator)
|
@@ -372,8 +371,8 @@ module Tagtical
|
|
372
371
|
|
373
372
|
def convert_finder_type_arguments(*args)
|
374
373
|
options = args.extract_options!
|
375
|
-
|
376
|
-
options
|
374
|
+
scopes = convert_scope_options(args.presence || options[:scope])
|
375
|
+
[scopes, options]
|
377
376
|
end
|
378
377
|
|
379
378
|
end
|
data/lib/tagtical/tag_list.rb
CHANGED
@@ -49,6 +49,11 @@ module Tagtical
|
|
49
49
|
end
|
50
50
|
alias << push
|
51
51
|
|
52
|
+
# Shorthand
|
53
|
+
def find(value)
|
54
|
+
detect { |t| t==value }
|
55
|
+
end
|
56
|
+
|
52
57
|
##
|
53
58
|
# Add tags to the tag_list. Duplicate or blank tags will be ignored.
|
54
59
|
# Use the <tt>:parse</tt> option to add an unparsed tag string.
|
@@ -120,26 +125,35 @@ module Tagtical
|
|
120
125
|
args.flatten!
|
121
126
|
end
|
122
127
|
|
128
|
+
# Returns an array by parsing the input.
|
123
129
|
def extract(input, options={})
|
124
130
|
case input
|
131
|
+
when Tagtical::Tag
|
132
|
+
TagValue.new(input.value, input.relevance)
|
125
133
|
when String
|
126
|
-
|
127
|
-
[
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
+
[].tap do |arr|
|
135
|
+
if !input.include?(delimiter) || options[:parse]==false
|
136
|
+
arr << input
|
137
|
+
else
|
138
|
+
input = input.dup
|
139
|
+
|
140
|
+
# Parse the quoted tags
|
141
|
+
value_quotes.each do |value_quote|
|
142
|
+
input.gsub!(/(\A|#{delimiter})\s*#{value_quote}(.*?)#{value_quote}\s*(#{delimiter}\s*|\z)/) { arr << $2 ; $3 }
|
143
|
+
end
|
144
|
+
|
145
|
+
# Parse the unquoted tags
|
146
|
+
input.split(delimiter).each { |word| arr << word.strip }
|
134
147
|
end
|
135
|
-
|
136
|
-
# Parse the unquoted tags
|
137
|
-
arr.concat(input.split(delimiter).each(&:strip!))
|
138
148
|
end
|
139
149
|
when Hash
|
140
150
|
input.map { |value, relevance| TagValue.new(value, relevance) }
|
141
151
|
when Array
|
142
|
-
input
|
152
|
+
input.map { |value| extract(value) }
|
153
|
+
when Symbol # put at the end, rare case
|
154
|
+
extract(input.to_s)
|
155
|
+
else
|
156
|
+
raise("Cannot parse: #{input.inspect}")
|
143
157
|
end
|
144
158
|
end
|
145
159
|
|
@@ -39,8 +39,8 @@ module Tagtical::Taggable
|
|
39
39
|
def save_cached_tag_list
|
40
40
|
tag_types.each do |tag_type|
|
41
41
|
if self.class.send("caching_#{tag_type.singularize}_list?")
|
42
|
-
if tag_list = tag_list_cache_on(tag_type)[
|
43
|
-
self[tag_type.tag_list_name(:cached)] = tag_list.
|
42
|
+
if tag_list = tag_list_cache_on(tag_type)[[:children, :current]]
|
43
|
+
self[tag_type.tag_list_name(:cached)] = tag_list.to_s
|
44
44
|
end
|
45
45
|
end
|
46
46
|
end
|
@@ -83,7 +83,7 @@ module Tagtical::Taggable
|
|
83
83
|
end
|
84
84
|
|
85
85
|
def find_tag_type!(input)
|
86
|
-
tag_types.find { |t| t.match?(input) } || raise("Cannot find tag type:'#{input}' in #{tag_types.inspect}")
|
86
|
+
(@tag_type ||= {})[input] ||= tag_types.find { |t| t.match?(input) } || raise("Cannot find tag type:'#{input}' in #{tag_types.inspect}")
|
87
87
|
end
|
88
88
|
|
89
89
|
##
|
@@ -206,11 +206,11 @@ module Tagtical::Taggable
|
|
206
206
|
def set_tag_list_on(context, new_list, *args)
|
207
207
|
tag_list = Tagtical::TagList.from(new_list)
|
208
208
|
cascade_set_tag_list!(tag_list, context, *args)
|
209
|
-
tag_list_cache_on(context)[
|
209
|
+
tag_list_cache_on(context)[scopes_for_tag_list(context, *args)] = tag_list
|
210
210
|
end
|
211
211
|
|
212
212
|
def tag_list_on(context, *args)
|
213
|
-
tag_list_cache_on(context)[
|
213
|
+
tag_list_cache_on(context)[scopes_for_tag_list(context, *args)] ||= Tagtical::TagList.new(tags_on(context, *args))
|
214
214
|
end
|
215
215
|
|
216
216
|
def tag_list_cache_on(context, prefix=nil)
|
@@ -219,7 +219,7 @@ module Tagtical::Taggable
|
|
219
219
|
end
|
220
220
|
|
221
221
|
def all_tags_list_on(context, *args)
|
222
|
-
tag_list_cache_on(context, :all)[
|
222
|
+
tag_list_cache_on(context, :all)[scopes_for_tag_list(context, *args)] ||= Tagtical::TagList.new(all_tags_on(context, *args)).freeze
|
223
223
|
end
|
224
224
|
|
225
225
|
##
|
@@ -254,17 +254,16 @@ module Tagtical::Taggable
|
|
254
254
|
# Do the classes from top to bottom. We want the list from "tag" to run before "sub_tag" runs.
|
255
255
|
# Otherwise, we will end up removing taggings from "sub_tag" since they aren't on "tag'.
|
256
256
|
tag_types.sort_by(&:active_record_sti_level).each do |tag_type|
|
257
|
-
(tag_list_cache_on(tag_type) || {}).each do |
|
257
|
+
(tag_list_cache_on(tag_type) || {}).each do |scopes, tag_list|
|
258
|
+
# Tag list saving only runs if its affecting the current scope or the current and children scope
|
259
|
+
next unless [:<=, :==].any? { |scope| scopes_for_tag_list(tag_type, scope)==scopes }
|
258
260
|
tag_list = tag_list.uniq
|
259
261
|
|
260
262
|
# Find existing tags or create non-existing tags:
|
261
263
|
tag_value_lookup = tag_type.scoping { find_or_create_tags(tag_list) }
|
262
264
|
tags = tag_value_lookup.keys
|
263
265
|
|
264
|
-
|
265
|
-
options[:scope] = Array(options[:scope]) + [:parents] # add in the parents because we need them later on down.
|
266
|
-
|
267
|
-
current_tags = tags_on(tag_type, options)
|
266
|
+
current_tags = tags_on(tag_type, *[:parents].concat(scopes)) # add in the parents because we need them later on down.
|
268
267
|
old_tags = current_tags - tags
|
269
268
|
new_tags = tags - current_tags
|
270
269
|
|
@@ -291,6 +290,9 @@ module Tagtical::Taggable
|
|
291
290
|
taggings.create!(:tag_id => tag.id, :taggable => self, :relevance => tag_value_lookup[tag].relevance) # Create new taggings:
|
292
291
|
end
|
293
292
|
end
|
293
|
+
|
294
|
+
# Force tag lists to reload to integrate any new tags from inheritance.
|
295
|
+
remove_tag_caches_on(tag_type)
|
294
296
|
end
|
295
297
|
|
296
298
|
true
|
@@ -298,18 +300,29 @@ module Tagtical::Taggable
|
|
298
300
|
|
299
301
|
private
|
300
302
|
|
303
|
+
def remove_tag_caches_on(tag_type)
|
304
|
+
[nil, :all].each do |prefix|
|
305
|
+
ivar = tag_type.tag_list_ivar(prefix)
|
306
|
+
remove_instance_variable(ivar) if instance_variable_defined?(ivar)
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
301
310
|
def tag_scope(input, *args)
|
302
311
|
tags.where(find_tag_type!(input).finder_type_condition(*args))
|
303
312
|
end
|
304
313
|
|
305
314
|
def find_tag_type!(input)
|
306
|
-
|
315
|
+
self.class.find_tag_type!(input)
|
307
316
|
end
|
308
317
|
|
309
|
-
def
|
318
|
+
def finder_type_arguments_for_tag_list(input, *args)
|
310
319
|
find_tag_type!(input).send(:convert_finder_type_arguments, *args)
|
311
320
|
end
|
312
321
|
|
322
|
+
def scopes_for_tag_list(*args)
|
323
|
+
finder_type_arguments_for_tag_list(*args)[0].sort
|
324
|
+
end
|
325
|
+
|
313
326
|
# Lets say tag class A inherits from B and B has a tag with value "foo". If we tag A with value "foo",
|
314
327
|
# we want B to have only one instance of "foo" and that tag should be an instance of A (a subclass of B).
|
315
328
|
def update_tagging_with_inherited_tag!(tagging, tags, tag_value_lookup)
|
@@ -322,8 +335,9 @@ module Tagtical::Taggable
|
|
322
335
|
# If cascade tag types are specified, it will attempt to look at Tag subclasses with
|
323
336
|
# possible_values and try to set those tag_lists with values from the possible_values list.
|
324
337
|
def cascade_set_tag_list!(tag_list, context, *args)
|
325
|
-
|
326
|
-
if
|
338
|
+
scopes, options = finder_type_arguments_for_tag_list(context, *args)
|
339
|
+
raise("You must include children if you are cascading") if options[:cascade] && !scopes.include?(:current)
|
340
|
+
if (cascade = options.delete(:cascade)) && (tag_type = find_tag_type!(context)).klass
|
327
341
|
tag_types = cascade==true ? self.tag_types : Array(cascade).map { |c| find_tag_type!(c) }
|
328
342
|
tag_types.each do |t|
|
329
343
|
if t.klass && t.klass <= tag_type.klass && t.klass.possible_values
|
@@ -334,7 +348,7 @@ module Tagtical::Taggable
|
|
334
348
|
true
|
335
349
|
end
|
336
350
|
end
|
337
|
-
tag_list_cache_on(t)[
|
351
|
+
tag_list_cache_on(t)[[:current]] = new_tag_list if !new_tag_list.empty?
|
338
352
|
end
|
339
353
|
end
|
340
354
|
end
|
data/lib/tagtical/taggable.rb
CHANGED
@@ -29,21 +29,22 @@ module Tagtical
|
|
29
29
|
else
|
30
30
|
write_inheritable_attribute(:tag_types, tag_types)
|
31
31
|
class_inheritable_reader(:tag_types)
|
32
|
+
|
33
|
+
has_many :taggings, :as => :taggable, :dependent => :destroy, :include => :tag, :class_name => "Tagtical::Tagging"
|
34
|
+
has_many :tags, :through => :taggings, :class_name => "Tagtical::Tag"
|
32
35
|
|
33
36
|
class_eval do
|
34
|
-
has_many :taggings, :as => :taggable, :dependent => :destroy, :include => :tag, :class_name => "Tagtical::Tagging"
|
35
|
-
has_many :tags, :through => :taggings, :class_name => "Tagtical::Tag"
|
36
|
-
|
37
37
|
def self.taggable?
|
38
38
|
true
|
39
39
|
end
|
40
|
-
|
41
|
-
include Tagtical::Taggable::Core
|
42
|
-
include Tagtical::Taggable::Collection
|
43
|
-
include Tagtical::Taggable::Cache
|
44
|
-
include Tagtical::Taggable::Ownership
|
45
|
-
include Tagtical::Taggable::Related
|
46
40
|
end
|
41
|
+
|
42
|
+
include Tagtical::Taggable::Core
|
43
|
+
include Tagtical::Taggable::Collection
|
44
|
+
include Tagtical::Taggable::Cache
|
45
|
+
include Tagtical::Taggable::Ownership
|
46
|
+
include Tagtical::Taggable::Related
|
47
|
+
|
47
48
|
end
|
48
49
|
|
49
50
|
end
|
@@ -1,7 +1,11 @@
|
|
1
1
|
require File.expand_path('../../spec_helper', __FILE__)
|
2
2
|
|
3
3
|
describe Tagtical::TagList do
|
4
|
-
before
|
4
|
+
before do
|
5
|
+
@klass = Tagtical::TagList
|
6
|
+
@tag_list = @klass.new("awesome", "radical")
|
7
|
+
end
|
8
|
+
|
5
9
|
subject { @tag_list }
|
6
10
|
|
7
11
|
it { should be_an Array }
|
@@ -70,8 +74,23 @@ describe Tagtical::TagList do
|
|
70
74
|
|
71
75
|
it "should be able to add relevances with a string" do
|
72
76
|
@tag_list.add("foo : 3.4, bar: 2.5")
|
73
|
-
@tag_list.
|
74
|
-
@tag_list.
|
77
|
+
@tag_list.find("foo").relevance.should == 3.4
|
78
|
+
@tag_list.find("bar").relevance.should == 2.5
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should be able to add a symbol" do
|
82
|
+
@tag_list.add(:car)
|
83
|
+
@tag_list.find("car").should_not be_nil
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should be able to add a list of tags" do
|
87
|
+
tags = [["foo", 1],["bar", 1.3],["car", 0.7]].map do |value, relevance|
|
88
|
+
Tagtical::Tag.new(:value => value).tap { |t| t["relevance"] = relevance }
|
89
|
+
end
|
90
|
+
@tag_list.add(tags)
|
91
|
+
tags.each do |tag|
|
92
|
+
@tag_list.find(tag.value).relevance.should == tag.relevance
|
93
|
+
end
|
75
94
|
end
|
76
95
|
|
77
96
|
it "should be able to remove words" do
|
@@ -92,7 +111,13 @@ describe Tagtical::TagList do
|
|
92
111
|
its(:to_s) { should == "awesome, radical" }
|
93
112
|
|
94
113
|
describe "#to_s" do
|
95
|
-
before
|
114
|
+
before do
|
115
|
+
@tag_list = Tagtical::TagList.new("far", "awesome : 4", "radical : 3", "car, bar:10.3", :parse => false)
|
116
|
+
@taggable = TaggableModel.new("taggable")
|
117
|
+
@taggable.set_tag_list "retro: 6, car:4, nature, test: 2.7 ", :cascade => true
|
118
|
+
@taggable.save
|
119
|
+
@taggable.reload
|
120
|
+
end
|
96
121
|
|
97
122
|
it "should contain relevance with the relevance delimiter" do
|
98
123
|
@tag_list.to_s.should include("awesome:4.0, radical:3.0")
|
@@ -102,6 +127,10 @@ describe Tagtical::TagList do
|
|
102
127
|
@tag_list.to_s.should include(%{"car, bar":10.3})
|
103
128
|
end
|
104
129
|
|
130
|
+
it "should include relevance in string" do
|
131
|
+
@taggable.tag_list.to_s.should == "retro:6.0, car:4.0, nature:1.0, test:2.7"
|
132
|
+
end
|
133
|
+
|
105
134
|
end
|
106
135
|
|
107
136
|
it "should quote escape tags with commas in them" do
|
data/spec/tagtical/tag_spec.rb
CHANGED
@@ -338,7 +338,7 @@ describe Tagtical::Tag do
|
|
338
338
|
end
|
339
339
|
end
|
340
340
|
|
341
|
-
describe "#
|
341
|
+
describe "#convert_scope_options" do
|
342
342
|
{:<= => [:children, :current],
|
343
343
|
:>= => [:parents, :current],
|
344
344
|
:"<>" => [:children, :parents],
|
@@ -348,7 +348,7 @@ describe Tagtical::Tag do
|
|
348
348
|
:"<" => [:children]
|
349
349
|
}.each do |operator, expected|
|
350
350
|
it "should convert #{operator.inspect} to #{expected.inspect}" do
|
351
|
-
subject.send(:
|
351
|
+
subject.send(:convert_scope_options, operator).should have_same_elements(expected)
|
352
352
|
end
|
353
353
|
end
|
354
354
|
end
|
@@ -24,7 +24,7 @@ describe Tagtical::Taggable do
|
|
24
24
|
|
25
25
|
it "should be able to create tags" do
|
26
26
|
@taggable.skill_list = "ruby, rails, css"
|
27
|
-
@taggable.tag_list_cache_on(:skill)[
|
27
|
+
@taggable.tag_list_cache_on(:skill)[[:children, :current]].should be_an_instance_of(Tagtical::TagList)
|
28
28
|
|
29
29
|
lambda { @taggable.save }.should change(Tagtical::Tag, :count).by(3)
|
30
30
|
|
@@ -127,7 +127,7 @@ describe Tagtical::Taggable do
|
|
127
127
|
end
|
128
128
|
end
|
129
129
|
|
130
|
-
describe "
|
130
|
+
describe "tag_list scoping behavior" do
|
131
131
|
before do
|
132
132
|
@taggables[0].tag_list = "bob"
|
133
133
|
@taggables[1].tag_list = "charlie"
|
@@ -136,15 +136,35 @@ describe Tagtical::Taggable do
|
|
136
136
|
@taggables[0].craft_list = "knitting"
|
137
137
|
@taggables[1].craft_list = "pottery"
|
138
138
|
@taggables.each(&:save!)
|
139
|
+
@taggables.each(&:reload)
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should empty out inheriting tags" do
|
143
|
+
@taggables[0].tag_list = []
|
144
|
+
@taggables[0].save!
|
145
|
+
@taggables[0].reload
|
146
|
+
|
147
|
+
@taggables[0].crafts.should be_empty
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should not empty out 'tag' type when :current scope" do
|
151
|
+
@taggables[0].set_tag_list([], :current)
|
152
|
+
@taggables[0].save!
|
153
|
+
@taggables[0].reload
|
154
|
+
|
155
|
+
@taggables[0].tags.should_not be_empty
|
156
|
+
@taggables[0].tags(:current).should be_empty
|
157
|
+
@taggables[0].skills.should_not be_empty
|
158
|
+
@taggables[0].crafts.should_not be_empty
|
139
159
|
end
|
140
160
|
|
141
161
|
it "should be able to query tags" do
|
142
162
|
@taggables[0].tags(:scope => :current).should have_only_tag_values %w{bob}
|
143
|
-
@taggables[0].tags(
|
163
|
+
@taggables[0].tags(:==).should have_only_tag_values %w{bob}
|
144
164
|
@taggables[0].tags.should have_only_tag_values %w{bob knitting ruby}
|
145
165
|
@taggables[0].tags(:scope => :children).should have_only_tag_values %w{knitting ruby}
|
146
166
|
@taggables[0].tags(:scope => :<).should have_only_tag_values %w{knitting ruby}
|
147
|
-
@taggables[1].crafts(:
|
167
|
+
@taggables[1].crafts(:parents).should have_only_tag_values %w{charlie css}
|
148
168
|
@taggables[1].crafts(:scope => :>).should have_only_tag_values %w{charlie css}
|
149
169
|
|
150
170
|
@taggables[1].crafts(:scope => [:parents, :current]).should have_only_tag_values %w{charlie css pottery}
|
@@ -446,14 +466,22 @@ describe Tagtical::Taggable do
|
|
446
466
|
|
447
467
|
describe "Associations" do
|
448
468
|
before(:each) do
|
449
|
-
@taggable = TaggableModel.create(:tag_list => "awesome, epic")
|
469
|
+
@taggable = TaggableModel.create(:tag_list => "awesome, epic", :skill_list => "basketball, hiking, boxing")
|
450
470
|
end
|
451
471
|
|
452
472
|
it "should not remove tags when creating associated objects" do
|
453
473
|
@taggable.untaggable_models.create!
|
454
474
|
@taggable.reload
|
455
|
-
@taggable.tag_list.should have(
|
475
|
+
@taggable.tag_list.should have(5).items
|
476
|
+
end
|
477
|
+
|
478
|
+
its "tag_list methods should accept scope arguments" do
|
479
|
+
@taggable.tag_list(:current).should have(2).items
|
480
|
+
@taggable.skill_list(:parents).should have(2).items
|
481
|
+
@taggable.skill_list(:current).should have(3).items
|
482
|
+
@taggable.tag_list(:current, :children).should have(5).items
|
456
483
|
end
|
484
|
+
|
457
485
|
end
|
458
486
|
|
459
487
|
describe "grouped_column_names_for method" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tagtical
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-07-
|
12
|
+
date: 2011-07-22 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
16
|
-
requirement: &
|
16
|
+
requirement: &2168459400 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - <=
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 3.0.5
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *2168459400
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rspec
|
27
|
-
requirement: &
|
27
|
+
requirement: &2168476040 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - <=
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 2.6.0
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *2168476040
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: sqlite3-ruby
|
38
|
-
requirement: &
|
38
|
+
requirement: &2168475560 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *2168475560
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: mysql
|
49
|
-
requirement: &
|
49
|
+
requirement: &2168475080 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *2168475080
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: jeweler
|
60
|
-
requirement: &
|
60
|
+
requirement: &2168474600 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :runtime
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *2168474600
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rcov
|
71
|
-
requirement: &
|
71
|
+
requirement: &2168474120 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,7 +76,7 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *2168474120
|
80
80
|
description: Tagtical allows you do create subclasses for Tag and add additional functionality
|
81
81
|
in an STI fashion. For example. You could do Tag::Color.find_by_name('blue').to_rgb.
|
82
82
|
It also supports storing weights or relevance on the taggings.
|