acts_as_nested_by 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|