has_many_scored 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d6e3ceacfc424710a369f2556276c3593353e762
4
+ data.tar.gz: d568b6e4ac4122bad8fa8df24d6609101a0e75a4
5
+ SHA512:
6
+ metadata.gz: f7c91444fa1250d1be8845623db6d3190a7e2e2012fa9f1cb80b67f1c78b9f5cef808e98ff85f6d2b81b65469a27fcabc7b018ca1bc76d3d88d22f220b575f51
7
+ data.tar.gz: 58a2fda5405b98b228f89c0bef26bd6475378a4666481ce5c77bab28164b81e2a2b6fe3a6467a4249edd2db678121634d12f2aaff87d58992e959cbb967a59ff
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour --format documentation
data/ChangeLog.rdoc ADDED
@@ -0,0 +1,4 @@
1
+ === 1.0.0 / 2014-02-15
2
+
3
+ * Initial release
4
+ * Stuff works
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in has_many_scored.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,72 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ has_many_scored (0.0.1)
5
+ activerecord (>= 3.0, <= 4.0.2)
6
+ redis-objects (>= 0.6.1)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ activemodel (4.0.2)
12
+ activesupport (= 4.0.2)
13
+ builder (~> 3.1.0)
14
+ activerecord (4.0.2)
15
+ activemodel (= 4.0.2)
16
+ activerecord-deprecated_finders (~> 1.0.2)
17
+ activesupport (= 4.0.2)
18
+ arel (~> 4.0.0)
19
+ activerecord-deprecated_finders (1.0.3)
20
+ activesupport (4.0.2)
21
+ i18n (~> 0.6, >= 0.6.4)
22
+ minitest (~> 4.2)
23
+ multi_json (~> 1.3)
24
+ thread_safe (~> 0.1)
25
+ tzinfo (~> 0.3.37)
26
+ arel (4.0.2)
27
+ atomic (1.1.14)
28
+ builder (3.1.4)
29
+ coderay (1.1.0)
30
+ diff-lcs (1.2.5)
31
+ fakeredis (0.4.3)
32
+ redis (~> 3.0.0)
33
+ i18n (0.6.9)
34
+ json (1.8.1)
35
+ method_source (0.8.2)
36
+ minitest (4.7.5)
37
+ multi_json (1.8.4)
38
+ pry (0.9.12.4)
39
+ coderay (~> 1.0)
40
+ method_source (~> 0.8)
41
+ slop (~> 3.4)
42
+ rdoc (4.1.1)
43
+ json (~> 1.4)
44
+ redis (3.0.7)
45
+ redis-objects (0.9.0)
46
+ redis (>= 3.0.2)
47
+ rspec (2.14.1)
48
+ rspec-core (~> 2.14.0)
49
+ rspec-expectations (~> 2.14.0)
50
+ rspec-mocks (~> 2.14.0)
51
+ rspec-core (2.14.7)
52
+ rspec-expectations (2.14.5)
53
+ diff-lcs (>= 1.1.3, < 2.0)
54
+ rspec-mocks (2.14.5)
55
+ rubygems-tasks (0.2.4)
56
+ slop (3.4.7)
57
+ sqlite3 (1.3.8)
58
+ thread_safe (0.1.3)
59
+ atomic
60
+ tzinfo (0.3.38)
61
+
62
+ PLATFORMS
63
+ ruby
64
+
65
+ DEPENDENCIES
66
+ fakeredis
67
+ has_many_scored!
68
+ pry
69
+ rdoc (~> 4.1.0)
70
+ rspec (~> 2.4)
71
+ rubygems-tasks (~> 0.2)
72
+ sqlite3
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Hsiu-Fan Wang
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # has_many_scored
2
+
3
+ ## Description
4
+
5
+ An ActiveRecord plugin that combines an ordered habtm-like association with optional redis caching.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'has_many_scored'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install has_many_scored
20
+
21
+ ## Usage
22
+
23
+ TODO: Write usage instructions here
24
+
25
+ ## Contributing
26
+
27
+ 1. Fork it ( http://github.com/hfwang/has_many_scored/fork )
28
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
29
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
30
+ 4. Push to the branch (`git push origin my-new-feature`)
31
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,31 @@
1
+ # encoding: utf-8
2
+
3
+ require "bundler/gem_tasks"
4
+ require 'rake'
5
+
6
+ begin
7
+ gem 'rdoc'
8
+ require 'rdoc/task'
9
+
10
+ RDoc::Task.new do |rdoc|
11
+ rdoc.title = "has_many_scored"
12
+ end
13
+ rescue LoadError => e
14
+ warn e.message
15
+ warn "Run `gem install rdoc` to install 'rdoc/task'."
16
+ end
17
+ task :doc => :rdoc
18
+
19
+ begin
20
+ gem 'rspec', '~> 2.4'
21
+ require 'rspec/core/rake_task'
22
+
23
+ RSpec::Core::RakeTask.new
24
+ rescue LoadError => e
25
+ task :spec do
26
+ abort "Please run `gem install rspec` to install RSpec."
27
+ end
28
+ end
29
+
30
+ task :test => :spec
31
+ task :default => :spec
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require File.expand_path("../lib/has_many_scored/version", __FILE__)
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.name = "has_many_scored"
7
+ gem.version = HasManyScored::VERSION
8
+ gem.summary = %q{An ActiveRecord plugin that combines an ordered habtm-like association with optional redis caching}
9
+ gem.description = %q{An ActiveRecord plugin that combines an ordered habtm-like association with optional redis caching.}
10
+ gem.license = "MIT"
11
+ gem.authors = ["Hsiu-Fan Wang"]
12
+ gem.email = "hfwang@porkbuns.net"
13
+ gem.homepage = "https://rubygems.org/gems/has_many_scored"
14
+
15
+ gem.files = `git ls-files`.split($/)
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.require_paths = ["lib"]
19
+
20
+ gem.add_dependency("activerecord", ">= 3.0", "<= 4.0.2")
21
+ gem.add_dependency("redis-objects", ">= 0.6.1")
22
+
23
+ gem.add_development_dependency "pry"
24
+ gem.add_development_dependency "sqlite3"
25
+ gem.add_development_dependency "fakeredis"
26
+ gem.add_development_dependency "rdoc", "~> 4.1.0"
27
+ gem.add_development_dependency "rspec", "~> 2.4"
28
+ gem.add_development_dependency "rubygems-tasks", "~> 0.2"
29
+ end
@@ -0,0 +1,38 @@
1
+ module HasManyScored
2
+ # This module is used to extend the join model and mix in additional logic
3
+ module HasManyScoredExtension
4
+ def self.bind_extension(options)
5
+ return Proc.new do
6
+ include HasManyScored::HasManyScoredExtension
7
+
8
+ # Options is defined using define_method so opts can still be within scope.
9
+ define_method :options do
10
+ return options
11
+ end
12
+ end
13
+ end
14
+
15
+ def update_score(*records)
16
+ join_table = proxy_association.join_table
17
+ reflection = proxy_association.reflection
18
+
19
+ records.each do |record|
20
+ update_manager = Arel::UpdateManager.new(join_table.engine)
21
+ update_manager.table(join_table)\
22
+ .set(join_table[options[:score_column]] => self.compute_score(record))\
23
+ .where(join_table[reflection.foreign_key].eq(proxy_association.owner.id))\
24
+ .where(join_table[reflection.association_foreign_key].eq(record.id))\
25
+ .take(1)
26
+ proxy_association.owner.connection.execute(update_manager.to_sql)
27
+ end
28
+
29
+ reset
30
+
31
+ self
32
+ end
33
+
34
+ def compute_score(record)
35
+ record.send(options[:score_field])
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,40 @@
1
+ module HasManyScored
2
+ # This module is used to extend the join model and mix in additional logic
3
+ module ScoredForManyExtension
4
+ def self.bind_extension(options)
5
+ return Proc.new do
6
+ include HasManyScored::ScoredForManyExtension
7
+
8
+ # Options is defined using define_method so opts can still be within scope.
9
+ define_method :options do
10
+ return options
11
+ end
12
+ end
13
+ end
14
+
15
+ def update_score(*records)
16
+ join_table = proxy_association.join_table
17
+ reflection = proxy_association.reflection
18
+
19
+ owner_score = self.compute_score(proxy_association.owner)
20
+
21
+ records.each do |record|
22
+ update_manager = Arel::UpdateManager.new(join_table.engine)
23
+ update_manager.table(join_table)\
24
+ .set(join_table[options[:score_column]] => owner_score)\
25
+ .where(join_table[reflection.foreign_key].eq(proxy_association.owner.id))\
26
+ .where(join_table[reflection.association_foreign_key].eq(record.id))\
27
+ .take(1)
28
+ proxy_association.owner.connection.execute(update_manager.to_sql)
29
+ end
30
+
31
+ reset
32
+
33
+ self
34
+ end
35
+
36
+ def compute_score(record)
37
+ record.send(options[:score_field])
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,3 @@
1
+ module HasManyScored
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,63 @@
1
+ require "has_many_scored/version"
2
+ require "has_many_scored/has_many_scored_extension"
3
+ require "has_many_scored/scored_for_many_extension"
4
+
5
+ module HasManyScored
6
+ module ClassMethods
7
+ VALID_HABTM_OPTIONS = [:class_name, :join_table, :foreign_key,
8
+ :association_foreign_key, :readonly, :validate,
9
+ :autosave]
10
+
11
+ def has_many_scored(name, opts=nil)
12
+ opts = opts.try(:dup) || {}
13
+
14
+ habtm_opts = opts.select { |k, v| VALID_HABTM_OPTIONS.include?(k) }
15
+ habtm_opts[:insert_sql] = lambda { |record|
16
+ proxy_association = self.association(name)
17
+ join_table = proxy_association.join_table
18
+ reflection = proxy_association.reflection
19
+
20
+ return join_table.compile_insert(
21
+ join_table[reflection.foreign_key] => self.id,
22
+ join_table[reflection.association_foreign_key] => record.id,
23
+ join_table[opts[:score_column]] => proxy_association.scope.compute_score(record))
24
+ }
25
+
26
+ opts[:score_column] ||= :score
27
+ opts[:score_field] ||= :score
28
+
29
+ has_and_belongs_to_many(
30
+ name,
31
+ lambda { |owner| order("#{owner.association(name).join_table.name}.#{opts[:score_column]} DESC") },
32
+ habtm_opts, &HasManyScored::HasManyScoredExtension.bind_extension(opts))
33
+ end
34
+
35
+ def scored_for_many(name, opts=nil)
36
+ opts = opts.try(:dup) || {}
37
+
38
+ habtm_opts = opts.select { |k, v| VALID_HABTM_OPTIONS.include?(k) }
39
+ habtm_opts[:insert_sql] = lambda { |record|
40
+ proxy_association = self.association(name)
41
+ join_table = proxy_association.join_table
42
+ reflection = proxy_association.reflection
43
+
44
+ return join_table.compile_insert(
45
+ join_table[reflection.foreign_key] => self.id,
46
+ join_table[reflection.association_foreign_key] => record.id,
47
+ join_table[opts[:score_column]] => proxy_association.scope.compute_score(self))
48
+ }
49
+
50
+ opts[:score_column] ||= :score
51
+ opts[:score_field] ||= :score
52
+
53
+ has_and_belongs_to_many(
54
+ name,
55
+ lambda { |owner| order("#{owner.association(name).join_table.name}.#{opts[:score_column]} DESC") },
56
+ habtm_opts, &HasManyScored::HasManyScoredExtension.bind_extension(opts))
57
+ end
58
+ end
59
+
60
+ def self.included(base)
61
+ base.extend(ClassMethods)
62
+ end
63
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+ require 'has_many_scored'
3
+
4
+ describe HasManyScored do
5
+ it "should have a VERSION constant" do
6
+ subject.const_get('VERSION').should_not be_empty
7
+ end
8
+ end
@@ -0,0 +1,125 @@
1
+ require 'spec_helper'
2
+ require 'has_many_scored'
3
+
4
+ class Topic < ActiveRecord::Base
5
+ include HasManyScored
6
+ scored_for_many :tags
7
+ end
8
+ class Tag < ActiveRecord::Base
9
+ include HasManyScored
10
+ has_many_scored :topics
11
+ end
12
+
13
+ def setup_schema!
14
+ setup_db do
15
+ create_table :topics do |t|
16
+ t.column :name, :string
17
+ t.column :score, :float
18
+ end
19
+ create_table :tags do |t|
20
+ t.column :name, :string
21
+ end
22
+ create_table :tags_topics do |t|
23
+ t.column :topic_id, :integer
24
+ t.column :tag_id, :integer
25
+ t.column :score, :float
26
+ end
27
+ end
28
+ end
29
+
30
+ describe Tag do
31
+ before(:each) do
32
+ setup_schema!
33
+ end
34
+ after(:each) do
35
+ teardown_db
36
+ end
37
+ context "with dummy data" do
38
+ before do
39
+ @t1 = Topic.create(:name => "Topic 1", :score => 0.2)
40
+ @t2 = Topic.create(:name => "Topic 2", :score => 0.1)
41
+ @t3 = Topic.create(:name => "Topic 3", :score => 0.3)
42
+ @tag = Tag.create(:name => "Tag 1")
43
+ @tag.topics << @t1 << @t2 << @t3
44
+ end
45
+
46
+ it "computes size" do
47
+ expect(@tag.topics.size).to eq(3)
48
+ @tag.topics = []
49
+ expect(@tag.topics.size).to eq(0)
50
+ end
51
+
52
+ it "computes score when setting by ID" do
53
+ @tag.topic_ids = [@t1.id, @t2.id]
54
+ expect(@tag.topics(true).map(&:name)).to eq(["Topic 1", "Topic 2"])
55
+
56
+ @tag.topic_ids = [@t3.id]
57
+ expect(@tag.topics(true).map(&:name)).to eq(["Topic 3"])
58
+
59
+ @tag.topic_ids = [@t3.id, @t2.id, @t1.id]
60
+ expect(@tag.topics(true).map { |t| t.name }).to eq(["Topic 3", "Topic 1", "Topic 2"])
61
+ end
62
+
63
+ it "computes scores" do
64
+ expect(@tag.topics.compute_score(@t2)).to eq(0.1)
65
+ end
66
+
67
+ it "reads in scored order" do
68
+ # Sadly we have to call reload.
69
+ @tag.topics.reload
70
+
71
+ expect(@tag.topics.map { |t| t.name }).to eq(["Topic 3", "Topic 1", "Topic 2"])
72
+ expect(@tag.topics.first(2).map { |t| t.name }).to eq(["Topic 3", "Topic 1"])
73
+ end
74
+
75
+ it "handles delete" do
76
+ @tag.topics.delete(@t1)
77
+
78
+ expect(@tag.topics.map { |t| t.name }).to eq(["Topic 3", "Topic 2"])
79
+ end
80
+
81
+ it "handles update_score" do
82
+ @t2.score = 4.0
83
+ @t2.save
84
+ @tag.topics.update_score(@t2)
85
+
86
+ expect(Tag.first.topics.map { |t| t.name }).to eq(["Topic 2", "Topic 3", "Topic 1"])
87
+ end
88
+ end
89
+ end
90
+
91
+ describe Topic do
92
+ before(:each) do
93
+ setup_schema!
94
+ end
95
+ after(:each) do
96
+ teardown_db
97
+ end
98
+
99
+ context "with dummy data" do
100
+ before do
101
+ @t1 = Topic.create(:name => "Topic 1", :score => 0.2)
102
+ @t2 = Topic.create(:name => "Topic 2", :score => 0.1)
103
+ @t3 = Topic.create(:name => "Topic 3", :score => 0.3)
104
+ @tag1 = Tag.create(:name => "Tag 1")
105
+ @tag2 = Tag.create(:name => "Tag 2")
106
+ @tag2 = Tag.create(:name => "Tag 3")
107
+ @tag1.topics << @t2 << @t3
108
+ @t1.tags << @tag1 << @tag2
109
+ end
110
+
111
+ it "computes size" do
112
+ expect(@t1.tags.size).to eq(2)
113
+ @t1.tags = []
114
+ expect(@t1.tags.size).to eq(0)
115
+ end
116
+
117
+ it "reads in scored order" do
118
+ # Sadly we have to call reload.
119
+ @tag1.topics.reload
120
+
121
+ expect(@tag1.topics.map { |t| t.name }).to eq(["Topic 3", "Topic 1", "Topic 2"])
122
+ expect(@tag2.topics.map { |t| t.name }).to eq(["Topic 1"])
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,27 @@
1
+ gem "rspec", "~> 2.4"
2
+ require "rspec"
3
+ require "has_many_scored/version"
4
+
5
+ require "pry"
6
+ require "active_record"
7
+ require "fakeredis"
8
+ require "redis-objects"
9
+
10
+ include HasManyScored
11
+
12
+ ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
13
+ ActiveRecord::Schema.verbose = false
14
+
15
+ def setup_db(&block)
16
+ # AR caches columns options like defaults etc. Clear them!
17
+ ActiveRecord::Base.connection.schema_cache.clear!
18
+ ActiveRecord::Schema.define(version: 1, &block)
19
+
20
+ Redis.current.flushall
21
+ end
22
+
23
+ def teardown_db
24
+ ActiveRecord::Base.connection.tables.each do |table|
25
+ ActiveRecord::Base.connection.drop_table(table)
26
+ end
27
+ end
metadata ADDED
@@ -0,0 +1,182 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: has_many_scored
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Hsiu-Fan Wang
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-02-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ - - "<="
21
+ - !ruby/object:Gem::Version
22
+ version: 4.0.2
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '3.0'
30
+ - - "<="
31
+ - !ruby/object:Gem::Version
32
+ version: 4.0.2
33
+ - !ruby/object:Gem::Dependency
34
+ name: redis-objects
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: 0.6.1
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 0.6.1
47
+ - !ruby/object:Gem::Dependency
48
+ name: pry
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: sqlite3
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: fakeredis
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: rdoc
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: 4.1.0
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: 4.1.0
103
+ - !ruby/object:Gem::Dependency
104
+ name: rspec
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '2.4'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: '2.4'
117
+ - !ruby/object:Gem::Dependency
118
+ name: rubygems-tasks
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '0.2'
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: '0.2'
131
+ description: An ActiveRecord plugin that combines an ordered habtm-like association
132
+ with optional redis caching.
133
+ email: hfwang@porkbuns.net
134
+ executables: []
135
+ extensions: []
136
+ extra_rdoc_files: []
137
+ files:
138
+ - ".gitignore"
139
+ - ".rspec"
140
+ - ChangeLog.rdoc
141
+ - Gemfile
142
+ - Gemfile.lock
143
+ - LICENSE
144
+ - README.md
145
+ - Rakefile
146
+ - has_many_scored.gemspec
147
+ - lib/has_many_scored.rb
148
+ - lib/has_many_scored/has_many_scored_extension.rb
149
+ - lib/has_many_scored/scored_for_many_extension.rb
150
+ - lib/has_many_scored/version.rb
151
+ - spec/has_many_scored_spec.rb
152
+ - spec/simple_model_spec.rb
153
+ - spec/spec_helper.rb
154
+ homepage: https://rubygems.org/gems/has_many_scored
155
+ licenses:
156
+ - MIT
157
+ metadata: {}
158
+ post_install_message:
159
+ rdoc_options: []
160
+ require_paths:
161
+ - lib
162
+ required_ruby_version: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ required_rubygems_version: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - ">="
170
+ - !ruby/object:Gem::Version
171
+ version: '0'
172
+ requirements: []
173
+ rubyforge_project:
174
+ rubygems_version: 2.2.1
175
+ signing_key:
176
+ specification_version: 4
177
+ summary: An ActiveRecord plugin that combines an ordered habtm-like association with
178
+ optional redis caching
179
+ test_files:
180
+ - spec/has_many_scored_spec.rb
181
+ - spec/simple_model_spec.rb
182
+ - spec/spec_helper.rb