tagtical 1.0.6 → 1.0.7

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/Gemfile CHANGED
@@ -4,8 +4,8 @@ source :gemcutter
4
4
 
5
5
  # Cannot require these as dependency until there the fix is released:
6
6
  #
7
- #gem 'rails', '3.0.5'
8
- #gem 'rspec', '2.6.0'
7
+ gem 'rails', '<=3.0.5'
8
+ gem 'rspec', '<=2.6.0'
9
9
  # http://rubyforge.org/tracker/?func=detail&atid=575&aid=29163&group_id=126
10
10
 
11
11
  gem 'sqlite3-ruby', :require => 'sqlite3'
@@ -17,4 +17,4 @@ gem 'rcov'
17
17
 
18
18
  group :test do
19
19
  gem "mocha"
20
- end
20
+ end
data/README.rdoc CHANGED
@@ -115,8 +115,11 @@ rake spec:plugins
115
115
  @user.save
116
116
 
117
117
  @user.activities # => [<Tag::Activity value:"joking">,<Tag::Activity value:"clowning">,<Tag::Sport value:"boxing">]
118
- @user.activities(:only => :children) # => [<Tag::Sport value:"boxing">] - look at only the STI subclasses
119
- @user.activities(:only => :current) # => [<Tag::Activity value:"joking">,<Tag::Activity value:"clowning">] - look at only the current STI class
118
+ @user.activities(:type => :children) # => [<Tag::Sport value:"boxing">] - look at only the STI subclasses
119
+ @user.activities(:type => :<) # => [<Tag::Sport value:"boxing">] - look at only the STI subclasses
120
+ @user.activities(:type => :current) # => [<Tag::Activity value:"joking">,<Tag::Activity value:"clowning">] - look at only the current STI class
121
+ @user.activities(:type => :==) # => [<Tag::Activity value:"joking">,<Tag::Activity value:"clowning">] - look at only the current STI class
122
+
120
123
  @user.activities.first.athletic? # => false
121
124
  @user.sports.all(&:ball?) # => true
122
125
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.6
1
+ 1.0.7
data/lib/tagtical/tag.rb CHANGED
@@ -60,7 +60,15 @@ module Tagtical
60
60
 
61
61
  def sti_name
62
62
  return @sti_name if instance_variable_defined?(:@sti_name)
63
- @sti_name = Tagtical::Tag==self ? nil : Type.new(name.demodulize).to_sti_name
63
+ @sti_name = Tagtical::Tag==self ? nil : Type[name.demodulize].to_sti_name
64
+ end
65
+
66
+ def define_methods_for_type(tag_type)
67
+ (@define_methods_for_type ||= {})[tag_type] ||= begin
68
+ scope(tag_type.scope_name, Proc.new { |options| tag_type.scoping(options || {}) })
69
+ define_method(:"#{tag_type}?") { is_a?(tag_type.klass!) }
70
+ true
71
+ end
64
72
  end
65
73
 
66
74
  protected
@@ -94,7 +102,7 @@ module Tagtical
94
102
  end
95
103
 
96
104
  def relevance
97
- (v = self["relevance"]) && v.to_f
105
+ (v = self[:relevance]) && v.to_f
98
106
  end
99
107
 
100
108
  # Try to sort by the relevance if provided.
@@ -110,23 +118,15 @@ module Tagtical
110
118
  value
111
119
  end
112
120
 
113
- # Overwrite these methods to provide your own storage mechanism for a tag.
114
- def load_value(value) value end
115
- def dump_value(value) value end
116
-
117
- def value
118
- @value ||= load_value(self[:value])
119
- end
120
-
121
- def value=(value)
122
- @value = nil
123
- self[:value] = dump_value(value)
121
+ def inspect
122
+ super.tap do |str|
123
+ str[-2] = "relevance: #{attribute_for_inspect(:relevance)}" if has_attribute?(:relevance)
124
+ end
124
125
  end
125
126
 
126
127
  # We return nil if we are *not* an STI class.
127
128
  def type
128
- type = self[:type]
129
- type && Type[type]
129
+ (type = self[:type]) && Type.new(type)
130
130
  end
131
131
 
