-
-
Notifications
You must be signed in to change notification settings - Fork 807
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1002 from gregmolnar/polyamorous-gem
make polyamorous a separate gem
- Loading branch information
Showing
27 changed files
with
370 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module Polyamorous | ||
VERSION = '2.1.1' | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# -*- encoding: utf-8 -*- | ||
$:.push File.expand_path("../lib", __FILE__) | ||
require "polyamorous/version" | ||
|
||
Gem::Specification.new do |s| | ||
s.name = "polyamorous" | ||
s.version = Polyamorous::VERSION | ||
s.authors = ["Ernie Miller", "Ryan Bigg", "Jon Atack", "Xiang Li"] | ||
s.email = ["[email protected]", "[email protected]", "[email protected]", "[email protected]"] | ||
s.homepage = "https://github.com/activerecord-hackery/ransack/tree/master/polyamorous" | ||
s.license = "MIT" | ||
s.summary = %q{ | ||
Loves/is loved by polymorphic belongs_to associations, Ransack, Squeel, MetaSearch... | ||
} | ||
s.description = %q{ | ||
This is just an extraction from Ransack/Squeel. You probably don't want to use this | ||
directly. It extends ActiveRecord's associations to support polymorphic belongs_to | ||
associations. | ||
} | ||
|
||
s.rubyforge_project = "polyamorous" | ||
|
||
s.add_dependency 'activerecord', '>= 5.0' | ||
s.add_development_dependency 'rspec', '~> 3' | ||
s.add_development_dependency 'machinist', '~> 1.0.6' | ||
s.add_development_dependency 'faker', '~> 1.6.5' | ||
s.add_development_dependency 'sqlite3', '~> 1.3.3' | ||
|
||
s.files = `git ls-files`.split("\n") | ||
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") | ||
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } | ||
s.require_paths = ["lib"] | ||
|
||
# specify any dependencies here; for example: | ||
# s.add_development_dependency "rspec" | ||
# s.add_runtime_dependency "rest-client" | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
Article.blueprint do | ||
person | ||
title | ||
body | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
Comment.blueprint do | ||
article | ||
person | ||
body | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
Note.blueprint do | ||
note | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
Person.blueprint do | ||
name | ||
salary | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
Tag.blueprint do | ||
name { Sham.tag_name } | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
module PolyamorousHelper | ||
if ActiveRecord::VERSION::STRING >= "4.1" | ||
def new_join_association(reflection, children, klass) | ||
Polyamorous::JoinAssociation.new reflection, children, klass | ||
end | ||
else | ||
def new_join_association(reflection, join_dependency, parent, klass) | ||
Polyamorous::JoinAssociation.new reflection, join_dependency, parent, klass | ||
end | ||
end | ||
|
||
if ActiveRecord::VERSION::STRING >= "5.2" | ||
def new_join_dependency(klass, associations = {}) | ||
alias_tracker = ::ActiveRecord::Associations::AliasTracker.create(klass.connection, klass.table_name, []) | ||
Polyamorous::JoinDependency.new klass, klass.arel_table, associations, alias_tracker | ||
end | ||
else | ||
def new_join_dependency(klass, associations = {}) | ||
Polyamorous::JoinDependency.new klass, associations, [] | ||
end | ||
end | ||
|
||
def new_join(name, type = Polyamorous::InnerJoin, klass = nil) | ||
Polyamorous::Join.new name, type, klass | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
require 'spec_helper' | ||
|
||
module Polyamorous | ||
describe JoinAssociation do | ||
|
||
join_base, join_association_args, polymorphic = [:join_root, 'parent.children', 'reflection.options[:polymorphic]'] | ||
let(:join_dependency) { new_join_dependency Note, {} } | ||
let(:reflection) { Note.reflect_on_association(:notable) } | ||
let(:parent) { join_dependency.send(join_base) } | ||
let(:join_association) { | ||
eval("new_join_association(reflection, #{join_association_args}, Article)") | ||
} | ||
|
||
it 'leaves the orginal reflection intact for thread safety' do | ||
reflection.instance_variable_set(:@klass, Article) | ||
join_association | ||
.swapping_reflection_klass(reflection, Person) do |new_reflection| | ||
expect(new_reflection.options).not_to equal reflection.options | ||
expect(new_reflection.options).not_to have_key(:polymorphic) | ||
expect(new_reflection.klass).to eq(Person) | ||
expect(reflection.klass).to eq(Article) | ||
end | ||
end | ||
|
||
it 'sets the polymorphic option to true after initializing' do | ||
expect(join_association.instance_eval(polymorphic)).to be true | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
require 'spec_helper' | ||
|
||
module Polyamorous | ||
describe JoinDependency do | ||
|
||
method, join_associations, join_base = | ||
if ActiveRecord::VERSION::STRING >= '4.1' | ||
[:instance_eval, 'join_root.drop(1)', :join_root] | ||
else | ||
[:send, 'join_associations', :join_base] | ||
end | ||
|
||
context 'with symbol joins' do | ||
subject { new_join_dependency Person, articles: :comments } | ||
|
||
specify { expect(subject.send(method, join_associations).size) | ||
.to eq(2) } | ||
specify { expect(subject.send(method, join_associations).map(&:join_type)) | ||
.to be_all { Polyamorous::InnerJoin } } | ||
end | ||
|
||
context 'with has_many :through association' do | ||
subject { new_join_dependency Person, :authored_article_comments } | ||
|
||
specify { expect(subject.send(method, join_associations).size) | ||
.to eq 1 } | ||
specify { expect(subject.send(method, join_associations).first.table_name) | ||
.to eq 'comments' } | ||
end | ||
|
||
context 'with outer join' do | ||
subject { new_join_dependency Person, new_join(:articles, :outer) } | ||
|
||
specify { expect(subject.send(method, join_associations).size) | ||
.to eq 1 } | ||
specify { expect(subject.send(method, join_associations).first.join_type) | ||
.to eq Polyamorous::OuterJoin } | ||
end | ||
|
||
context 'with nested outer joins' do | ||
subject { new_join_dependency Person, | ||
new_join(:articles, :outer) => new_join(:comments, :outer) } | ||
|
||
specify { expect(subject.send(method, join_associations).size) | ||
.to eq 2 } | ||
specify { expect(subject.send(method, join_associations).map(&:join_type)) | ||
.to eq [Polyamorous::OuterJoin, Polyamorous::OuterJoin] } | ||
specify { expect(subject.send(method, join_associations).map(&:join_type)) | ||
.to be_all { Polyamorous::OuterJoin } } | ||
end | ||
|
||
context 'with polymorphic belongs_to join' do | ||
subject { new_join_dependency Note, new_join(:notable, :inner, Person) } | ||
|
||
specify { expect(subject.send(method, join_associations).size) | ||
.to eq 1 } | ||
specify { expect(subject.send(method, join_associations).first.join_type) | ||
.to eq Polyamorous::InnerJoin } | ||
specify { expect(subject.send(method, join_associations).first.table_name) | ||
.to eq 'people' } | ||
end | ||
|
||
context 'with polymorphic belongs_to join and nested symbol join' do | ||
subject { new_join_dependency Note, | ||
new_join(:notable, :inner, Person) => :comments } | ||
|
||
specify { expect(subject.send(method, join_associations).size) | ||
.to eq 2 } | ||
specify { expect(subject.send(method, join_associations).map(&:join_type)) | ||
.to be_all { Polyamorous::InnerJoin } } | ||
specify { expect(subject.send(method, join_associations).first.table_name) | ||
.to eq 'people' } | ||
specify { expect(subject.send(method, join_associations)[1].table_name) | ||
.to eq 'comments' } | ||
end | ||
|
||
context '#left_outer_join in Rails 5 overrides join type specified', | ||
if: ActiveRecord::VERSION::MAJOR >= 5 && ActiveRecord::VERSION::MINOR < 2 do | ||
|
||
let(:join_type_class) do | ||
new_join_dependency( | ||
Person, | ||
new_join(:articles) | ||
).join_constraints( | ||
[], | ||
Arel::Nodes::OuterJoin | ||
).first.joins.map(&:class) | ||
end | ||
|
||
specify { expect(join_type_class).to eq [Arel::Nodes::OuterJoin] } | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
require 'spec_helper' | ||
|
||
module Polyamorous | ||
describe Join do | ||
it 'is a tree node' do | ||
join = new_join(:articles, :outer) | ||
expect(join).to be_kind_of(TreeNode) | ||
end | ||
|
||
it 'can be added to a tree' do | ||
join = new_join(:articles, :outer) | ||
|
||
tree_hash = {} | ||
join.add_to_tree(tree_hash) | ||
|
||
expect(tree_hash[join]).to be {} | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
require 'machinist/active_record' | ||
require 'sham' | ||
require 'faker' | ||
require 'polyamorous' | ||
|
||
Time.zone = 'Eastern Time (US & Canada)' | ||
|
||
Dir[File.expand_path('../{helpers,support,blueprints}/**/*.rb', __FILE__)] | ||
.each do |f| | ||
require f | ||
end | ||
|
||
Sham.define do | ||
name { Faker::Name.name } | ||
title { Faker::Lorem.sentence } | ||
body { Faker::Lorem.paragraph } | ||
salary { |index| 30000 + (index * 1000) } | ||
tag_name { Faker::Lorem.words(3).join(' ') } | ||
note { Faker::Lorem.words(7).join(' ') } | ||
end | ||
|
||
RSpec.configure do |config| | ||
config.before(:suite) do | ||
message = "Running Polyamorous specs with #{ | ||
ActiveRecord::Base.connection.adapter_name | ||
}, Active Record #{::ActiveRecord::VERSION::STRING}, Arel #{Arel::VERSION | ||
} and Ruby #{RUBY_VERSION}" | ||
line = '=' * message.length | ||
puts line, message, line | ||
Schema.create | ||
end | ||
config.before(:all) { Sham.reset(:before_all) } | ||
config.before(:each) { Sham.reset(:before_each) } | ||
|
||
config.include PolyamorousHelper | ||
end | ||
|
||
RSpec::Matchers.define :be_like do |expected| | ||
match do |actual| | ||
actual.gsub(/^\s+|\s+$/, '').gsub(/\s+/, ' ').strip == | ||
expected.gsub(/^\s+|\s+$/, '').gsub(/\s+/, ' ').strip | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
require 'active_record' | ||
|
||
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:') | ||
|
||
class Person < ActiveRecord::Base | ||
belongs_to :parent, class_name: 'Person', foreign_key: :parent_id | ||
has_many :children, class_name: 'Person', foreign_key: :parent_id | ||
has_many :articles | ||
has_many :comments | ||
has_many :authored_article_comments, through: :articles, | ||
foreign_key: :person_id, source: :comments | ||
has_many :notes, as: :notable | ||
end | ||
|
||
class Article < ActiveRecord::Base | ||
belongs_to :person | ||
has_many :comments | ||
has_and_belongs_to_many :tags | ||
has_many :notes, as: :notable | ||
end | ||
|
||
class Comment < ActiveRecord::Base | ||
belongs_to :article | ||
belongs_to :person | ||
end | ||
|
||
class Tag < ActiveRecord::Base | ||
has_and_belongs_to_many :articles | ||
end | ||
|
||
class Note < ActiveRecord::Base | ||
belongs_to :notable, polymorphic: true | ||
end | ||
|
||
module Schema | ||
def self.create | ||
ActiveRecord::Migration.verbose = false | ||
|
||
ActiveRecord::Schema.define do | ||
create_table :people, force: true do |t| | ||
t.integer :parent_id | ||
t.string :name | ||
t.integer :salary | ||
t.boolean :awesome, default: false | ||
t.timestamps null: false | ||
end | ||
|
||
create_table :articles, force: true do |t| | ||
t.integer :person_id | ||
t.string :title | ||
t.text :body | ||
end | ||
|
||
create_table :comments, force: true do |t| | ||
t.integer :article_id | ||
t.integer :person_id | ||
t.text :body | ||
end | ||
|
||
create_table :tags, force: true do |t| | ||
t.string :name | ||
end | ||
|
||
create_table :articles_tags, force: true, id: false do |t| | ||
t.integer :article_id | ||
t.integer :tag_id | ||
end | ||
|
||
create_table :notes, force: true do |t| | ||
t.integer :notable_id | ||
t.string :notable_type | ||
t.string :note | ||
end | ||
end | ||
|
||
10.times do | ||
person = Person.make | ||
Note.make(notable: person) | ||
3.times do | ||
article = Article.make(person: person) | ||
3.times do | ||
article.tags = [Tag.make, Tag.make, Tag.make] | ||
end | ||
Note.make(notable: article) | ||
10.times do | ||
Comment.make(article: article) | ||
end | ||
end | ||
2.times do | ||
Comment.make(person: person) | ||
end | ||
end | ||
|
||
Comment.make( | ||
body: 'First post!', article: Article.make(title: 'Hello, world!') | ||
) | ||
end | ||
end |
Oops, something went wrong.