sundbp-dm-polymorphic 0.10.2

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Daniel Neighman
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,51 @@
1
+ Please see wiki for discussion.
2
+
3
+ The DM polymorphic gem mimics AR style polymorphism. It has been decided that DM will not follow this path, since it
4
+ really isn't very nice on the DB and there are other ways, that do not require DBA to cry to achieve the same result.
5
+
6
+ That being said this is still useful for those ppl wishing to convert rails apps over.
7
+
8
+ One Massive Caveat is that using this you will get n+1 calls to the db atm if you do Comments#commentable for example. It needs a proxy object if anyone cares to write one.
9
+
10
+ This is highly experimental software, use it at your own risk.
11
+
12
+ ==== Example Usage.
13
+
14
+ class Comment
15
+ include DataMapper::Resource
16
+
17
+ is :polymorphic, :commentable
18
+
19
+ property :id, Integer, :serial => true
20
+ property :text, String
21
+ end
22
+
23
+ class Post
24
+ include DataMapper::Resource
25
+
26
+ property :id, Integer, :serial => true
27
+ property :name, String
28
+
29
+ has n, :comments, :polymorphically => :commentable
30
+ end
31
+
32
+ class Article
33
+ include DataMapper::Resource
34
+
35
+ property :id, Integer, :serial => true
36
+ property :name, String
37
+
38
+ has n, :comments, :polymorphically => :commentable
39
+ end
40
+
41
+ This will then provide the following methods
42
+
43
+ Comment#commentable
44
+ Comment#post
45
+ Comment#article
46
+ Post#comments
47
+ Article#comments
48
+
49
+ What is needed is a
50
+ Comment.commentables or something method so there is a nice proxy to avoid having all the loading issues.
51
+
data/Rakefile ADDED
@@ -0,0 +1,60 @@
1
+ require "rubygems"
2
+ require "spec"
3
+ require "rake/clean"
4
+ require "rake/gempackagetask"
5
+ require "spec/rake/spectask"
6
+ require "pathname"
7
+
8
+ CLEAN.include "{log,pkg}/"
9
+
10
+ spec = Gem::Specification.new do |s|
11
+ s.name = "sundbp-dm-polymorphic"
12
+ s.version = "0.10.2"
13
+ s.platform = Gem::Platform::RUBY
14
+ s.has_rdoc = true
15
+ s.extra_rdoc_files = %w[ README LICENSE TODO ]
16
+ s.summary = "DataMapper plugin enabling simple ActiveRecord style polymorphism"
17
+ s.description = s.summary
18
+ s.author = "Daniel Neighman, Wayne E. Seguin, Ripta Pasay"
19
+ s.email = "has.sox@gmail.com, wayneeseguin@gmail.com, github@r8y.org"
20
+ s.homepage = "http://github.com/hassox/dm-polymorphic"
21
+ s.require_path = "lib"
22
+ s.files = FileList[ "{lib,spec}/**/*.rb", "spec/spec.opts", "Rakefile", *s.extra_rdoc_files ]
23
+ s.add_dependency("dm-core", ">=#{s.version}")
24
+ end
25
+
26
+ task :default => [ :spec ]
27
+
28
+ WIN32 = (RUBY_PLATFORM =~ /win32|mingw|cygwin/) rescue nil
29
+ SUDO = WIN32 ? "" : ("sudo" unless ENV["SUDOLESS"])
30
+
31
+ Rake::GemPackageTask.new(spec) do |pkg|
32
+ pkg.gem_spec = spec
33
+ end
34
+
35
+ desc "Install #{spec.name} #{spec.version} (default ruby)"
36
+ task :install => [ :package ] do
37
+ sh "#{SUDO} gem install pkg/#{spec.name}-#{spec.version} --no-update-sources", :verbose => false
38
+ end
39
+
40
+ namespace :jruby do
41
+ desc "Install #{spec.name} #{spec.version} with JRuby"
42
+ task :install => [ :package ] do
43
+ sh %{#{SUDO} jruby -S gem install --local pkg/#{spec.name}-#{spec.version} --no-update-sources}, :verbose => false
44
+ end
45
+ end
46
+
47
+ desc "Run specifications"
48
+ Spec::Rake::SpecTask.new(:spec) do |t|
49
+ t.spec_opts << "--options" << "spec/spec.opts" if File.exists?("spec/spec.opts")
50
+ t.spec_files = Pathname.glob(Pathname.new(__FILE__).dirname + "spec/**/*_spec.rb")
51
+
52
+ begin
53
+ t.rcov = ENV.has_key?("NO_RCOV") ? ENV["NO_RCOV"] != "true" : true
54
+ t.rcov_opts << "--exclude" << "spec"
55
+ t.rcov_opts << "--text-summary"
56
+ t.rcov_opts << "--sort" << "coverage" << "--sort-reverse"
57
+ rescue Exception
58
+ # rcov not installed
59
+ end
60
+ end
data/TODO ADDED
File without changes
@@ -0,0 +1,25 @@
1
+ module DataMapper
2
+ module Model
3
+ module Relationship
4
+
5
+ alias_method :has_without_polymorphism, :has
6
+
7
+ def has(cardinality, name, *args)
8
+ opts = args.extract_options!
9
+ if interface = opts.delete(:polymorphically)
10
+ # get the child model
11
+ child_model_name = opts.fetch(:class_name, Extlib::Inflection.classify(name))
12
+ child_klass = Extlib::Inflection.constantize(child_model_name)
13
+ belongs_to_name = Extlib::Inflection.underscore(Extlib::Inflection.demodulize(self.name))
14
+
15
+ # Setup the has with the right stuff
16
+ has_without_polymorphism cardinality, name, :child_key => [:"#{interface}_id"], :"#{interface}_class" => self
17
+ child_klass.belongs_to :"#{belongs_to_name}", :child_key => [:"#{interface}_id"], :"#{interface}_class" => self
18
+ else
19
+ has_without_polymorphism(cardinality, name, *(args + [opts]))
20
+ end
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,46 @@
1
+ require "rubygems"
2
+ require "pathname"
3
+
4
+ gem "dm-core", ">=0.10.0"
5
+ require "dm-core"
6
+
7
+
8
+ module DataMapper
9
+ module Is
10
+ module Polymorphic
11
+
12
+ def is_polymorphic(name, id_type = Serial)
13
+ self.class_eval <<-EOS, __FILE__, __LINE__
14
+ property :"#{name}_class", Klass
15
+ property :"#{name}_id", #{id_type}
16
+
17
+ def #{name}
18
+ return nil if self.#{name}_class.nil? || self.#{name}_class == NilClass
19
+ return nil if self.#{name}_id.nil?
20
+ if (self.#{name}_class.class == Class)
21
+ self.#{name}_class.get(self.#{name}_id)
22
+ else
23
+ klass = Kernel.const_get(self.#{name}_class.to_s)
24
+ if klass.ancestors.include? DataMapper::Resource
25
+ klass.get(self.#{name}_id)
26
+ else
27
+ nil
28
+ end
29
+ end
30
+ end
31
+
32
+ def #{name}=(entity)
33
+ self.#{name}_class = entity.class
34
+ self.#{name}_id = entity.id
35
+ end
36
+ EOS
37
+ end
38
+
39
+ end # Polymophic
40
+ end # Is
41
+ end
42
+
43
+ DataMapper::Model.append_extensions DataMapper::Is::Polymorphic
44
+
45
+ require Pathname(__FILE__).dirname.expand_path / "associations.rb"
46
+ require Pathname(__FILE__).dirname.expand_path / "types.rb"
data/lib/tester.rb ADDED
@@ -0,0 +1,50 @@
1
+ require File.join(File.dirname(__FILE__), "dm-polymorphic")
2
+
3
+ DataMapper::Logger.new(STDOUT, :debug)
4
+ DataMapper.setup(:default, 'sqlite3::memory:')
5
+
6
+ class Comment
7
+ include DataMapper::Resource
8
+
9
+ is :polymorphic, :commentable
10
+
11
+ property :id, Integer, :serial => true
12
+ property :text, String
13
+ end
14
+
15
+ class Post
16
+ include DataMapper::Resource
17
+
18
+ property :id, Integer, :serial => true
19
+ property :name, String
20
+
21
+ has n, :comments, :polymorphically => :commentable
22
+ end
23
+
24
+ class Article
25
+ include DataMapper::Resource
26
+
27
+ property :id, Integer, :serial => true
28
+ property :name, String
29
+
30
+ has n, :comments, :polymorphically => :commentable
31
+ end
32
+
33
+ Comment.auto_migrate!
34
+ Post.auto_migrate!
35
+ Article.auto_migrate!
36
+
37
+ post1 = Post.create(:name => "post1")
38
+ article1 = Article.create(:name => "article1")
39
+ post2 = Post.create(:name => "post2")
40
+ article2 = Article.create(:name => "article2")
41
+
42
+ %w(one two three four five six seven eight nine ten).each_with_index do |text, index|
43
+ [post1, post2, article1, article2].each do |item|
44
+ item.comments << Comment.new(:text => text)
45
+ end
46
+ end
47
+
48
+ Comment.all.each do |c|
49
+ puts "COMMENT: #{c.text} - #{c.commentable}"
50
+ end
data/lib/types.rb ADDED
@@ -0,0 +1,7 @@
1
+ module DataMapper
2
+ module Types
3
+ class Klass < DataMapper::Type
4
+ primitive Class
5
+ end # class Klass
6
+ end # module Types
7
+ end # module DataMapper
@@ -0,0 +1,121 @@
1
+ require File.dirname(__FILE__) + "/spec_helper"
2
+
3
+ DataMapper::Logger.new(STDOUT, :debug)
4
+
5
+ if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
6
+ describe "DataMapper::Polymorphic" do
7
+
8
+ class Comment
9
+ include DataMapper::Resource
10
+
11
+ is :polymorphic, :commentable
12
+
13
+ property :id, Serial
14
+ property :text, String
15
+ end
16
+
17
+ class Post
18
+ include DataMapper::Resource
19
+
20
+ property :id, Serial
21
+ property :name, String
22
+
23
+ has n, :comments, :polymorphically => :commentable
24
+ end
25
+
26
+ class Article
27
+ include DataMapper::Resource
28
+
29
+ property :id, Serial
30
+ property :name, String
31
+
32
+ has n, :comments, :polymorphically => :commentable
33
+ end
34
+
35
+ before :each do
36
+ Comment.auto_migrate!
37
+ Post.auto_migrate!
38
+ Article.auto_migrate!
39
+ end
40
+
41
+ [Article, Post].each do |klass|
42
+ it "should create an associated object for #{klass}" do
43
+ item = klass.create(:name => "item1")
44
+ item.reload
45
+ item.comments.create(:text => "A Comment")
46
+ item.reload
47
+ item.comments(:text => "A Comment").should have(1).item
48
+ end
49
+
50
+ it "should add the comment with the << syntax for #{klass}" do
51
+ item = klass.create(:name => "item2")
52
+ c = Comment.new(:text => "comment2")
53
+ item.comments << c
54
+ c.save
55
+ item.reload
56
+ item.comments(:text => "comment2").should have(1).item
57
+ end
58
+
59
+ it "should not add the comment with the << syntax for #{klass} if comment was not saved" do
60
+ item = klass.create(:name => "item2a")
61
+ c = Comment.new(:text => "comment2a")
62
+ item.comments << c
63
+ item.reload
64
+ item.comments(:text => "comment2a").should have(0).item
65
+ end
66
+
67
+ it "should access all the comments from the post for #{klass}" do
68
+ item = klass.create(:name => "item3")
69
+ c1 = Comment.new(:text => "comment3")
70
+ c2 = Comment.new(:text => "comment4")
71
+ [c1,c2].each{|c| item.comments << c}
72
+ item.comments.save
73
+ item.reload
74
+ item.comments.should have(2).items
75
+ end
76
+
77
+ it "should access the post from the comment for #{klass}" do
78
+ item = klass.create(:name => "item4")
79
+ c = Comment.new(:text => "comment5")
80
+ item.comments << c
81
+ item.save
82
+ c.send(Extlib::Inflection.underscore(klass.name).to_sym).should == item
83
+ end
84
+
85
+ it "should access the commentable from the comment for #{klass}" do
86
+ item = klass.create(:name => "item5")
87
+ c = Comment.new(:text => "comment6")
88
+ item.comments << c
89
+ c.save
90
+ item.reload; c.reload
91
+ c.commentable.should == item
92
+ end
93
+ end
94
+
95
+ # it "should only make one query to each Model" do
96
+ # post1 = Post.create(:name => "post1")
97
+ # article1 = Article.create(:name => "article1")
98
+ # post2 = Post.create(:name => "post2")
99
+ # article2 = Article.create(:name => "article2")
100
+ #
101
+ # %w(one two three four five six seven eight nine ten).each_with_index do |text, index|
102
+ # [post1, post2, article1, article2].each do |item|
103
+ # item.comments.create(:text => text)
104
+ # end
105
+ # end
106
+ #
107
+ # Post.all.each do |c|
108
+ # puts "COMMENT: #{c.text} - #{c.commentable_class}"
109
+ # end
110
+ #
111
+ # Post.should_receive(:all).once
112
+ # Article.should_receive(:all).once.and_return(Article.comments)
113
+ #
114
+ # Comment.all.each do |comment|
115
+ # [Post, Article].should include(comment.commentable.class)
116
+ # end
117
+ # end
118
+
119
+ end
120
+ end
121
+
data/spec/spec.opts ADDED
@@ -0,0 +1,2 @@
1
+ --format specdoc
2
+ --colour
@@ -0,0 +1,31 @@
1
+ require "rubygems"
2
+ require "pathname"
3
+
4
+ gem "dm-core", ">=0.10.0"
5
+ require "dm-core"
6
+
7
+ spec_dir_path = Pathname(__FILE__).dirname.expand_path
8
+ require spec_dir_path.parent + "lib/dm-polymorphic"
9
+
10
+ def load_driver(name, default_uri)
11
+ return false if ENV["ADAPTER"] != name.to_s
12
+
13
+ lib = "do_#{name}"
14
+
15
+ begin
16
+ gem lib, ">=0.10.0"
17
+ require lib
18
+ DataMapper.setup(name, ENV["#{name.to_s.upcase}_SPEC_URI"] || default_uri)
19
+ DataMapper::Repository.adapters[:default] = DataMapper::Repository.adapters[name]
20
+ true
21
+ rescue Gem::LoadError => e
22
+ warn "Could not load #{lib}: #{e}"
23
+ false
24
+ end
25
+ end
26
+
27
+ ENV["ADAPTER"] ||= "sqlite3"
28
+
29
+ HAS_SQLITE3 = load_driver(:sqlite3, "sqlite3::memory:")
30
+ HAS_MYSQL = load_driver(:mysql, "mysql://localhost/dm_core_test")
31
+ HAS_POSTGRES = load_driver(:postgres, "postgres://postgres@localhost/dm_core_test")
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sundbp-dm-polymorphic
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.10.2
5
+ platform: ruby
6
+ authors:
7
+ - Daniel Neighman, Wayne E. Seguin, Ripta Pasay
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-01-12 00:00:00 +00:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: dm-core
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.10.2
24
+ version:
25
+ description: DataMapper plugin enabling simple ActiveRecord style polymorphism
26
+ email: has.sox@gmail.com, wayneeseguin@gmail.com, github@r8y.org
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README
33
+ - LICENSE
34
+ - TODO
35
+ files:
36
+ - lib/associations.rb
37
+ - lib/dm-polymorphic.rb
38
+ - lib/tester.rb
39
+ - lib/types.rb
40
+ - spec/dm-polymorphic_spec.rb
41
+ - spec/spec_helper.rb
42
+ - spec/spec.opts
43
+ - Rakefile
44
+ - README
45
+ - LICENSE
46
+ - TODO
47
+ has_rdoc: true
48
+ homepage: http://github.com/hassox/dm-polymorphic
49
+ licenses: []
50
+
51
+ post_install_message:
52
+ rdoc_options: []
53
+
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ version:
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: "0"
67
+ version:
68
+ requirements: []
69
+
70
+ rubyforge_project:
71
+ rubygems_version: 1.3.5
72
+ signing_key:
73
+ specification_version: 3
74
+ summary: DataMapper plugin enabling simple ActiveRecord style polymorphism
75
+ test_files: []
76
+