dm-accepts_nested_attributes 0.12.0 → 1.0.0.rc1
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/.gitignore +3 -0
- data/Gemfile +145 -0
- data/Rakefile +6 -11
- data/VERSION +1 -0
- data/dm-accepts_nested_attributes.gemspec +18 -17
- data/lib/dm-accepts_nested_attributes/model.rb +0 -38
- data/spec/accepts_nested_attributes_for_spec.rb +4 -4
- data/spec/many_to_many_spec.rb +5 -5
- data/spec/many_to_one_spec.rb +3 -3
- data/spec/one_to_many_spec.rb +3 -3
- data/spec/one_to_one_spec.rb +4 -4
- data/spec/shared/many_to_many_spec.rb +35 -51
- data/spec/shared/many_to_one_spec.rb +5 -25
- data/spec/shared/one_to_many_spec.rb +0 -21
- data/spec/shared/one_to_one_spec.rb +0 -19
- data/spec/spec_helper.rb +17 -33
- data/tasks/local_gemfile.rake +18 -0
- data/tasks/spec.rake +0 -3
- metadata +58 -25
- data/lib/dm-accepts_nested_attributes/error_collecting.rb +0 -35
- data/lib/dm-accepts_nested_attributes/transactional_save.rb +0 -24
data/.gitignore
CHANGED
data/Gemfile
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
# If you're working on more than one datamapper gem at a time, then it's
|
2
|
+
# recommended to create a local Gemfile and use this instead of the git
|
3
|
+
# sources. This will make sure that you are developing against your
|
4
|
+
# other local datamapper sources that you currently work on. Gemfile.local
|
5
|
+
# will behave identically to the standard Gemfile apart from the fact that
|
6
|
+
# it fetches the datamapper gems from local paths. This means that you can use
|
7
|
+
# the same environment variables, like ADAPTER(S) or PLUGIN(S) when running
|
8
|
+
# bundle commands. Gemfile.local is added to .gitignore, so you don't need to
|
9
|
+
# worry about accidentally checking local development paths into git.
|
10
|
+
# In order to create a local Gemfile, all you need to do is run:
|
11
|
+
#
|
12
|
+
# bundle exec rake local_gemfile
|
13
|
+
#
|
14
|
+
# This will give you a Gemfile.local file that points to your local clones of
|
15
|
+
# the various datamapper gems. It's assumed that all datamapper repo clones
|
16
|
+
# reside in the same directory. You can use the Gemfile.local like so for
|
17
|
+
# running any bundle command:
|
18
|
+
#
|
19
|
+
# BUNDLE_GEMFILE=Gemfile.local bundle foo
|
20
|
+
#
|
21
|
+
# You can also specify which adapter(s) should be part of the bundle by setting
|
22
|
+
# an environment variable. This of course also works when using the Gemfile.local
|
23
|
+
#
|
24
|
+
# bundle foo # dm-sqlite-adapter
|
25
|
+
# ADAPTER=mysql bundle foo # dm-mysql-adapter
|
26
|
+
# ADAPTERS=sqlite,mysql bundle foo # dm-sqlite-adapter and dm-mysql-adapter
|
27
|
+
#
|
28
|
+
# Of course you can also use the ADAPTER(S) variable when using the Gemfile.local
|
29
|
+
# and running specs against selected adapters.
|
30
|
+
#
|
31
|
+
# For easily working with adapters supported on your machine, it's recommended
|
32
|
+
# that you first install all adapters that you are planning to use or work on
|
33
|
+
# by doing something like
|
34
|
+
#
|
35
|
+
# ADAPTERS=sqlite,mysql,postgres bundle install
|
36
|
+
#
|
37
|
+
# This will clone the various repositories and make them available to bundler.
|
38
|
+
# Once you have them installed you can easily switch between adapters for the
|
39
|
+
# various development tasks. Running something like
|
40
|
+
#
|
41
|
+
# ADAPTER=mysql bundle exec rake spec
|
42
|
+
#
|
43
|
+
# will make sure that the dm-mysql-adapter is part of the bundle, and will be used
|
44
|
+
# when running the specs.
|
45
|
+
#
|
46
|
+
# You can also specify which plugin(s) should be part of the bundle by setting
|
47
|
+
# an environment variable. This also works when using the Gemfile.local
|
48
|
+
#
|
49
|
+
# bundle foo # dm-migrations
|
50
|
+
# PLUGINS=dm-validations bundle foo # dm-migrations and dm-validations
|
51
|
+
# PLUGINS=dm-validations,dm-types bundle foo # dm-migrations, dm-validations and dm-types
|
52
|
+
#
|
53
|
+
# Of course you can combine the PLUGIN(S) and ADAPTER(S) env vars to run specs
|
54
|
+
# for certain adapter/plugin combinations.
|
55
|
+
#
|
56
|
+
# Finally, to speed up running specs and other tasks, it's recommended to run
|
57
|
+
#
|
58
|
+
# bundle lock
|
59
|
+
#
|
60
|
+
# after running 'bundle install' for the first time. This will make 'bundle exec' run
|
61
|
+
# a lot faster compared to the unlocked version. With an unlocked bundle you would
|
62
|
+
# typically just run 'bundle install' from time to time to fetch the latest sources from
|
63
|
+
# upstream. When you locked your bundle, you need to run
|
64
|
+
#
|
65
|
+
# bundle install --relock
|
66
|
+
#
|
67
|
+
# to make sure to fetch the latest updates and then lock the bundle again. Gemfile.lock
|
68
|
+
# is added to the .gitignore file, so you don't need to worry about accidentally checking
|
69
|
+
# it into version control.
|
70
|
+
|
71
|
+
source 'http://rubygems.org'
|
72
|
+
|
73
|
+
DATAMAPPER = 'git://github.com/datamapper'
|
74
|
+
DM_VERSION = '~> 1.0.0.rc1'
|
75
|
+
|
76
|
+
|
77
|
+
group :runtime do # Runtime dependencies (as in the gemspec)
|
78
|
+
|
79
|
+
if ENV['EXTLIB']
|
80
|
+
gem 'extlib', '~> 0.9.15', :git => "#{DATAMAPPER}/extlib.git"
|
81
|
+
else
|
82
|
+
gem 'activesupport', '~> 3.0.0.beta3', :git => 'git://github.com/rails/rails.git', :require => nil
|
83
|
+
end
|
84
|
+
|
85
|
+
gem 'dm-core', DM_VERSION, :git => "#{DATAMAPPER}/dm-core.git"
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
group(:development) do # Development dependencies (as in the gemspec)
|
90
|
+
|
91
|
+
gem 'dm-validations', DM_VERSION, :git => "#{DATAMAPPER}/dm-validations.git"
|
92
|
+
gem 'dm-constraints', DM_VERSION, :git => "#{DATAMAPPER}/dm-constraints.git"
|
93
|
+
|
94
|
+
gem 'rake', '~> 0.8.7'
|
95
|
+
gem 'rspec', '~> 1.3'
|
96
|
+
gem 'yard', '~> 0.5'
|
97
|
+
gem 'rcov', '~> 0.9.7'
|
98
|
+
gem 'jeweler', '~> 1.4'
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
group :quality do # These gems contain rake tasks that check the quality of the source code
|
103
|
+
|
104
|
+
gem 'yardstick', '~> 0.1'
|
105
|
+
gem 'metric_fu', '~> 1.3'
|
106
|
+
gem 'reek', '~> 1.2.7'
|
107
|
+
gem 'roodi', '~> 2.1'
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
group :datamapper do # We need this because we want to pin these dependencies to their git master sources
|
112
|
+
|
113
|
+
adapters = ENV['ADAPTER'] || ENV['ADAPTERS']
|
114
|
+
adapters = adapters.to_s.gsub(',',' ').split(' ') - ['in_memory']
|
115
|
+
|
116
|
+
unless adapters.empty?
|
117
|
+
|
118
|
+
DO_VERSION = '~> 0.10.2'
|
119
|
+
DM_DO_ADAPTERS = %w[sqlite postgres mysql oracle sqlserver]
|
120
|
+
|
121
|
+
gem 'data_objects', DO_VERSION, :git => "#{DATAMAPPER}/do.git"
|
122
|
+
|
123
|
+
adapters.each do |adapter|
|
124
|
+
if DM_DO_ADAPTERS.any? { |dm_do_adapter| dm_do_adapter =~ /#{adapter}/ }
|
125
|
+
adapter = 'sqlite3' if adapter == 'sqlite'
|
126
|
+
gem "do_#{adapter}", DO_VERSION, :git => "#{DATAMAPPER}/do.git"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
gem 'dm-do-adapter', DM_VERSION, :git => "#{DATAMAPPER}/dm-do-adapter.git"
|
131
|
+
|
132
|
+
adapters.each do |adapter|
|
133
|
+
gem "dm-#{adapter}-adapter", DM_VERSION, :git => "#{DATAMAPPER}/dm-#{adapter}-adapter.git"
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
plugins = ENV['PLUGINS'] || ENV['PLUGIN']
|
139
|
+
plugins = (plugins.to_s.gsub(',',' ').split(' ') + ['dm-migrations']).uniq
|
140
|
+
|
141
|
+
plugins.each do |plugin|
|
142
|
+
gem plugin, DM_VERSION, :git => "#{DATAMAPPER}/#{plugin}.git"
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
data/Rakefile
CHANGED
@@ -1,35 +1,30 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'rake'
|
3
3
|
|
4
|
-
require File.expand_path('../lib/dm-accepts_nested_attributes/version', __FILE__)
|
5
|
-
|
6
|
-
FileList['tasks/**/*.rake'].each { |task| load task }
|
7
|
-
|
8
4
|
begin
|
9
5
|
|
10
|
-
gem 'jeweler', '~> 1.4'
|
11
6
|
require 'jeweler'
|
12
7
|
|
13
8
|
Jeweler::Tasks.new do |gem|
|
14
9
|
|
15
|
-
gem.version = DataMapper::NestedAttributes::VERSION
|
16
|
-
|
17
10
|
gem.name = 'dm-accepts_nested_attributes'
|
18
11
|
gem.summary = 'Nested model assignment for datamapper'
|
19
12
|
gem.description = 'A datamapper plugin that allows nested model assignment like activerecord.'
|
20
13
|
gem.email = 'gamsnjaga [a] gmail [d] com'
|
21
14
|
gem.homepage = 'http://github.com/snusnu/dm-accepts_nested_attributes'
|
22
|
-
gem.authors = [ 'Martin Gamsjaeger' ]
|
15
|
+
gem.authors = [ 'Martin Gamsjaeger (snusnu)' ]
|
23
16
|
|
24
|
-
gem.add_dependency
|
17
|
+
gem.add_dependency 'dm-core', '~> 1.0.0.rc1'
|
25
18
|
|
26
|
-
gem.add_development_dependency 'rspec',
|
27
|
-
gem.add_development_dependency 'yard',
|
19
|
+
gem.add_development_dependency 'rspec', '~> 1.3'
|
20
|
+
gem.add_development_dependency 'yard', '~> 0.5'
|
28
21
|
|
29
22
|
end
|
30
23
|
|
31
24
|
Jeweler::GemcutterTasks.new
|
32
25
|
|
26
|
+
FileList['tasks/**/*.rake'].each { |task| import task }
|
27
|
+
|
33
28
|
rescue LoadError
|
34
29
|
puts 'Jeweler (or a dependency) not available. Install it with: gem install jeweler'
|
35
30
|
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.0.rc1
|
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{dm-accepts_nested_attributes}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "1.0.0.rc1"
|
9
9
|
|
10
|
-
s.required_rubygems_version = Gem::Requirement.new("
|
11
|
-
s.authors = ["Martin Gamsjaeger"]
|
12
|
-
s.date = %q{2010-
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Martin Gamsjaeger (snusnu)"]
|
12
|
+
s.date = %q{2010-05-20}
|
13
13
|
s.description = %q{A datamapper plugin that allows nested model assignment like activerecord.}
|
14
14
|
s.email = %q{gamsnjaga [a] gmail [d] com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -20,16 +20,16 @@ Gem::Specification.new do |s|
|
|
20
20
|
s.files = [
|
21
21
|
".gitignore",
|
22
22
|
"CHANGELOG",
|
23
|
+
"Gemfile",
|
23
24
|
"LICENSE",
|
24
25
|
"README.textile",
|
25
26
|
"Rakefile",
|
26
27
|
"TODO",
|
28
|
+
"VERSION",
|
27
29
|
"dm-accepts_nested_attributes.gemspec",
|
28
30
|
"lib/dm-accepts_nested_attributes.rb",
|
29
|
-
"lib/dm-accepts_nested_attributes/error_collecting.rb",
|
30
31
|
"lib/dm-accepts_nested_attributes/model.rb",
|
31
32
|
"lib/dm-accepts_nested_attributes/resource.rb",
|
32
|
-
"lib/dm-accepts_nested_attributes/transactional_save.rb",
|
33
33
|
"lib/dm-accepts_nested_attributes/version.rb",
|
34
34
|
"spec/accepts_nested_attributes_for_spec.rb",
|
35
35
|
"spec/many_to_many_spec.rb",
|
@@ -45,6 +45,7 @@ Gem::Specification.new do |s|
|
|
45
45
|
"spec/spec_helper.rb",
|
46
46
|
"tasks/changelog.rake",
|
47
47
|
"tasks/ci.rake",
|
48
|
+
"tasks/local_gemfile.rake",
|
48
49
|
"tasks/metrics.rake",
|
49
50
|
"tasks/spec.rake",
|
50
51
|
"tasks/yard.rake",
|
@@ -53,7 +54,7 @@ Gem::Specification.new do |s|
|
|
53
54
|
s.homepage = %q{http://github.com/snusnu/dm-accepts_nested_attributes}
|
54
55
|
s.rdoc_options = ["--charset=UTF-8"]
|
55
56
|
s.require_paths = ["lib"]
|
56
|
-
s.rubygems_version = %q{1.3.
|
57
|
+
s.rubygems_version = %q{1.3.7}
|
57
58
|
s.summary = %q{Nested model assignment for datamapper}
|
58
59
|
s.test_files = [
|
59
60
|
"spec/accepts_nested_attributes_for_spec.rb",
|
@@ -72,19 +73,19 @@ Gem::Specification.new do |s|
|
|
72
73
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
73
74
|
s.specification_version = 3
|
74
75
|
|
75
|
-
if Gem::Version.new(Gem::
|
76
|
-
s.add_runtime_dependency(%q<dm-core>, ["~> 0.
|
77
|
-
s.add_development_dependency(%q<rspec>, ["~> 1.
|
78
|
-
s.add_development_dependency(%q<yard>, ["~> 0.
|
76
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
77
|
+
s.add_runtime_dependency(%q<dm-core>, ["~> 1.0.0.rc1"])
|
78
|
+
s.add_development_dependency(%q<rspec>, ["~> 1.3"])
|
79
|
+
s.add_development_dependency(%q<yard>, ["~> 0.5"])
|
79
80
|
else
|
80
|
-
s.add_dependency(%q<dm-core>, ["~> 0.
|
81
|
-
s.add_dependency(%q<rspec>, ["~> 1.
|
82
|
-
s.add_dependency(%q<yard>, ["~> 0.
|
81
|
+
s.add_dependency(%q<dm-core>, ["~> 1.0.0.rc1"])
|
82
|
+
s.add_dependency(%q<rspec>, ["~> 1.3"])
|
83
|
+
s.add_dependency(%q<yard>, ["~> 0.5"])
|
83
84
|
end
|
84
85
|
else
|
85
|
-
s.add_dependency(%q<dm-core>, ["~> 0.
|
86
|
-
s.add_dependency(%q<rspec>, ["~> 1.
|
87
|
-
s.add_dependency(%q<yard>, ["~> 0.
|
86
|
+
s.add_dependency(%q<dm-core>, ["~> 1.0.0.rc1"])
|
87
|
+
s.add_dependency(%q<rspec>, ["~> 1.3"])
|
88
|
+
s.add_dependency(%q<yard>, ["~> 0.5"])
|
88
89
|
end
|
89
90
|
end
|
90
91
|
|
@@ -56,16 +56,6 @@ module DataMapper
|
|
56
56
|
|
57
57
|
include ::DataMapper::NestedAttributes::Resource
|
58
58
|
|
59
|
-
# TODO i wonder if this is the best place here?
|
60
|
-
# the transactional save behavior is definitely not needed for all resources,
|
61
|
-
# but it's necessary for resources that accept nested attributes
|
62
|
-
# FIXME this leads to weird "no such table" errors when specs are run
|
63
|
-
add_transactional_save_behavior # TODO if repository.adapter.supports_transactions?
|
64
|
-
|
65
|
-
# TODO make this do something
|
66
|
-
# it's only here now to remind me that this is probably the best place to put it
|
67
|
-
add_error_collection_behavior if DataMapper.const_defined?('Validate')
|
68
|
-
|
69
59
|
type = relationship.max > 1 ? :collection : :resource
|
70
60
|
|
71
61
|
define_method "#{association_name}_attributes" do
|
@@ -87,34 +77,6 @@ module DataMapper
|
|
87
77
|
|
88
78
|
private
|
89
79
|
|
90
|
-
##
|
91
|
-
# Provides a hook to include or disable customized transactional save behavior.
|
92
|
-
# Override this method to customize the implementation or disable it altogether.
|
93
|
-
# The current implementation in @see DataMapper::NestedAttributes::TransactionalSave
|
94
|
-
# simply wraps the saving of the complete object tree inside a transaction
|
95
|
-
# and rolls back in case any exceptions are raised, or any of the calls to
|
96
|
-
# @see DataMapper::Resource#save returned false
|
97
|
-
#
|
98
|
-
# @return Not specified
|
99
|
-
#
|
100
|
-
def add_transactional_save_behavior
|
101
|
-
require 'dm-accepts_nested_attributes/transactional_save'
|
102
|
-
include ::DataMapper::NestedAttributes::TransactionalSave
|
103
|
-
end
|
104
|
-
|
105
|
-
##
|
106
|
-
# Provides a hook to include or disable customized error collecting behavior.
|
107
|
-
# Overwrite this method to customize the implementation or disable it altogether.
|
108
|
-
# The current implementation in @see DataMapper::NestedAttributes::ValidationErrorCollecting
|
109
|
-
# simply attaches all errors of related resources to the object that was initially saved.
|
110
|
-
#
|
111
|
-
# @return Not specified
|
112
|
-
#
|
113
|
-
def add_error_collection_behavior
|
114
|
-
require 'dm-accepts_nested_attributes/error_collecting'
|
115
|
-
include ::DataMapper::NestedAttributes::ValidationErrorCollecting
|
116
|
-
end
|
117
|
-
|
118
80
|
##
|
119
81
|
# Checks options passed to @see accepts_nested_attributes_for
|
120
82
|
# If any of the given options is invalid, this method will raise
|
@@ -4,7 +4,7 @@ describe "DataMapper::Model.accepts_nested_attributes_for" do
|
|
4
4
|
|
5
5
|
FIXTURES = <<-RUBY
|
6
6
|
|
7
|
-
class Branch
|
7
|
+
class ::Branch
|
8
8
|
include DataMapper::Resource
|
9
9
|
property :id, Serial
|
10
10
|
has 1, :shop
|
@@ -12,20 +12,20 @@ describe "DataMapper::Model.accepts_nested_attributes_for" do
|
|
12
12
|
has n, :bookings, :through => :items
|
13
13
|
end
|
14
14
|
|
15
|
-
class Shop
|
15
|
+
class ::Shop
|
16
16
|
include DataMapper::Resource
|
17
17
|
property :id, Serial
|
18
18
|
belongs_to :branch
|
19
19
|
end
|
20
20
|
|
21
|
-
class Item
|
21
|
+
class ::Item
|
22
22
|
include DataMapper::Resource
|
23
23
|
property :id, Serial
|
24
24
|
belongs_to :branch
|
25
25
|
has n, :bookings
|
26
26
|
end
|
27
27
|
|
28
|
-
class Booking
|
28
|
+
class ::Booking
|
29
29
|
include DataMapper::Resource
|
30
30
|
property :id, Serial
|
31
31
|
belongs_to :item
|
data/spec/many_to_many_spec.rb
CHANGED
@@ -4,7 +4,7 @@ describe "Person.has(n, :projects, :through => :project_memberships);" do
|
|
4
4
|
|
5
5
|
before(:all) do
|
6
6
|
|
7
|
-
class Person
|
7
|
+
class ::Person
|
8
8
|
|
9
9
|
include DataMapper::Resource
|
10
10
|
extend ConstraintSupport
|
@@ -18,7 +18,7 @@ describe "Person.has(n, :projects, :through => :project_memberships);" do
|
|
18
18
|
|
19
19
|
end
|
20
20
|
|
21
|
-
class Project
|
21
|
+
class ::Project
|
22
22
|
|
23
23
|
include DataMapper::Resource
|
24
24
|
extend ConstraintSupport
|
@@ -32,7 +32,7 @@ describe "Person.has(n, :projects, :through => :project_memberships);" do
|
|
32
32
|
|
33
33
|
end
|
34
34
|
|
35
|
-
class ProjectMembership
|
35
|
+
class ::ProjectMembership
|
36
36
|
|
37
37
|
include DataMapper::Resource
|
38
38
|
|
@@ -43,7 +43,7 @@ describe "Person.has(n, :projects, :through => :project_memberships);" do
|
|
43
43
|
|
44
44
|
end
|
45
45
|
|
46
|
-
class Task
|
46
|
+
class ::Task
|
47
47
|
|
48
48
|
include DataMapper::Resource
|
49
49
|
|
@@ -54,7 +54,7 @@ describe "Person.has(n, :projects, :through => :project_memberships);" do
|
|
54
54
|
|
55
55
|
end
|
56
56
|
|
57
|
-
DataMapper.
|
57
|
+
DataMapper.auto_migrate!
|
58
58
|
|
59
59
|
end
|
60
60
|
|
data/spec/many_to_one_spec.rb
CHANGED
@@ -4,7 +4,7 @@ describe "Profile.belongs_to(:person);" do
|
|
4
4
|
|
5
5
|
before(:all) do
|
6
6
|
|
7
|
-
class Person
|
7
|
+
class ::Person
|
8
8
|
|
9
9
|
include DataMapper::Resource
|
10
10
|
extend ConstraintSupport
|
@@ -16,7 +16,7 @@ describe "Profile.belongs_to(:person);" do
|
|
16
16
|
|
17
17
|
end
|
18
18
|
|
19
|
-
class Profile
|
19
|
+
class ::Profile
|
20
20
|
|
21
21
|
include DataMapper::Resource
|
22
22
|
|
@@ -28,7 +28,7 @@ describe "Profile.belongs_to(:person);" do
|
|
28
28
|
|
29
29
|
end
|
30
30
|
|
31
|
-
DataMapper.
|
31
|
+
DataMapper.auto_migrate!
|
32
32
|
|
33
33
|
end
|
34
34
|
|
data/spec/one_to_many_spec.rb
CHANGED
@@ -4,7 +4,7 @@ describe "Project.has(n, :tasks);" do
|
|
4
4
|
|
5
5
|
before(:all) do
|
6
6
|
|
7
|
-
class Project
|
7
|
+
class ::Project
|
8
8
|
|
9
9
|
include DataMapper::Resource
|
10
10
|
extend ConstraintSupport
|
@@ -16,7 +16,7 @@ describe "Project.has(n, :tasks);" do
|
|
16
16
|
|
17
17
|
end
|
18
18
|
|
19
|
-
class Task
|
19
|
+
class ::Task
|
20
20
|
|
21
21
|
include DataMapper::Resource
|
22
22
|
|
@@ -27,7 +27,7 @@ describe "Project.has(n, :tasks);" do
|
|
27
27
|
|
28
28
|
end
|
29
29
|
|
30
|
-
DataMapper.
|
30
|
+
DataMapper.auto_migrate!
|
31
31
|
|
32
32
|
end
|
33
33
|
|
data/spec/one_to_one_spec.rb
CHANGED
@@ -4,7 +4,7 @@ describe "Person.has(1, :profile);" do
|
|
4
4
|
|
5
5
|
before(:all) do
|
6
6
|
|
7
|
-
class Person
|
7
|
+
class ::Person
|
8
8
|
|
9
9
|
include DataMapper::Resource
|
10
10
|
extend ConstraintSupport
|
@@ -17,7 +17,7 @@ describe "Person.has(1, :profile);" do
|
|
17
17
|
|
18
18
|
end
|
19
19
|
|
20
|
-
class Profile
|
20
|
+
class ::Profile
|
21
21
|
|
22
22
|
include DataMapper::Resource
|
23
23
|
|
@@ -29,7 +29,7 @@ describe "Person.has(1, :profile);" do
|
|
29
29
|
|
30
30
|
end
|
31
31
|
|
32
|
-
class Address
|
32
|
+
class ::Address
|
33
33
|
|
34
34
|
include DataMapper::Resource
|
35
35
|
|
@@ -41,7 +41,7 @@ describe "Person.has(1, :profile);" do
|
|
41
41
|
|
42
42
|
end
|
43
43
|
|
44
|
-
DataMapper.
|
44
|
+
DataMapper.auto_migrate!
|
45
45
|
|
46
46
|
end
|
47
47
|
|
@@ -1,26 +1,28 @@
|
|
1
1
|
describe "every accessible many_to_many association", :shared => true do
|
2
2
|
|
3
3
|
it "should allow to update an existing project via Person#projects_attributes" do
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
pending_if "#{DataMapper::Spec.adapter_name} doesn't support M2M", !HAS_M2M_SUPPORT do
|
5
|
+
Person.all.size.should == 0
|
6
|
+
Project.all.size.should == 0
|
7
|
+
ProjectMembership.all.size.should == 0
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
9
|
+
person = Person.create :name => 'snusnu'
|
10
|
+
project = Project.create(:name => 'dm-accepts_nested_attributes')
|
11
|
+
project_membership = ProjectMembership.create(:person => person, :project => project)
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
13
|
+
Person.all.size.should == 1
|
14
|
+
Project.all.size.should == 1
|
15
|
+
ProjectMembership.all.size.should == 1
|
15
16
|
|
16
|
-
|
17
|
-
|
17
|
+
person.projects_attributes = [{ :id => project.id, :name => 'still dm-accepts_nested_attributes' }]
|
18
|
+
person.save
|
18
19
|
|
19
|
-
|
20
|
-
|
21
|
-
|
20
|
+
Person.all.size.should == 1
|
21
|
+
ProjectMembership.all.size.should == 1
|
22
|
+
Project.all.size.should == 1
|
22
23
|
|
23
|
-
|
24
|
+
Project.first.name.should == 'still dm-accepts_nested_attributes'
|
25
|
+
end
|
24
26
|
end
|
25
27
|
|
26
28
|
it "should return the attributes written to Person#projects_attributes from the Person#projects_attributes reader" do
|
@@ -83,26 +85,6 @@ describe "every accessible many_to_many association with no reject_if proc", :sh
|
|
83
85
|
Project.first.name.should == 'dm-accepts_nested_attributes'
|
84
86
|
end
|
85
87
|
|
86
|
-
it "should perform atomic commits" do
|
87
|
-
|
88
|
-
person = Person.new :name => 'snusnu'
|
89
|
-
person.projects_attributes = [{ :name => nil }] # should fail because of validations
|
90
|
-
person.save
|
91
|
-
|
92
|
-
Person.all.size.should == 0 # TODO think more if this should be '1'
|
93
|
-
ProjectMembership.all.size.should == 0
|
94
|
-
Project.all.size.should == 0
|
95
|
-
|
96
|
-
person.name = nil # should fail because of validations
|
97
|
-
person.projects_attributes = [{ :name => nil }]
|
98
|
-
person.save
|
99
|
-
|
100
|
-
Person.all.size.should == 0
|
101
|
-
ProjectMembership.all.size.should == 0
|
102
|
-
Project.all.size.should == 0
|
103
|
-
|
104
|
-
end
|
105
|
-
|
106
88
|
end
|
107
89
|
|
108
90
|
describe "every accessible many_to_many association with :allow_destroy => false", :shared => true do
|
@@ -135,28 +117,30 @@ end
|
|
135
117
|
describe "every accessible many_to_many association with :allow_destroy => true", :shared => true do
|
136
118
|
|
137
119
|
it "should allow to delete an existing project via Person#projects_attributes" do
|
138
|
-
|
120
|
+
pending_if "#{DataMapper::Spec.adapter_name} doesn't support M2M", !HAS_M2M_SUPPORT do
|
121
|
+
person = Person.create :name => 'snusnu'
|
139
122
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
123
|
+
project_1 = Project.create(:name => 'dm-accepts_nested_attributes')
|
124
|
+
project_2 = Project.create(:name => 'dm-is-localizable')
|
125
|
+
project_membership_1 = ProjectMembership.create(:person => person, :project => project_1)
|
126
|
+
project_membership_2 = ProjectMembership.create(:person => person, :project => project_2)
|
144
127
|
|
145
|
-
|
146
|
-
|
147
|
-
|
128
|
+
Person.all.size.should == 1
|
129
|
+
ProjectMembership.all.size.should == 2
|
130
|
+
Project.all.size.should == 2
|
148
131
|
|
149
|
-
|
132
|
+
person.projects_attributes = [{ :id => project_1.id, :_delete => true }]
|
150
133
|
|
151
|
-
|
152
|
-
|
153
|
-
|
134
|
+
Person.all.size.should == 1
|
135
|
+
ProjectMembership.all.size.should == 2
|
136
|
+
Project.all.size.should == 2
|
154
137
|
|
155
|
-
|
138
|
+
person.save
|
156
139
|
|
157
|
-
|
158
|
-
|
159
|
-
|
140
|
+
Person.all.size.should == 1
|
141
|
+
ProjectMembership.all.size.should == 1
|
142
|
+
Project.all.size.should == 1
|
143
|
+
end
|
160
144
|
end
|
161
145
|
|
162
146
|
end
|
@@ -21,27 +21,6 @@ describe "every accessible many_to_one association", :shared => true do
|
|
21
21
|
Person.first.name.should == 'Martin Gamsjaeger'
|
22
22
|
end
|
23
23
|
|
24
|
-
it "should perform atomic commits" do
|
25
|
-
Profile.all.size.should == 0
|
26
|
-
Person.all.size.should == 0
|
27
|
-
|
28
|
-
# related resource is invalid
|
29
|
-
profile = Profile.new :nick => 'snusnu'
|
30
|
-
profile.person_attributes = { :name => nil }
|
31
|
-
profile.save.should be_false
|
32
|
-
|
33
|
-
Profile.all.size.should == 0
|
34
|
-
Person.all.size.should == 0
|
35
|
-
|
36
|
-
# self is invalid
|
37
|
-
profile.nick = nil
|
38
|
-
profile.person_attributes = { :name => 'Martin' }
|
39
|
-
profile.save.should be_false
|
40
|
-
|
41
|
-
Profile.all.size.should == 0
|
42
|
-
Person.all.size.should == 0
|
43
|
-
end
|
44
|
-
|
45
24
|
it "should return the attributes written to Profile#person_attributes from the Profile#person_attributes reader" do
|
46
25
|
profile = Profile.new :nick => 'snusnu'
|
47
26
|
profile.person_attributes.should be_nil
|
@@ -63,10 +42,11 @@ describe "every accessible many_to_one association with a valid reject_if proc",
|
|
63
42
|
Profile.all.size.should == 0
|
64
43
|
Person.all.size.should == 0
|
65
44
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
45
|
+
begin
|
46
|
+
profile.save.should be(false)
|
47
|
+
rescue
|
48
|
+
# swallow native FK errors which is basically like expecting save to be false
|
49
|
+
end
|
70
50
|
end
|
71
51
|
|
72
52
|
end
|
@@ -61,27 +61,6 @@ describe "every accessible one_to_many association with no reject_if proc", :sha
|
|
61
61
|
Task.first.name.should == 'write specs'
|
62
62
|
end
|
63
63
|
|
64
|
-
it "should perform atomic commits" do
|
65
|
-
Project.all.size.should == 0
|
66
|
-
Task.all.size.should == 0
|
67
|
-
|
68
|
-
# self is invalid
|
69
|
-
project = Project.new :name => nil
|
70
|
-
project.tasks_attributes = [{ :name => 'write specs' }]
|
71
|
-
project.save.should be_false
|
72
|
-
|
73
|
-
Project.all.size.should == 0
|
74
|
-
Task.all.size.should == 0
|
75
|
-
|
76
|
-
# related resource is invalid
|
77
|
-
project.name = 'dm-accepts_nested_attributes'
|
78
|
-
project.tasks_attributes = [{ :name => nil }] # will fail because of validations
|
79
|
-
project.save
|
80
|
-
|
81
|
-
Project.all.size.should == 0
|
82
|
-
Task.all.size.should == 0
|
83
|
-
end
|
84
|
-
|
85
64
|
end
|
86
65
|
|
87
66
|
describe "every accessible one_to_many association with :allow_destroy => false", :shared => true do
|
@@ -60,25 +60,6 @@ describe "every accessible one_to_one association with no reject_if proc", :shar
|
|
60
60
|
Profile.first.nick.should == 'snusnu'
|
61
61
|
end
|
62
62
|
|
63
|
-
it "should perform atomic commits" do
|
64
|
-
|
65
|
-
# related resource is invalid
|
66
|
-
person = Person.new :name => 'Martin'
|
67
|
-
person.profile_attributes = { :nick => nil } # will fail because of validations
|
68
|
-
person.save.should be_false
|
69
|
-
|
70
|
-
Person.all.size.should == 0
|
71
|
-
Profile.all.size.should == 0
|
72
|
-
|
73
|
-
# self is invalid
|
74
|
-
person.name = nil # will fail because of validations
|
75
|
-
person.profile_attributes = { :nick => 'snusnu' }
|
76
|
-
person.save.should be_false
|
77
|
-
|
78
|
-
Person.all.size.should == 0
|
79
|
-
Profile.all.size.should == 0
|
80
|
-
end
|
81
|
-
|
82
63
|
end
|
83
64
|
|
84
65
|
describe "every accessible one_to_one association with :allow_destroy => false", :shared => true do
|
data/spec/spec_helper.rb
CHANGED
@@ -1,44 +1,16 @@
|
|
1
|
-
require '
|
2
|
-
require '
|
3
|
-
require 'spec'
|
1
|
+
require 'dm-core/spec/setup'
|
2
|
+
require 'dm-core/spec/lib/pending_helpers'
|
4
3
|
|
5
|
-
# require the plugin
|
6
4
|
require 'dm-accepts_nested_attributes'
|
7
5
|
|
8
|
-
# allow testing with dm-validations enabled
|
9
|
-
# must be required after the plugin, since
|
10
|
-
# dm-validations seems to need dm-core
|
11
|
-
require 'dm-validations'
|
12
|
-
require 'dm-constraints'
|
13
|
-
|
14
|
-
ENV["SQLITE3_SPEC_URI"] ||= 'sqlite3::memory:'
|
15
|
-
ENV["MYSQL_SPEC_URI"] ||= 'mysql://localhost/dm-accepts_nested_attributes_test'
|
16
|
-
ENV["POSTGRES_SPEC_URI"] ||= 'postgres://postgres@localhost/dm-accepts_nested_attributes_test'
|
17
|
-
|
18
|
-
|
19
|
-
def setup_adapter(name, default_uri = nil)
|
20
|
-
begin
|
21
|
-
DataMapper.setup(name, ENV["#{ENV['ADAPTER'].to_s.upcase}_SPEC_URI"] || default_uri)
|
22
|
-
Object.const_set('ADAPTER', ENV['ADAPTER'].to_sym) if name.to_s == ENV['ADAPTER']
|
23
|
-
true
|
24
|
-
rescue Exception => e
|
25
|
-
if name.to_s == ENV['ADAPTER']
|
26
|
-
Object.const_set('ADAPTER', nil)
|
27
|
-
warn "Could not load do_#{name}: #{e}"
|
28
|
-
end
|
29
|
-
false
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
ENV['ADAPTER'] ||= 'mysql'
|
34
|
-
setup_adapter(:default)
|
35
|
-
|
36
|
-
|
37
6
|
require 'shared/many_to_many_spec'
|
38
7
|
require 'shared/many_to_one_spec'
|
39
8
|
require 'shared/one_to_many_spec'
|
40
9
|
require 'shared/one_to_one_spec'
|
41
10
|
|
11
|
+
DataMapper::Spec.setup
|
12
|
+
|
13
|
+
HAS_M2M_SUPPORT = !%w[in_memory yaml].include?(DataMapper::Spec.adapter_name)
|
42
14
|
|
43
15
|
module ConstraintSupport
|
44
16
|
|
@@ -51,3 +23,15 @@ module ConstraintSupport
|
|
51
23
|
end
|
52
24
|
|
53
25
|
end
|
26
|
+
|
27
|
+
Spec::Runner.configure do |config|
|
28
|
+
|
29
|
+
config.include(DataMapper::Spec::PendingHelpers)
|
30
|
+
|
31
|
+
config.after(:suite) do
|
32
|
+
if DataMapper.respond_to?(:auto_migrate_down!, true)
|
33
|
+
DataMapper.send(:auto_migrate_down!, DataMapper::Spec.adapter.name)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
desc "Support bundling from local source code (allows BUNDLE_GEMFILE=Gemfile.local bundle foo)"
|
2
|
+
task :local_gemfile do |t|
|
3
|
+
|
4
|
+
root = Pathname(__FILE__).dirname.parent
|
5
|
+
datamapper = root.parent
|
6
|
+
|
7
|
+
source_regex = /DATAMAPPER = 'git:\/\/github.com\/datamapper'/
|
8
|
+
gem_source_regex = /:git => \"#\{DATAMAPPER\}\/(.+?)(?:\.git)?\"/
|
9
|
+
|
10
|
+
root.join('Gemfile.local').open('w') do |f|
|
11
|
+
root.join('Gemfile').open.each do |line|
|
12
|
+
line.sub!(source_regex, "DATAMAPPER = '#{datamapper}'")
|
13
|
+
line.sub!(gem_source_regex, ':path => "#{DATAMAPPER}/\1"')
|
14
|
+
f.puts line
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
data/tasks/spec.rake
CHANGED
metadata
CHANGED
@@ -1,47 +1,71 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dm-accepts_nested_attributes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 144173629
|
5
|
+
prerelease: true
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 0
|
10
|
+
- rc1
|
11
|
+
version: 1.0.0.rc1
|
5
12
|
platform: ruby
|
6
13
|
authors:
|
7
|
-
- Martin Gamsjaeger
|
14
|
+
- Martin Gamsjaeger (snusnu)
|
8
15
|
autorequire:
|
9
16
|
bindir: bin
|
10
17
|
cert_chain: []
|
11
18
|
|
12
|
-
date: 2010-
|
19
|
+
date: 2010-05-20 00:00:00 +02:00
|
13
20
|
default_executable:
|
14
21
|
dependencies:
|
15
22
|
- !ruby/object:Gem::Dependency
|
16
23
|
name: dm-core
|
17
|
-
|
18
|
-
|
19
|
-
|
24
|
+
prerelease: false
|
25
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
20
27
|
requirements:
|
21
28
|
- - ~>
|
22
29
|
- !ruby/object:Gem::Version
|
23
|
-
|
24
|
-
|
30
|
+
hash: 144173629
|
31
|
+
segments:
|
32
|
+
- 1
|
33
|
+
- 0
|
34
|
+
- 0
|
35
|
+
- rc1
|
36
|
+
version: 1.0.0.rc1
|
37
|
+
type: :runtime
|
38
|
+
version_requirements: *id001
|
25
39
|
- !ruby/object:Gem::Dependency
|
26
40
|
name: rspec
|
27
|
-
|
28
|
-
|
29
|
-
|
41
|
+
prerelease: false
|
42
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
30
44
|
requirements:
|
31
45
|
- - ~>
|
32
46
|
- !ruby/object:Gem::Version
|
33
|
-
|
34
|
-
|
47
|
+
hash: 9
|
48
|
+
segments:
|
49
|
+
- 1
|
50
|
+
- 3
|
51
|
+
version: "1.3"
|
52
|
+
type: :development
|
53
|
+
version_requirements: *id002
|
35
54
|
- !ruby/object:Gem::Dependency
|
36
55
|
name: yard
|
37
|
-
|
38
|
-
|
39
|
-
|
56
|
+
prerelease: false
|
57
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
40
59
|
requirements:
|
41
60
|
- - ~>
|
42
61
|
- !ruby/object:Gem::Version
|
43
|
-
|
44
|
-
|
62
|
+
hash: 1
|
63
|
+
segments:
|
64
|
+
- 0
|
65
|
+
- 5
|
66
|
+
version: "0.5"
|
67
|
+
type: :development
|
68
|
+
version_requirements: *id003
|
45
69
|
description: A datamapper plugin that allows nested model assignment like activerecord.
|
46
70
|
email: gamsnjaga [a] gmail [d] com
|
47
71
|
executables: []
|
@@ -55,16 +79,16 @@ extra_rdoc_files:
|
|
55
79
|
files:
|
56
80
|
- .gitignore
|
57
81
|
- CHANGELOG
|
82
|
+
- Gemfile
|
58
83
|
- LICENSE
|
59
84
|
- README.textile
|
60
85
|
- Rakefile
|
61
86
|
- TODO
|
87
|
+
- VERSION
|
62
88
|
- dm-accepts_nested_attributes.gemspec
|
63
89
|
- lib/dm-accepts_nested_attributes.rb
|
64
|
-
- lib/dm-accepts_nested_attributes/error_collecting.rb
|
65
90
|
- lib/dm-accepts_nested_attributes/model.rb
|
66
91
|
- lib/dm-accepts_nested_attributes/resource.rb
|
67
|
-
- lib/dm-accepts_nested_attributes/transactional_save.rb
|
68
92
|
- lib/dm-accepts_nested_attributes/version.rb
|
69
93
|
- spec/accepts_nested_attributes_for_spec.rb
|
70
94
|
- spec/many_to_many_spec.rb
|
@@ -80,6 +104,7 @@ files:
|
|
80
104
|
- spec/spec_helper.rb
|
81
105
|
- tasks/changelog.rake
|
82
106
|
- tasks/ci.rake
|
107
|
+
- tasks/local_gemfile.rake
|
83
108
|
- tasks/metrics.rake
|
84
109
|
- tasks/spec.rake
|
85
110
|
- tasks/yard.rake
|
@@ -94,21 +119,29 @@ rdoc_options:
|
|
94
119
|
require_paths:
|
95
120
|
- lib
|
96
121
|
required_ruby_version: !ruby/object:Gem::Requirement
|
122
|
+
none: false
|
97
123
|
requirements:
|
98
124
|
- - ">="
|
99
125
|
- !ruby/object:Gem::Version
|
126
|
+
hash: 3
|
127
|
+
segments:
|
128
|
+
- 0
|
100
129
|
version: "0"
|
101
|
-
version:
|
102
130
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
131
|
+
none: false
|
103
132
|
requirements:
|
104
|
-
- - "
|
133
|
+
- - ">"
|
105
134
|
- !ruby/object:Gem::Version
|
106
|
-
|
107
|
-
|
135
|
+
hash: 25
|
136
|
+
segments:
|
137
|
+
- 1
|
138
|
+
- 3
|
139
|
+
- 1
|
140
|
+
version: 1.3.1
|
108
141
|
requirements: []
|
109
142
|
|
110
143
|
rubyforge_project:
|
111
|
-
rubygems_version: 1.3.
|
144
|
+
rubygems_version: 1.3.7
|
112
145
|
signing_key:
|
113
146
|
specification_version: 3
|
114
147
|
summary: Nested model assignment for datamapper
|
@@ -1,35 +0,0 @@
|
|
1
|
-
module DataMapper
|
2
|
-
module NestedAttributes
|
3
|
-
|
4
|
-
module ValidationErrorCollecting
|
5
|
-
|
6
|
-
# collect errors on parent associations
|
7
|
-
def before_save_parent_association(association, context)
|
8
|
-
if association.respond_to?(:each)
|
9
|
-
association.each do |r|
|
10
|
-
unless r.valid?(context)
|
11
|
-
r.errors.each { |e| self.errors.add(:general, e) }
|
12
|
-
end
|
13
|
-
end
|
14
|
-
else
|
15
|
-
unless association.valid?(context)
|
16
|
-
association.errors.each { |e| self.errors.add(:general, e) }
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
# collect errors on child associations
|
22
|
-
def before_save_child_association(association, context)
|
23
|
-
if association.respond_to?(:valid?)
|
24
|
-
unless association.valid?(context)
|
25
|
-
association.errors.each { |e| self.errors.add(:general, e) }
|
26
|
-
end
|
27
|
-
else
|
28
|
-
self.errors.add(:general, "child association is missing")
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
end
|
33
|
-
|
34
|
-
end
|
35
|
-
end
|
@@ -1,24 +0,0 @@
|
|
1
|
-
module DataMapper
|
2
|
-
module NestedAttributes
|
3
|
-
|
4
|
-
module TransactionalSave
|
5
|
-
|
6
|
-
##
|
7
|
-
# Overrides @see DataMapper::Resource#save to perform inside a transaction.
|
8
|
-
# The current implementation simply wraps the saving of the complete object tree
|
9
|
-
# inside a transaction and rolls back in case any exceptions are raised,
|
10
|
-
# or any of the calls to
|
11
|
-
#
|
12
|
-
# @see DataMapper::Resource#save
|
13
|
-
#
|
14
|
-
# @return [Boolean]
|
15
|
-
# true if all related resources were saved properly
|
16
|
-
#
|
17
|
-
def save
|
18
|
-
transaction { |t| super || t.rollback && false }
|
19
|
-
end
|
20
|
-
|
21
|
-
end
|
22
|
-
|
23
|
-
end
|
24
|
-
end
|