132
132
  def count
@@ -146,17 +146,19 @@ module Tagtical
146
146
  # "tag" should always correspond with demodulize name of the base Tag class (ie Tagtical::Tag).
147
147
  BASE = "tag".freeze
148
148
 
149
- # Default to simply "tag", if none is provided. This will return Tagtical::Tag on calls to #klass
150
- def initialize(arg)
151
- super(arg.to_s.singularize.underscore.gsub(/_tag$/, ''))
152
- end
153
-
154
149
  class << self
155
150
  def find(input)
156
151
  return input.map { |c| self[c] } if input.is_a?(Array)
157
- input.is_a?(self) ? input : new(input)
152
+ input.is_a?(self) ? input : new(sanitize(input))
158
153
  end
159
154
  alias :[] :find
155
+
156
+ private
157
+
158
+ # Sanitize the input for type name consistency.
159
+ def sanitize(input)
160
+ input.to_s.singularize.underscore.gsub(/_tag$/, '')
161
+ end
160
162
  end
161
163
 
162
164
  # The STI name for the Tag model is the same as the tag type.
@@ -172,24 +174,24 @@ module Tagtical
172
174
  # <tt>only</tt> - An array of the following: :parents, :current, :children. Will construct conditions to query the current, parent, and/or children STI classes.
173
175
  #
174
176
  def finder_type_condition(options={})
175
- only = Array.wrap(options[:only] || (klass ? [:current, :children] : :current))
177
+ type = convert_type_options(options[:type])
176
178
 
177
179
  # If we want [:current, :children] or [:current, :children, :parents] and we don't need the finder type condition,
178
180
  # then that means we don't need a condition at all since we are at the top-level sti class and we are essentially
179
181
  # searching the whole range of sti classes.
180
182
  if klass && !klass.finder_needs_type_condition?
181
- only.delete(:parents) # we are at the topmost level.
182
- only = [] if only==[:current, :children] # no condition is required if we want the current AND the children.
183
+ type.delete(:parents) # we are at the topmost level.
184
+ type = [] if type==[:current, :children] # no condition is required if we want the current AND the children.
183
185
  end
184
186
 
185
187
  sti_names = []
186
- if only.include?(:current)
188
+ if type.include?(:current)
187
189
  sti_names << (klass ? klass.sti_name : to_sti_name)
188
190
  end
189
- if only.include?(:children) && klass
191
+ if type.include?(:children) && klass
190
192
  sti_names.concat(klass.descendants.map(&:sti_name))
191
193
  end
192
- if only.include?(:parents) && klass # include searches up the STI chain
194
+ if type.include?(:parents) && klass # include searches up the STI chain
193
195
  parent_class = klass.superclass
194
196
  while parent_class <= Tagtical::Tag
195
197
  sti_names << parent_class.sti_name
@@ -283,6 +285,19 @@ module Tagtical
283
285
  end
284
286
  end
285
287
 
288
+ # Take operator types (ie <, >, =) and convert them into :children, :current, or :parents.
289
+ def convert_type_options(input)
290
+ Array.wrap(input || (klass ? [:current, :children] : :current)).map do |type, i|
291
+ if (t = type.to_s)=~/^[=><]+$/
292
+ {"=" => :current, ">" => :parents, "<" => :children}.map do |operator, val|
293
+ val if t.include?(operator)
294
+ end.compact
295
+ else
296
+ type
297
+ end
298
+ end.flatten.uniq
299
+ end
300
+
286
301
  def find_tag_class
287
302
  candidates = derive_class_candidates
288
303
 
@@ -24,14 +24,14 @@ module Tagtical::Taggable
24
24
  # This keeps your reflections cleaner.
25
25
 
26
26
  # In the case of the base tag type, it will just use the :tags association defined above.
27
- Tagtical::Tag.scope(tag_type.scope_name, Proc.new { |options| tag_type.scoping(options || {}) }) unless Tagtical::Tag.respond_to?(tag_type.scope_name)
27
+ Tagtical::Tag.define_methods_for_type(tag_type)
28
28
 
29
29
  # If the tag_type is base? (type=="tag"), then we add additional functionality to the AR
