acts_as_nested_by 0.1.1

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/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Thomas Limp
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.rdoc ADDED
@@ -0,0 +1,52 @@
1
+ = acts_as_nested_by
2
+
3
+ "acts_as_nested_by" is/will be a simple counterpart for rails' "accepts_attribute_for".
4
+
5
+ == 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
+
8
+ class Foo < ActiveRecord
9
+ has_many :bars
10
+ validates_associated :bars
11
+ accepts_nested_attributes_for :bars
12
+ end
13
+
14
+ class Bar < ActiveRecord
15
+ belongs_to :foo
16
+ validates_presence_of :foo
17
+ end
18
+
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.
20
+
21
+ But on creation of a Foo with nested Bars in on step produces a kind of dead look, since the :foo_id for the Bars is not available until the Foo ist saved, and the validates_presence_of :bars produces an error in the Bars, no :foo_id, no Foo in the :foos table. And because the Foo :validates_associated :bars it cannot be saved.
22
+ Using an :unless => :new_record? conditions with the validations might help, but it can but those valdation would also be skipped, if the Bars were not to be created in a nested form.
23
+
24
+ To handle this acts_as_nested_by comes in handy.
25
+ class Bar < ActiveRecord
26
+ belongs_to :foo
27
+ acts_as_nested_by :foo
28
+ validates_presence_of :foo, :unless => :nested_by_foo?
29
+ end
30
+
31
+ Now just pass a parameter (with a hidden form parameter, or in the controller) :nested_by_foo => true when creating Bars nested in a Foo. If the Foo ist valid? it can be saved and the nested Bars will be auto saved and consistency is assured. ;)
32
+
33
+ == Nota bene
34
+ When using :attr_accessible, :attr_proteced and a hidden form parameter you should add :nested_by_foo to the mass-assignable attributes.
35
+
36
+ == Next steps/known issues
37
+
38
+ Since the setting of :nested_by_foo via mass assignement could be exploited to create inconsitent entries, the build/create methods provide by the association macros should set the :nested_by_foo internaly and the generated ActiveRecord::Base#nested_by_foo should be defined protected.
39
+
40
+ == Note on Patches/Pull Requests
41
+
42
+ * Fork the project.
43
+ * Make your feature addition or bug fix.
44
+ * Add tests for it. This is important so I don't break it in a
45
+ future version unintentionally.
46
+ * Commit, do not mess with rakefile, version, or history.
47
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
48
+ * Send me a pull request. Bonus points for topic branches.
49
+
50
+ == Copyright
51
+
52
+ Copyright (c) 2010 Thomas Limp. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,59 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "acts_as_nested_by"
8
+ gem.summary = %Q{Add a acts_as_nested_by :nesting_model class method to ActiveRecord::Base models}
9
+ gem.description = %Q{
10
+ The acts_as_nested_by class method add 3 instance methods to the model.
11
+ nested_by_nesting_model=(flag) sets the nesting_model
12
+ nested_by_nesting_model returns true if nested_by nesting_model
13
+ nested_by_nesting_model? alias for nested_by_nesting_model
14
+ }
15
+ gem.email = "thomas.limp@valiton.com"
16
+ gem.homepage = "http://github.com/tehael/acts_as_nested_by"
17
+ gem.authors = ["Thomas Limp"]
18
+ gem.add_development_dependency "shoulda", ">= 0"
19
+ gem.add_development_dependency "sqlite3-ruby", ">= 0"
20
+ gem.add_dependency "activerecord"
21
+ end
22
+ Jeweler::GemcutterTasks.new
23
+ rescue LoadError
24
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
25
+ end
26
+
27
+ require 'rake/testtask'
28
+ Rake::TestTask.new(:test) do |test|
29
+ test.libs << 'lib' << 'test'
30
+ test.pattern = 'test/**/test_*.rb'
31
+ test.verbose = true
32
+ end
33
+
34
+ begin
35
+ require 'rcov/rcovtask'
36
+ Rcov::RcovTask.new do |test|
37
+ test.libs << 'test'
38
+ test.pattern = 'test/**/test_*.rb'
39
+ test.verbose = true
40
+ end
41
+ rescue LoadError
42
+ task :rcov do
43
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
44
+ end
45
+ end
46
+
47
+ task :test => :check_dependencies
48
+
49
+ task :default => :test
50
+
51
+ require 'rake/rdoctask'
52
+ Rake::RDocTask.new do |rdoc|
53
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
54
+
55
+ rdoc.rdoc_dir = 'rdoc'
56
+ rdoc.title = "acts_as_nested_by #{version}"
57
+ rdoc.rdoc_files.include('README*')
58
+ rdoc.rdoc_files.include('lib/**/*.rb')
59
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.1
@@ -0,0 +1,65 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{acts_as_nested_by}
8
+ s.version = "0.1.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Thomas Limp"]
12
+ s.date = %q{2010-05-05}
13
+ s.description = %q{
14
+ The acts_as_nested_by class method add 3 instance methods to the model.
15
+ nested_by_nesting_model=(flag) sets the nesting_model
16
+ nested_by_nesting_model returns true if nested_by nesting_model
17
+ nested_by_nesting_model? alias for nested_by_nesting_model
18
+ }
19
+ s.email = %q{thomas.limp@valiton.com}
20
+ s.extra_rdoc_files = [
21
+ "LICENSE",
22
+ "README.rdoc"
23
+ ]
24
+ s.files = [
25
+ ".document",
26
+ ".gitignore",
27
+ "LICENSE",
28
+ "README.rdoc",
29
+ "Rakefile",
30
+ "VERSION",
31
+ "acts_as_nested_by.gemspec",
32
+ "lib/acts_as_nested_by.rb",
33
+ "test/helper.rb",
34
+ "test/test_acts_as_nested_by.rb"
35
+ ]
36
+ s.homepage = %q{http://github.com/tehael/acts_as_nested_by}
37
+ s.rdoc_options = ["--charset=UTF-8"]
38
+ s.require_paths = ["lib"]
39
+ s.rubygems_version = %q{1.3.6.1}
40
+ s.summary = %q{Add a acts_as_nested_by :nesting_model class method to ActiveRecord::Base models}
41
+ s.test_files = [
42
+ "test/helper.rb",
43
+ "test/test_acts_as_nested_by.rb"
44
+ ]
45
+
46
+ if s.respond_to? :specification_version then
47
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
48
+ s.specification_version = 3
49
+
50
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
51
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
52
+ s.add_development_dependency(%q<sqlite3-ruby>, [">= 0"])
53
+ s.add_runtime_dependency(%q<activerecord>, [">= 0"])
54
+ else
55
+ s.add_dependency(%q<shoulda>, [">= 0"])
56
+ s.add_dependency(%q<sqlite3-ruby>, [">= 0"])
57
+ s.add_dependency(%q<activerecord>, [">= 0"])
58
+ end
59
+ else
60
+ s.add_dependency(%q<shoulda>, [">= 0"])
61
+ s.add_dependency(%q<sqlite3-ruby>, [">= 0"])
62
+ s.add_dependency(%q<activerecord>, [">= 0"])
63
+ end
64
+ end
65
+
@@ -0,0 +1,38 @@
1
+ module ActsAsNestedBy#:nodoc
2
+ def self.included(base)
3
+ base.send :extend, ClassMethods
4
+ end
5
+
6
+ module ClassMethods #:nodoc
7
+ # Generates instance methods for setting and reading a nested_by_other flag
8
+ # raises ArgumentError if association to other does not exist or is not created by the :belongs_to macro
9
+ def acts_as_nested_by(*association_names)
10
+ association_names.each do |association_name|
11
+ if reflection = reflect_on_association(association_name)
12
+ if :belongs_to == reflection.macro
13
+ class_eval %{
14
+
15
+ def nested_by_#{association_name}=(nested_by_#{association_name})
16
+ @nested_by_#{association_name} = nested_by_#{association_name}
17
+ end
18
+
19
+ def nested_by_#{association_name}
20
+ @nested_by_#{association_name} = @nested_by_#{association_name}.nil? ? false : true
21
+ end
22
+
23
+ def nested_by_#{association_name}?
24
+ nested_by_#{association_name}
25
+ end
26
+ }
27
+ else
28
+ raise ArgumentError, "Association `#{association_name}' must be :belongs_to but it's `#{reflection.macro}'."
29
+ end
30
+ else
31
+ raise ArgumentError, "No association found for name `#{association_name}'. Has it been defined yet?"
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ require "active_record"
38
+ ActiveRecord::Base.send :include, ActsAsNestedBy
data/test/helper.rb ADDED
@@ -0,0 +1,24 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ require 'acts_as_nested_by'
8
+
9
+ class Foo < ActiveRecord::Base; end
10
+
11
+ class Bar < ActiveRecord::Base; end
12
+
13
+ class Test::Unit::TestCase
14
+ def self.db_setup
15
+ @dbfile = File.join(File.dirname(__FILE__),"test.sqlite3")
16
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => @dbfile)
17
+ ActiveRecord::Migration.create_table :foos
18
+ ActiveRecord::Migration.create_table :bars do |t| t.references :foo end
19
+ end
20
+
21
+ def self.db_teardown
22
+ File.delete(@dbfile)
23
+ end
24
+ end
@@ -0,0 +1,78 @@
1
+ require 'helper'
2
+
3
+ class TestActsAsNestedBy < Test::Unit::TestCase
4
+ db_setup
5
+
6
+ context "ActiveRecord::Base decendant class" do
7
+ should "respond to :acts_as_nested_by" do
8
+ assert Foo.respond_to? :acts_as_nested_by
9
+ end
10
+
11
+ should "raise ArgumentError when trying to set :acts_as_nested_by for an undefined association" do
12
+ assert_raise ArgumentError do
13
+ class Bar < ActiveRecord::Base
14
+ acts_as_nested_by :foo
15
+ end
16
+ end
17
+ end
18
+
19
+ should "raise ArgumentError when trying to set :acts_as_nested_by for association :has_many" do
20
+ assert_raise ArgumentError do
21
+ class Foo < ActiveRecord::Base
22
+ has_many :bars
23
+ acts_as_nested_by :bars
24
+ end
25
+ end
26
+ end
27
+
28
+ should "raise ArgumentError when trying to set :acts_as_nested_by for association :has_one" do
29
+ assert_raise ArgumentError do
30
+ class Foo < ActiveRecord::Base
31
+ has_one :bar
32
+ acts_as_nested_by :bar
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ context "Instance of Bar (which acts_as_nested_by)" do
39
+ setup do
40
+ class Bar < ActiveRecord::Base
41
+ belongs_to :foo
42
+ acts_as_nested_by :foo
43
+ end
44
+ @bar = Bar.new
45
+ end
46
+ should "respond to :nested_by_foo=" do
47
+ assert @bar.respond_to? :nested_by_foo=
48
+ end
49
+
50
+ should "respond to :nested_by_foo" do
51
+ assert @bar.respond_to? :nested_by_foo
52
+ end
53
+
54
+ should "respond to :nested_by_foo?" do
55
+ assert @bar.respond_to? :nested_by_foo?
56
+ end
57
+
58
+ should "return false when called #nested_by_foo if nested_by_foo was not set" do
59
+ assert !@bar.nested_by_foo
60
+ end
61
+
62
+ should "return false when called #nested_by_foo? if nested_by_foo was not set" do
63
+ assert !@bar.nested_by_foo?
64
+ end
65
+
66
+ should "return true when called #nested_by_foo if nested_by_foo was set" do
67
+ @bar = Bar.new(:nested_by_foo => 1)
68
+ assert @bar.nested_by_foo
69
+ end
70
+
71
+ should "return true when called #nested_by_foo? if nested_by_foo was set" do
72
+ @bar = Bar.new(:nested_by_foo => 1)
73
+ assert @bar.nested_by_foo?
74
+ end
75
+ end
76
+
77
+ db_teardown
78
+ end
metadata ADDED
@@ -0,0 +1,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: acts_as_nested_by
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 1
9
+ version: 0.1.1
10
+ platform: ruby
11
+ authors:
12
+ - Thomas Limp
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-05-05 00:00:00 +02:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: shoulda
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :development
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: sqlite3-ruby
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ version: "0"
44
+ type: :development
45
+ version_requirements: *id002
46
+ - !ruby/object:Gem::Dependency
47
+ name: activerecord
48
+ prerelease: false
49
+ requirement: &id003 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ segments:
55
+ - 0
56
+ version: "0"
57
+ type: :runtime
58
+ version_requirements: *id003
59
+ 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@valiton.com
61
+ executables: []
62
+
63
+ extensions: []
64
+
65
+ extra_rdoc_files:
66
+ - LICENSE
67
+ - README.rdoc
68
+ files:
69
+ - .document
70
+ - .gitignore
71
+ - LICENSE
72
+ - README.rdoc
73
+ - Rakefile
74
+ - VERSION
75
+ - acts_as_nested_by.gemspec
76
+ - lib/acts_as_nested_by.rb
77
+ - test/helper.rb
78
+ - test/test_acts_as_nested_by.rb
79
+ has_rdoc: true
80
+ homepage: http://github.com/tehael/acts_as_nested_by
81
+ licenses: []
82
+
83
+ post_install_message:
84
+ rdoc_options:
85
+ - --charset=UTF-8
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ segments:
94
+ - 0
95
+ version: "0"
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ segments:
102
+ - 0
103
+ version: "0"
104
+ requirements: []
105
+
106
+ rubyforge_project:
107
+ rubygems_version: 1.3.6.1
108
+ signing_key:
109
+ specification_version: 3
110
+ summary: Add a acts_as_nested_by :nesting_model class method to ActiveRecord::Base models
111
+ test_files:
112
+ - test/helper.rb
113
+ - test/test_acts_as_nested_by.rb