acts_as_nested_by 0.1.1 → 0.1.2
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/LICENSE +17 -16
- data/README.rdoc +27 -13
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/acts_as_nested_by.gemspec +6 -5
- data/init.rb +1 -0
- data/lib/acts_as_nested_by.rb +17 -6
- data/test/helper.rb +1 -1
- metadata +6 -10
data/LICENSE
CHANGED
@@ -1,20 +1,21 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
1
3
|
Copyright (c) 2009 Thomas Limp
|
2
4
|
|
3
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
the following conditions:
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
10
11
|
|
11
|
-
The above copyright notice and this permission notice shall be
|
12
|
-
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
13
14
|
|
14
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
OF
|
20
|
-
|
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,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.rdoc
CHANGED
@@ -1,41 +1,55 @@
|
|
1
|
-
=
|
1
|
+
= ActsAsNestedBy
|
2
2
|
|
3
|
-
|
3
|
+
'acts_as_nested_by' is/will be a simple counterpart for ActiveRecord::NestedAttributes 'accepts_attribute_for'.
|
4
|
+
|
5
|
+
== Installation
|
6
|
+
|
7
|
+
* as gem
|
8
|
+
$ sudo gem install acts_as_nested_by
|
9
|
+
* or as plugin in your rails app
|
10
|
+
$ ./script/plugin/install git://github.com/tehael/acts_as_nested_by.git # rails 2.3.x
|
11
|
+
$ rails plugin install git://github.com/tehael/acts_as_nested_by.git # rails 3.0.x
|
4
12
|
|
5
13
|
== Use case example
|
6
|
-
Since the rails-way of handling referential integrity is to code the logic into you your model, without using database dependent foreign key constraints, you might come across situations like this.
|
7
14
|
|
8
|
-
|
15
|
+
Since the rails-way of handling referential integrity is to code the logic into you model without using database level foreign key constraints, you might produce code like this.
|
16
|
+
|
17
|
+
class Foo < ActiveRecord::Base
|
9
18
|
has_many :bars
|
10
19
|
validates_associated :bars
|
11
20
|
accepts_nested_attributes_for :bars
|
12
21
|
end
|
13
22
|
|
14
|
-
class Bar < ActiveRecord
|
23
|
+
class Bar < ActiveRecord::Base
|
15
24
|
belongs_to :foo
|
16
25
|
validates_presence_of :foo
|
17
26
|
end
|
18
27
|
|
19
|
-
Using validates_presence_of :foo instead of :foo_id ensures that not only a :foo_id was given but a Foo object existst in the :foos table.
|
28
|
+
Using 'validates_presence_of :foo' instead of 'validates_presence_of :foo_id' ensures that not only a ':foo_id' was given but a Foo object existst in the :foos table.
|
20
29
|
|
21
|
-
But on creation of a Foo with nested Bars in
|
22
|
-
Using an :unless => :new_record?
|
30
|
+
But on creation of a Foo with nested Bars in one step produces a dead look, since the ':foo_id' for the Bars is not available until the Foo is saved, and the 'validates_presence_of :foo' therefore produces an error in the Bars invalidating them, no ':foo_id' no 'Foo' in the ':foos' table. And because the 'Foo' ':validates_associated :bars' it cannot be saved.
|
31
|
+
Using an ':unless => :new_record?' condition with the ':validates_presence_of :foo' might help, but the validation is also skipped, if a 'Bar' is not created in a nested way.
|
23
32
|
|
24
|
-
To handle this acts_as_nested_by comes in handy.
|
25
|
-
|
33
|
+
To handle this 'acts_as_nested_by' comes in handy.
|
34
|
+
|
35
|
+
class Bar < ActiveRecord::Base
|
26
36
|
belongs_to :foo
|
27
37
|
acts_as_nested_by :foo
|
28
38
|
validates_presence_of :foo, :unless => :nested_by_foo?
|
29
39
|
end
|
30
40
|
|
31
|
-
|
41
|
+
For now just pass a parameter (with a hidden form parameter) ':nested_by_foo => true' when creating 'Bars' nested in a 'Foo'. If the 'Foo' itsef is 'valid?' it can be saved, the nested 'Bars' will be auto saved and consistency is assured. ;)
|
32
42
|
|
33
43
|
== Nota bene
|
34
|
-
|
44
|
+
|
45
|
+
* The association must be established before 'calling acts_as_nested_by :foo', so it must be called after 'belongs_to :foo'. An ArgumentError will be raised if the association is not yet established.
|
46
|
+
* By now the association must be defined by 'belongs_to' macro, otherwise an ArgumentError will be raised.
|
47
|
+
* When using ':attr_accessible', ':attr_proteced' and a hidden form parameter you should add ':nested_by_foo' to the mass-assignable attributes.
|
35
48
|
|
36
49
|
== Next steps/known issues
|
37
50
|
|
38
|
-
|
51
|
+
* Setting of ':nested_by_other' via mass assignement or by calling 'nested_by_other = true' could be exploited to create inconsistent entries.
|
52
|
+
* Therefore the mass assignment setter method provided by 'ActiveRecord#accepts_nested_attributes_for' should set the ':nested_by_other' flag internaly and 'ActiveRecord::Base#nested_by_other' should be defined protected.
|
39
53
|
|
40
54
|
== Note on Patches/Pull Requests
|
41
55
|
|
data/Rakefile
CHANGED
@@ -12,7 +12,7 @@ begin
|
|
12
12
|
nested_by_nesting_model returns true if nested_by nesting_model
|
13
13
|
nested_by_nesting_model? alias for nested_by_nesting_model
|
14
14
|
}
|
15
|
-
gem.email = "thomas.limp@
|
15
|
+
gem.email = "thomas.limp@gmx.com"
|
16
16
|
gem.homepage = "http://github.com/tehael/acts_as_nested_by"
|
17
17
|
gem.authors = ["Thomas Limp"]
|
18
18
|
gem.add_development_dependency "shoulda", ">= 0"
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.2
|
data/acts_as_nested_by.gemspec
CHANGED
@@ -5,18 +5,18 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{acts_as_nested_by}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.2"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Thomas Limp"]
|
12
|
-
s.date = %q{2010-05-
|
12
|
+
s.date = %q{2010-05-06}
|
13
13
|
s.description = %q{
|
14
14
|
The acts_as_nested_by class method add 3 instance methods to the model.
|
15
15
|
nested_by_nesting_model=(flag) sets the nesting_model
|
16
16
|
nested_by_nesting_model returns true if nested_by nesting_model
|
17
17
|
nested_by_nesting_model? alias for nested_by_nesting_model
|
18
18
|
}
|
19
|
-
s.email = %q{thomas.limp@
|
19
|
+
s.email = %q{thomas.limp@gmx.com}
|
20
20
|
s.extra_rdoc_files = [
|
21
21
|
"LICENSE",
|
22
22
|
"README.rdoc"
|
@@ -29,6 +29,7 @@ Gem::Specification.new do |s|
|
|
29
29
|
"Rakefile",
|
30
30
|
"VERSION",
|
31
31
|
"acts_as_nested_by.gemspec",
|
32
|
+
"init.rb",
|
32
33
|
"lib/acts_as_nested_by.rb",
|
33
34
|
"test/helper.rb",
|
34
35
|
"test/test_acts_as_nested_by.rb"
|
@@ -36,7 +37,7 @@ Gem::Specification.new do |s|
|
|
36
37
|
s.homepage = %q{http://github.com/tehael/acts_as_nested_by}
|
37
38
|
s.rdoc_options = ["--charset=UTF-8"]
|
38
39
|
s.require_paths = ["lib"]
|
39
|
-
s.rubygems_version = %q{1.3.6
|
40
|
+
s.rubygems_version = %q{1.3.6}
|
40
41
|
s.summary = %q{Add a acts_as_nested_by :nesting_model class method to ActiveRecord::Base models}
|
41
42
|
s.test_files = [
|
42
43
|
"test/helper.rb",
|
@@ -47,7 +48,7 @@ Gem::Specification.new do |s|
|
|
47
48
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
48
49
|
s.specification_version = 3
|
49
50
|
|
50
|
-
if Gem::Version.new(Gem::
|
51
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
51
52
|
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
52
53
|
s.add_development_dependency(%q<sqlite3-ruby>, [">= 0"])
|
53
54
|
s.add_runtime_dependency(%q<activerecord>, [">= 0"])
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "acts_as_nested_by"
|
data/lib/acts_as_nested_by.rb
CHANGED
@@ -1,17 +1,28 @@
|
|
1
|
-
module ActsAsNestedBy#:nodoc
|
2
|
-
def self.included(base)
|
1
|
+
module ActsAsNestedBy #:nodoc:
|
2
|
+
def self.included(base) #:nodoc:
|
3
3
|
base.send :extend, ClassMethods
|
4
4
|
end
|
5
5
|
|
6
|
-
module ClassMethods
|
7
|
-
# Generates instance methods for setting and
|
8
|
-
#
|
6
|
+
module ClassMethods
|
7
|
+
# Generates instance methods for setting and getting a 'nested_by_other' flag for each ':other' in association_names
|
8
|
+
# * Example:
|
9
|
+
# Bar < ActiveRecord::Base
|
10
|
+
# belongs_to :other
|
11
|
+
# acts_as_nested_by :other
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# generates methods
|
15
|
+
# Bar#nested_by_other=
|
16
|
+
# Bar#nested_by_other
|
17
|
+
# Bar#nested_by_other?
|
18
|
+
# * Exceptions raised
|
19
|
+
# * ArgumentError if one of the associations does not exist
|
20
|
+
# * ArgumentError if one of the associations is not created by the :belongs_to macro
|
9
21
|
def acts_as_nested_by(*association_names)
|
10
22
|
association_names.each do |association_name|
|
11
23
|
if reflection = reflect_on_association(association_name)
|
12
24
|
if :belongs_to == reflection.macro
|
13
25
|
class_eval %{
|
14
|
-
|
15
26
|
def nested_by_#{association_name}=(nested_by_#{association_name})
|
16
27
|
@nested_by_#{association_name} = nested_by_#{association_name}
|
17
28
|
end
|
data/test/helper.rb
CHANGED
@@ -14,7 +14,7 @@ class Test::Unit::TestCase
|
|
14
14
|
def self.db_setup
|
15
15
|
@dbfile = File.join(File.dirname(__FILE__),"test.sqlite3")
|
16
16
|
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => @dbfile)
|
17
|
-
ActiveRecord::Migration.create_table :foos
|
17
|
+
ActiveRecord::Migration.create_table :foos do end
|
18
18
|
ActiveRecord::Migration.create_table :bars do |t| t.references :foo end
|
19
19
|
end
|
20
20
|
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
version: 0.1.
|
8
|
+
- 2
|
9
|
+
version: 0.1.2
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Thomas Limp
|
@@ -14,14 +14,13 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-05-
|
17
|
+
date: 2010-05-06 00:00:00 +02:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: shoulda
|
22
22
|
prerelease: false
|
23
23
|
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
-
none: false
|
25
24
|
requirements:
|
26
25
|
- - ">="
|
27
26
|
- !ruby/object:Gem::Version
|
@@ -34,7 +33,6 @@ dependencies:
|
|
34
33
|
name: sqlite3-ruby
|
35
34
|
prerelease: false
|
36
35
|
requirement: &id002 !ruby/object:Gem::Requirement
|
37
|
-
none: false
|
38
36
|
requirements:
|
39
37
|
- - ">="
|
40
38
|
- !ruby/object:Gem::Version
|
@@ -47,7 +45,6 @@ dependencies:
|
|
47
45
|
name: activerecord
|
48
46
|
prerelease: false
|
49
47
|
requirement: &id003 !ruby/object:Gem::Requirement
|
50
|
-
none: false
|
51
48
|
requirements:
|
52
49
|
- - ">="
|
53
50
|
- !ruby/object:Gem::Version
|
@@ -57,7 +54,7 @@ dependencies:
|
|
57
54
|
type: :runtime
|
58
55
|
version_requirements: *id003
|
59
56
|
description: "\n The acts_as_nested_by class method add 3 instance methods to the model.\n nested_by_nesting_model=(flag) sets the nesting_model \n nested_by_nesting_model returns true if nested_by nesting_model\n nested_by_nesting_model? alias for nested_by_nesting_model\n "
|
60
|
-
email: thomas.limp@
|
57
|
+
email: thomas.limp@gmx.com
|
61
58
|
executables: []
|
62
59
|
|
63
60
|
extensions: []
|
@@ -73,6 +70,7 @@ files:
|
|
73
70
|
- Rakefile
|
74
71
|
- VERSION
|
75
72
|
- acts_as_nested_by.gemspec
|
73
|
+
- init.rb
|
76
74
|
- lib/acts_as_nested_by.rb
|
77
75
|
- test/helper.rb
|
78
76
|
- test/test_acts_as_nested_by.rb
|
@@ -86,7 +84,6 @@ rdoc_options:
|
|
86
84
|
require_paths:
|
87
85
|
- lib
|
88
86
|
required_ruby_version: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
87
|
requirements:
|
91
88
|
- - ">="
|
92
89
|
- !ruby/object:Gem::Version
|
@@ -94,7 +91,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
94
91
|
- 0
|
95
92
|
version: "0"
|
96
93
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
94
|
requirements:
|
99
95
|
- - ">="
|
100
96
|
- !ruby/object:Gem::Version
|
@@ -104,7 +100,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
104
100
|
requirements: []
|
105
101
|
|
106
102
|
rubyforge_project:
|
107
|
-
rubygems_version: 1.3.6
|
103
|
+
rubygems_version: 1.3.6
|
108
104
|
signing_key:
|
109
105
|
specification_version: 3
|
110
106
|
summary: Add a acts_as_nested_by :nesting_model class method to ActiveRecord::Base models
|