30
30
  # has_many :tags.
31
31
  #
32
- # taggable_model.tags(:only => :children)
32
+ # taggable_model.tags(:type => :children)
33
33
  # taggable_model.tags <-- still works like normal has_many
34
- # taggable_model.tags(true, :only => :current) <-- reloads the tags association and appends scope for only current type.
34
+ # taggable_model.tags(true, :type => :current) <-- reloads the tags association and appends scope for only current type.
35
35
  if tag_type.has_many_name==:tags
36
36
  define_method("tags_with_finder_type_options") do |*args|
37
37
  options = args.pop if args.last.is_a?(Hash)
@@ -99,7 +99,7 @@ module Tagtical::Taggable
99
99
 
100
100
  options[:on] ||= Tagtical::Tag::Type::BASE
101
101
  tag_type = Tagtical::Tag::Type.find(options.delete(:on))
102
- finder_type_condition_options = options.extract!(:only)
102
+ finder_type_condition_options = options.extract!(:type)
103
103
 
104
104
  tag_table, tagging_table = Tagtical::Tag.table_name, Tagtical::Tagging.table_name
105
105
 
@@ -259,7 +259,7 @@ module Tagtical::Taggable
259
259
  tag_value_lookup = tag_type.scoping { find_or_create_tags(tag_list) }
260
260
  tags = tag_value_lookup.keys
261
261
 
262
- current_tags = tags_on(tag_type, :only => [:current, :parents, :children])
262
+ current_tags = tags_on(tag_type, :type => [:current, :parents, :children])
263
263
  old_tags = current_tags - tags
264
264
  new_tags = tags - current_tags
265
265
 
@@ -72,7 +72,7 @@ module Tagtical::Taggable
72
72
  tag_value_lookup = tag_type.scoping { find_or_create_tags(tag_list) }
73
73
  tags = tag_value_lookup.keys
74
74
 
75
- owned_tags = owner_tags_on(owner, tag_type, :only => [:current, :parents, :children])
75
+ owned_tags = owner_tags_on(owner, tag_type, :type => [:current, :parents, :children])
76
76
  old_tags = owned_tags - tags
77
77
  new_tags = tags - owned_tags
78
78
 
data/spec/spec_helper.rb CHANGED
@@ -25,7 +25,12 @@ end
25
25
 
26
26
  RSpec::Matchers.define :have_tag_values do |expected|
27
27
  match do |actual|
28
- actual.map(&:value).sort == expected.sort
28
+ actual.map(&:value).should have_same_elements(expected)
29
+ end
30
+ end
31
+ RSpec::Matchers.define :have_same_elements do |expected|
32
+ match do |actual|
33
+ actual.sort == expected.sort
29
34
  end
30
35
  end
31
36
 
@@ -57,7 +57,7 @@ describe Tagtical::Tag do
57
57
 
58
58
  end
59
59
 
60
- describe "tag scopes" do
60
+ describe "tag scopes Type#finder_type_conditions" do
61
61
  before do
62
62
  Tagtical::Tag.create(:value => "Plane")
63
63
  Tag::Skill.create(:value => "Kung Fu")
@@ -65,40 +65,71 @@ describe Tagtical::Tag do
65
65
  NeedTag.create(:value => "chair")
66
66
  end
67
67
 
68
- it "should retrieve tags finder type conditions" do
69
- Tagtical::Tag.skills.should have_tag_values ["Kung Fu", "Painting"]
70
- Tagtical::Tag.skills(:only => :current).should have_tag_values ["Kung Fu"]
71
- Tagtical::Tag.crafts(:only => :parents).should have_tag_values ["Kung Fu", "Plane"]
68
+ context "when :type => :current or the alias :==" do
69
+ it "should retrieve current STI level tags" do
70
+ Tagtical::Tag.skills.should have_tag_values ["Kung Fu", "Painting"]
71
+ Tagtical::Tag.skills(:type => :current).should have_tag_values ["Kung Fu"]
72
+ Tagtical::Tag.skills(:type => :==).should have_tag_values ["Kung Fu"]
73
+ end
72
74
  end
73
75
 
74
- end
76
+ context "when :type => :parent or the alias :>" do
77
+ it "should retrieve parent STI level tags" do
78
+ Tagtical::Tag.skills.should have_tag_values ["Kung Fu", "Painting"]
79
+ Tagtical::Tag.crafts(:type => :parents).should have_tag_values ["Kung Fu", "Plane"]
80
+ Tagtical::Tag.crafts(:type => :>).should have_tag_values ["Kung Fu", "Plane"]
81
+ Tagtical::Tag.skills(:type => :>).should have_tag_values ["Plane"]
82
+ end
83
+ end
75
84
 
76
- describe "#dump_value" do
77
- before do
78
- @tag = Tagtical::Tag::PartTag.new(:value => "FOO")
85
+ context "when :type => :childern or the alias :<" do
86
+ it "should retrieve child STI level tags" do
87
+ Tagtical::Tag.skills.should have_tag_values ["Kung Fu", "Painting"]
88
+ Tagtical::Tag.skills(:type => :children).should have_tag_values ["Painting"]
89
+ Tagtical::Tag.skills(:type => :<).should have_tag_values ["Painting"]
90
+ end
79
91
  end
80
92
 
81
- its(:value) { should == "foo" }
93
+ context "when :type => :\"><\"" do
94
+ it "should retrieve parent and child STI level tags" do
95
+ Tagtical::Tag.skills.should have_tag_values ["Kung Fu", "Painting"]
96
+ Tagtical::Tag.skills(:type => :"><").should have_tag_values ["Plane", "Painting"]
97
+ end
98
+ end
82
99
 
83
- it "should accept a nil value" do
84
- lambda { @tag.value = nil }.should_not raise_error
85
- @tag.value.should be_nil
100
+ context "when :type => :>=" do
101
+ it "should retrieve current and parent STI level tags" do
102
+ Tagtical::Tag.skills.should have_tag_values ["Kung Fu", "Painting"]
103
+ Tagtical::Tag.skills(:type => :>=).should have_tag_values ["Kung Fu", "Plane"]
104
+ end
105
+ end
106
+
107
+ context "when :type => :<=" do
108
+ it "should retrieve current and child STI level tags" do
109
+ Tagtical::Tag.skills.should have_tag_values ["Kung Fu", "Painting"]
110
+ Tagtical::Tag.skills(:type => :<=).should have_tag_values ["Kung Fu", "Painting"]
111
+ end
86
112
  end
87
113
  end
88
-
89
- describe "#load_value" do
114
+
115
+ describe ".define_methods_for_type" do
90
116
  before do
91
- @tag = Tag::Skill.new(:value => "basketball")
117
+ @skill = Tag::Skill.new(:value => "baskeball")
118
+ @craft = Tag::Craft.new(:value => "pottery")
92
119
  end
93
120
 
94
- specify { @tag[:value].should == "basketball" }
95
-
96
- its(:value) { should == "basketballer" }
121
+ it "should have a quester method" do
122
+ @skill.tag?.should be_true
123
+ @skill.skill?.should be_true
124
+ @skill.craft?.should be_false
125
+ end
97
126
 
98
- it "should accept a nil value" do
99
- lambda { @tag.value = nil }.should_not raise_error
100
- @tag.value.should be_nil
127
+ it "should have a quester method that considers inheritance" do
128
+ @craft.tag?.should be_true
129
+ @craft.skill?.should be_true
130
+ @craft.craft?.should be_true
101
131
  end
132
+
102
133
  end
103
134
 
104
135
  it "should refresh @value on value setter" do
@@ -254,10 +285,10 @@ describe Tagtical::Tag do
254
285
  its(:klass) { should == Tag::Skill }
255
286
  its(:scope_name) { should == :skills }
256
287
 
257
- describe "initialize" do
288
+ describe ".find" do
258
289
  it "converts string into correct format" do
259
290
  {"ClassNames" => "class_name", "photo_tags" => "photo", :photo => "photo"}.each do |input, result|
260
- @klass.new(input).should == result
291
+ @klass.find(input).should == result
261
292
  end
262
293
  end
263
294
  end
@@ -273,6 +304,21 @@ describe Tagtical::Tag do
273
304
  end
274
305
  end
275
306
 
307
+ describe "#convert_type_options" do
308
+ {:<= => [:children, :current],
309
+ :>= => [:parents, :current],
310
+ :"<>" => [:children, :parents],
311
+ :== => [:current],
312
+ "==" => [:current], # should work with strings as well.
313
+ :">" => [:parents],
314
+ :"<" => [:children]
315
+ }.each do |operator, expected|
316
+ it "should convert #{operator.inspect} to #{expected.inspect}" do
317
+ subject.send(:convert_type_options, operator).should have_same_elements(expected)
318
+ end
319
+ end
320
+ end
321
+
276
322
  describe "#derive_class_candidates" do
277
323
  specify do
278
324
  subject.send(:derive_class_candidates).should include(
@@ -64,24 +64,35 @@ describe Tagtical::Taggable do
64
64
  end
65
65
 
66
66
  it "should be able to query tags" do
67
- @taggables[0].tags(:only => :current).should have_tag_values %w{bob}
67
+ @taggables[0].tags(:type => :current).should have_tag_values %w{bob}
68
+ @taggables[0].tags(:type => :==).should have_tag_values %w{bob}
68
69
  @taggables[0].tags.should have_tag_values %w{bob knitting ruby}
69
- @taggables[0].tags(:only => :children).should have_tag_values %w{knitting ruby}
70
- @taggables[1].crafts(:only => :parents).should have_tag_values %w{charlie css}
71
- @taggables[1].crafts(:only => [:parents, :current]).should have_tag_values %w{charlie css pottery}
72
- @taggables[1].skills(:only => [:parents, :children]).should have_tag_values %w{charlie pottery}
70
+ @taggables[0].tags(:type => :children).should have_tag_values %w{knitting ruby}
71
+ @taggables[0].tags(:type => :<).should have_tag_values %w{knitting ruby}
72
+ @taggables[1].crafts(:type => :parents).should have_tag_values %w{charlie css}
73
+ @taggables[1].crafts(:type => :>).should have_tag_values %w{charlie css}
74
+
75
+ @taggables[1].crafts(:type => [:parents, :current]).should have_tag_values %w{charlie css pottery}
76
+ @taggables[1].crafts(:type => :>=).should have_tag_values %w{charlie css pottery}
77
+ @taggables[1].skills(:type => [:parents, :children]).should have_tag_values %w{charlie pottery}
78
+ @taggables[1].skills(:type => :"><").should have_tag_values %w{charlie pottery}
73
79
  end
74
80
 
75
81
  it "should be able to select taggables by subset of tags using ActiveRelation methods" do
76
82
  TaggableModel.with_tags("bob").should == [@taggables[0]]
77
83
  TaggableModel.with_skills("ruby").should == [@taggables[0]]
78
84
  TaggableModel.with_tags("rUBy").should == [@taggables[0]]
79
- TaggableModel.with_tags("ruby", :only => :current).should == []
85
+ TaggableModel.with_tags("ruby", :type => :current).should == []
86
+ TaggableModel.with_tags("ruby", :type => :==).should == []
80
87
  TaggableModel.with_skills("knitting").should == [@taggables[0]]
81
- TaggableModel.with_skills("KNITTING", :only => :current).should == []
82
- TaggableModel.with_skills("knitting", :only => :parents).should == []
83
- TaggableModel.with_tags("bob", :only => :current).should == [@taggables[0]]
84
- TaggableModel.with_skills("bob", :only => :parents).should == [@taggables[0]]
88
+ TaggableModel.with_skills("KNITTING", :type => :current).should == []
89
+ TaggableModel.with_skills("KNITTING", :type => :==).should == []
90
+ TaggableModel.with_skills("knitting", :type => :parents).should == []
91
+ TaggableModel.with_skills("knitting", :type => :>).should == []
92
+ TaggableModel.with_tags("bob", :type => :current).should == [@taggables[0]]
93
+ TaggableModel.with_tags("bob", :type => :==).should == [@taggables[0]]
94
+ TaggableModel.with_skills("bob", :type => :parents).should == [@taggables[0]]
95
+ TaggableModel.with_skills("bob", :type => :>).should == [@taggables[0]]
85
96
  TaggableModel.with_crafts("knitting").should == [@taggables[0]]
86
97
  end
87
98
  end
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.0.6
4
+ version: 1.0.7
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,33 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-07-10 00:00:00.000000000Z
12
+ date: 2011-07-12 00:00:00.000000000Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: &2152043280 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - <=
20
+ - !ruby/object:Gem::Version
21
+ version: 3.0.5
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *2152043280
25
+ - !ruby/object:Gem::Dependency
26
+ name: rspec
27
+ requirement: &2152042800 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - <=
31
+ - !ruby/object:Gem::Version
32
+ version: 2.6.0
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *2152042800
14
36
  - !ruby/object:Gem::Dependency
15
37
  name: sqlite3-ruby
16
- requirement: &2161646020 !ruby/object:Gem::Requirement
38
+ requirement: &2152042320 !ruby/object:Gem::Requirement
17
39
  none: false
18
40
  requirements:
19
41
  - - ! '>='
@@ -21,10 +43,10 @@ dependencies:
21
43
  version: '0'
22
44
  type: :runtime
23
45
  prerelease: false
24
- version_requirements: *2161646020
46
+ version_requirements: *2152042320
25
47
  - !ruby/object:Gem::Dependency
26
48
  name: mysql
27
- requirement: &2161645540 !ruby/object:Gem::Requirement
49
+ requirement: &2152041840 !ruby/object:Gem::Requirement
28
50
  none: false
29
51
  requirements:
30
52
  - - ! '>='
@@ -32,10 +54,10 @@ dependencies:
32
54
  version: '0'
33
55
  type: :runtime
34
56
  prerelease: false
35
- version_requirements: *2161645540
57
+ version_requirements: *2152041840
36
58
  - !ruby/object:Gem::Dependency
37
59
  name: jeweler
38
- requirement: &2161645060 !ruby/object:Gem::Requirement
60
+ requirement: &2152041360 !ruby/object:Gem::Requirement
39
61
  none: false
40
62
  requirements:
41
63
  - - ! '>='
@@ -43,10 +65,10 @@ dependencies:
43
65
  version: '0'
44
66
  type: :runtime
45
67
  prerelease: false
46
- version_requirements: *2161645060
68
+ version_requirements: *2152041360
47
69
  - !ruby/object:Gem::Dependency
48
70
  name: rcov
49
- requirement: &2161644580 !ruby/object:Gem::Requirement
71
+ requirement: &2152040880 !ruby/object:Gem::Requirement
50
72
  none: false
51
73
  requirements:
52
74
  - - ! '>='
@@ -54,7 +76,7 @@ dependencies:
54
76
  version: '0'
55
77
  type: :runtime
56
78
  prerelease: false
57
- version_requirements: *2161644580
79
+ version_requirements: *2152040880
58
80
  description: Tagtical allows you do create subclasses for Tag and add additional functionality
59
81
  in an STI fashion. For example. You could do Tag::Color.find_by_name('blue').to_rgb.
60
82
  It also supports storing weights or relevance on the taggings.
@@ -66,7 +88,6 @@ extra_rdoc_files:
66
88
  files:
67
89
  - CHANGELOG
68
90
  - Gemfile
69
- - Gemfile.lock
70
91
  - MIT-LICENSE
71
92
  - README.rdoc
72
93
  - Rakefile
data/Gemfile.lock DELETED
@@ -1,25 +0,0 @@
1
- GEM
2
- remote: http://rubygems.org/
3
- specs:
4
- git (1.2.5)
5
- jeweler (1.6.2)
6
- bundler (~> 1.0)
7
- git (>= 1.2.5)
8
- rake
9
- mocha (0.9.12)
10
- mysql (2.8.1)
11
- rake (0.9.2)
12
- rcov (0.9.9)
13
- sqlite3 (1.3.3)
14
- sqlite3-ruby (1.3.3)
15
- sqlite3 (>= 1.3.3)
16
-
17
- PLATFORMS
18
- ruby
19
-
20
- DEPENDENCIES
21
- jeweler
22
- mocha
23
- mysql
24
- rcov
25
- sqlite3-ruby