diff --git a/test/unit/product_test.rb b/test/unit/product_test.rb
index 7ce4821..a32c0b3 100644
--- a/test/unit/product_test.rb
+++ b/test/unit/product_test.rb
@@ -8,6 +8,14 @@ class ProductTest < ActiveSupport::TestCase
@profile = fast_create(Enterprise)
end
+ should 'return associated enterprise region' do
+ @profile.region = fast_create Region, :name => 'Salvador'
+ @profile.save!
+ p = fast_create(Product, :name => 'test product1', :product_category_id => @product_category.id, :enterprise_id => @profile.id)
+
+ assert_equal @profile.region, p.region
+ end
+
should 'create product' do
assert_difference Product, :count do
p = Product.new(:name => 'test product1', :product_category => @product_category, :enterprise_id => @profile.id)
diff --git a/vendor/plugins/nested_has_many_through/.gitignore b/vendor/plugins/nested_has_many_through/.gitignore
new file mode 100644
index 0000000..57f3a0b
--- /dev/null
+++ b/vendor/plugins/nested_has_many_through/.gitignore
@@ -0,0 +1,2 @@
+.garlic
+doc/*
diff --git a/vendor/plugins/nested_has_many_through/CHANGELOG b/vendor/plugins/nested_has_many_through/CHANGELOG
new file mode 100644
index 0000000..2a62803
--- /dev/null
+++ b/vendor/plugins/nested_has_many_through/CHANGELOG
@@ -0,0 +1,4 @@
+* spec'd and fixed some problems with using named_scope in edge
+
+* Initial commit
+
diff --git a/vendor/plugins/nested_has_many_through/MIT-LICENSE b/vendor/plugins/nested_has_many_through/MIT-LICENSE
new file mode 100644
index 0000000..906139d
--- /dev/null
+++ b/vendor/plugins/nested_has_many_through/MIT-LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2008 Ian White - ian.w.white@gmail.com
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/vendor/plugins/nested_has_many_through/README.rdoc b/vendor/plugins/nested_has_many_through/README.rdoc
new file mode 100755
index 0000000..03f01f6
--- /dev/null
+++ b/vendor/plugins/nested_has_many_through/README.rdoc
@@ -0,0 +1,92 @@
+http://plugins.ardes.com > nested_has_many_through
+
+= nested_has_many_through
+
+A fantastic patch/plugin has been floating around for a while:
+
+* http://dev.rubyonrails.org/ticket/6461
+* http://code.torchbox.com/svn/rails/plugins/nested_has_many_through
+
+obrie made the original ticket and Matt Westcott released the first version of
+the plugin, under the MIT license. Many others have contributed, see the trac
+ticket for details.
+
+Here is a refactored version (I didn't write the original), suitable for edge/2.0-stable
+with a bunch of acceptance specs. I'm concentrating on plugin usage, once
+it becomes stable, and well enough speced/understood, then it's time to pester
+rails-core.
+
+== Why republish this on github?
+
+* The previous implementations are very poorly speced/tested, so it's pretty
+ hard to refactor and understand this complicated bit of sql-fu, especially
+ when you're aiming at a moving target (edge)
+* the lastest patches don't apply on edge
+* github - let's collab to make this better and get a patch accepted, fork away!
+
+== Help out
+
+I'm releasing 'early and often' in the hope that people will use it and find bugs/problems.
+Report them at http://ianwhite.lighthouseapp.com, or fork and pull request, yada yada.
+
+== History
+
+Here's the original description:
+
+ This plugin makes it possible to define has_many :through relationships that
+ go through other has_many :through relationships, possibly through an
+ arbitrarily deep hierarchy. This allows associations across any number of
+ tables to be constructed, without having to resort to find_by_sql (which isn't
+ a suitable solution if you need to do eager loading through :include as well).
+
+== Contributors
+
+* Matt Westcott
+* terceiro
+* shoe
+* mhoroschun
+* Ian White (http://github.com/ianwhite)
+* Claudio (http://github.com/masterkain)
+
+Get in touch if you should be on this list
+
+== Show me the money!
+
+Here's some models from the specs:
+
+ class Author < User
+ has_many :posts
+ has_many :categories, :through => :posts, :uniq => true
+ has_many :similar_posts, :through => :categories, :source => :posts
+ has_many :similar_authors, :through => :similar_posts, :source => :author, :uniq => true
+ has_many :posts_of_similar_authors, :through => :similar_authors, :source => :posts, :uniq => true
+ has_many :commenters, :through => :posts, :uniq => true
+ end
+
+ class Post < ActiveRecord::Base
+ belongs_to :author
+ belongs_to :category
+ has_many :comments
+ has_many :commenters, :through => :comments, :source => :user, :uniq => true
+ end
+
+The first two has_manys of Author are plain vanilla, the last four are what this plugin enables
+
+ # has_many through a has_many :through
+ has_many :similar_posts, :through => :categories, :source => :posts
+
+ # doubly nested has_many :through
+ has_many :similar_authors, :through => :similar_posts, :source => :author, :uniq => true
+
+ # whoah!
+ has_many :posts_of_similar_authors, :through => :similar_authors, :source => :posts, :uniq => true
+
+ # has_many through a has_many :through in another model
+ has_many :commenters, :through => :posts, :uniq => true
+
+== What does it run on?
+
+Currently it's running on 2.0, 2.1, and 2.2 stable branches
+
+If you want to run the CI suite, then check out garlic_example.rb (The CI suite
+is being cooked with garlic - git://github.com/ianwhite/garlic)
diff --git a/vendor/plugins/nested_has_many_through/Rakefile b/vendor/plugins/nested_has_many_through/Rakefile
new file mode 100644
index 0000000..ecc8b5f
--- /dev/null
+++ b/vendor/plugins/nested_has_many_through/Rakefile
@@ -0,0 +1,77 @@
+# use pluginized rpsec if it exists
+rspec_base = File.expand_path(File.dirname(__FILE__) + '/../rspec/lib')
+$LOAD_PATH.unshift(rspec_base) if File.exist?(rspec_base) and !$LOAD_PATH.include?(rspec_base)
+
+require 'spec/rake/spectask'
+require 'spec/rake/verify_rcov'
+require 'rake/rdoctask'
+
+plugin_name = 'nested_has_many_through'
+
+task :default => :spec
+
+desc "Run the specs for #{plugin_name}"
+Spec::Rake::SpecTask.new(:spec) do |t|
+ t.spec_files = FileList['spec/**/*_spec.rb']
+ t.spec_opts = ["--colour"]
+end
+
+namespace :spec do
+ desc "Generate RCov report for #{plugin_name}"
+ Spec::Rake::SpecTask.new(:rcov) do |t|
+ t.spec_files = FileList['spec/**/*_spec.rb']
+ t.rcov = true
+ t.rcov_dir = 'doc/coverage'
+ t.rcov_opts = ['--text-report', '--exclude', "spec/,rcov.rb,#{File.expand_path(File.join(File.dirname(__FILE__),'../../..'))}"]
+ end
+
+ namespace :rcov do
+ desc "Verify RCov threshold for #{plugin_name}"
+ RCov::VerifyTask.new(:verify => "spec:rcov") do |t|
+ t.threshold = 97.1
+ t.index_html = File.join(File.dirname(__FILE__), 'doc/coverage/index.html')
+ end
+ end
+
+ desc "Generate specdoc for #{plugin_name}"
+ Spec::Rake::SpecTask.new(:doc) do |t|
+ t.spec_files = FileList['spec/**/*_spec.rb']
+ t.spec_opts = ["--format", "specdoc:SPECDOC"]
+ end
+
+ namespace :doc do
+ desc "Generate html specdoc for #{plugin_name}"
+ Spec::Rake::SpecTask.new(:html => :rdoc) do |t|
+ t.spec_files = FileList['spec/**/*_spec.rb']
+ t.spec_opts = ["--format", "html:doc/rspec_report.html", "--diff"]
+ end
+ end
+end
+
+task :rdoc => :doc
+task "SPECDOC" => "spec:doc"
+
+desc "Generate rdoc for #{plugin_name}"
+Rake::RDocTask.new(:doc) do |t|
+ t.rdoc_dir = 'doc'
+ t.main = 'README.rdoc'
+ t.title = "#{plugin_name}"
+ t.template = ENV['RDOC_TEMPLATE']
+ t.options = ['--line-numbers', '--inline-source']
+ t.rdoc_files.include('README.rdoc', 'SPECDOC', 'MIT-LICENSE')
+ t.rdoc_files.include('lib/**/*.rb')
+end
+
+namespace :doc do
+ desc "Generate all documentation (rdoc, specdoc, specdoc html and rcov) for #{plugin_name}"
+ task :all => ["spec:doc:html", "spec:doc", "spec:rcov", "doc"]
+end
+
+task :cruise do
+ # run the garlic task, capture the output, if succesful make the docs and copy them to ardes
+ sh "garlic all"
+ `garlic run > .garlic/report.txt`
+ `scp -i ~/.ssh/ardes .garlic/report.txt ardes@ardes.com:~/subdomains/plugins/httpdocs/doc/#{plugin_name}_garlic_report.txt`
+ `cd .garlic/*/vendor/plugins/#{plugin_name}; rake doc:all; scp -i ~/.ssh/ardes -r doc ardes@ardes.com:~/subdomains/plugins/httpdocs/doc/#{plugin_name}`
+ puts "The build is GOOD"
+end
diff --git a/vendor/plugins/nested_has_many_through/SPECDOC b/vendor/plugins/nested_has_many_through/SPECDOC
new file mode 100644
index 0000000..6ce019f
--- /dev/null
+++ b/vendor/plugins/nested_has_many_through/SPECDOC
@@ -0,0 +1,49 @@
+
+Author (newly created)
+- #posts should == []
+- #categories should == []
+- #similar_posts should == []
+- #similar_authors should == []
+- #commenters should == []
+
+Author (newly created) who creates post with category
+- #posts should == [post]
+- #categories should == [category]
+
+Author (newly created) who creates post with category and @other_author creates post2 in category
+- #posts should == [post2]
+- #categories should == [category]
+- #similar_posts.should == [post, post2]
+- #similar_authors.should == [@author, @other_author]
+
+Author (newly created) who creates post with category and @other_author creates post2 in category and creates @other_post in @other_category
+- #similar_posts.should == [@post, @post2]
+- #posts_by_similar_authors.should == [@post, @post2, @other_post]
+
+Commenter use case (a1: p1>c1, a2: p2>c1, p3>c2, a3: p4>c3)
+- a1.posts should == [p1]
+- a1.categories should == [c1]
+- a2.posts should == [p2, p3]
+- a2.categories should == [c1, c2]
+
+Commenter use case (a1: p1>c1, a2: p2>c1, p3>c2, a3: p4>c3) u1 comments on p2
+- u1.comments should == [comment]
+- a1.commenters should be empty
+- a2.commenters should == [u1]
+- u1.commented_posts should == [p2]
+- u1.commented_posts.find_inflamatory(:all) should be empty
+- u1.commented_posts.inflamatory should be empty
+- u1.commented_authors should == [a2]
+- u1.posts_of_interest should == [p1, p2, p3]
+- u1.categories_of_interest should == [c1, c2]
+
+Commenter use case (a1: p1>c1, a2: p2>c1, p3>c2, a3: p4>c3) u1 comments on p2 when p2 is inflamatory
+- p2 should be inflamatory
+- u1.commented_posts.find_inflamatory(:all) should == [p2]
+- u1.posts_of_interest.find_inflamatory(:all) should == [p2]
+- u1.commented_posts.inflamatory should == [p2]
+- u1.posts_of_interest.inflamatory should == [p2]
+
+Finished in 0.538693 seconds
+
+31 examples, 0 failures
diff --git a/vendor/plugins/nested_has_many_through/TODO b/vendor/plugins/nested_has_many_through/TODO
new file mode 100644
index 0000000..76e4409
--- /dev/null
+++ b/vendor/plugins/nested_has_many_through/TODO
@@ -0,0 +1,10 @@
+* get C2 up to 100%
+ - spec a polymorphic relationship
+
+* quote table names
+
+* make more use of rails in construct_has_many_or_belongs_to_attributes to reduce brittleness
+
+* Add more coverage
+ - scopes
+ - raise an error when nhmt is being used in a perverse way
\ No newline at end of file
diff --git a/vendor/plugins/nested_has_many_through/garlic.rb b/vendor/plugins/nested_has_many_through/garlic.rb
new file mode 100644
index 0000000..57c0b85
--- /dev/null
+++ b/vendor/plugins/nested_has_many_through/garlic.rb
@@ -0,0 +1,27 @@
+garlic do
+ repo 'nested_has_many_through', :path => '.'
+
+ repo 'rails', :url => 'git://github.com/rails/rails'
+ repo 'rspec', :url => 'git://github.com/dchelimsky/rspec'
+ repo 'rspec-rails', :url => 'git://github.com/dchelimsky/rspec-rails'
+
+ # target rails versions
+ ['origin/2-2-stable', 'origin/2-1-stable', 'origin/2-0-stable'].each do |rails|
+ # specify how to prepare app and run CI task
+ target "Rails: #{rails}", :tree_ish => rails do
+ prepare do
+ plugin 'rspec'
+ plugin 'rspec-rails' do
+ `script/generate rspec -f`
+ end
+ plugin 'nested_has_many_through', :clone => true
+ end
+
+ run do
+ cd "vendor/plugins/nested_has_many_through" do
+ sh "rake spec:rcov:verify"
+ end
+ end
+ end
+ end
+end
diff --git a/vendor/plugins/nested_has_many_through/init.rb b/vendor/plugins/nested_has_many_through/init.rb
new file mode 100644
index 0000000..ccd759b
--- /dev/null
+++ b/vendor/plugins/nested_has_many_through/init.rb
@@ -0,0 +1,10 @@
+require 'nested_has_many_through'
+
+ActiveRecord::Associations::HasManyThroughAssociation.send :include, NestedHasManyThrough::Association
+
+# BC
+if defined?(ActiveRecord::Reflection::ThroughReflection)
+ ActiveRecord::Reflection::ThroughReflection.send :include, NestedHasManyThrough::Reflection
+else
+ ActiveRecord::Reflection::AssociationReflection.send :include, NestedHasManyThrough::Reflection
+end
\ No newline at end of file
diff --git a/vendor/plugins/nested_has_many_through/lib/nested_has_many_through.rb b/vendor/plugins/nested_has_many_through/lib/nested_has_many_through.rb
new file mode 100644
index 0000000..958efb7
--- /dev/null
+++ b/vendor/plugins/nested_has_many_through/lib/nested_has_many_through.rb
@@ -0,0 +1,148 @@
+module NestedHasManyThrough
+ module Reflection # :nodoc:
+ def self.included(base)
+ base.send :alias_method_chain, :check_validity!, :nested_has_many_through
+ end
+
+ def check_validity_with_nested_has_many_through!
+ check_validity_without_nested_has_many_through!
+ rescue ActiveRecord::HasManyThroughSourceAssociationMacroError => e
+ # now we permit has many through to a :though source
+ raise e unless source_reflection.options[:through]
+ end
+ end
+
+ module Association
+ def self.included(base)
+ base.class_eval do
+ alias_method :original_construct_conditions, :construct_conditions
+ alias_method :original_construct_joins, :construct_joins
+
+ def construct_conditions
+ if @reflection.macro == :has_one
+ original_construct_conditions
+ else
+ @nested_join_attributes ||= construct_nested_join_attributes
+ "#{@nested_join_attributes[:remote_key]} = #{@owner.quoted_id} #{@nested_join_attributes[:conditions]}"
+ end
+ end
+
+ def construct_joins(custom_joins = nil)
+ if @reflection.macro == :has_one
+ original_construct_joins(custom_joins)
+ else
+ @nested_join_attributes ||= construct_nested_join_attributes
+ "#{@nested_join_attributes[:joins]} #{custom_joins}"
+ end
+ end
+ end
+ end
+
+ protected
+ # Given any belongs_to or has_many (including has_many :through) association,
+ # return the essential components of a join corresponding to that association, namely:
+ #
+ # * :joins: any additional joins required to get from the association's table
+ # (reflection.table_name) to the table that's actually joining to the active record's table
+ # * :remote_key: the name of the key in the join table (qualified by table name) which will join
+ # to a field of the active record's table
+ # * :local_key: the name of the key in the local table (not qualified by table name) which will
+ # take part in the join
+ # * :conditions: any additional conditions (e.g. filtering by type for a polymorphic association,
+ # or a :conditions clause explicitly given in the association), including a leading AND
+ def construct_nested_join_attributes( reflection = @reflection,
+ association_class = reflection.klass,
+ table_ids = {association_class.table_name => 1})
+ if reflection.macro == :has_many && reflection.through_reflection
+ construct_has_many_through_attributes(reflection, table_ids)
+ else
+ construct_has_many_or_belongs_to_attributes(reflection, association_class, table_ids)
+ end
+ end
+
+ def construct_has_many_through_attributes(reflection, table_ids)
+ # Construct the join components of the source association, so that we have a path from
+ # the eventual target table of the association up to the table named in :through, and
+ # all tables involved are allocated table IDs.
+ source_attrs = construct_nested_join_attributes(reflection.source_reflection, reflection.klass, table_ids)
+
+ # Determine the alias of the :through table; this will be the last table assigned
+ # when constructing the source join components above.
+ through_table_alias = through_table_name = reflection.through_reflection.table_name
+ through_table_alias += "_#{table_ids[through_table_name]}" unless table_ids[through_table_name] == 1
+
+ # Construct the join components of the through association, so that we have a path to
+ # the active record's table.
+ through_attrs = construct_nested_join_attributes(reflection.through_reflection, reflection.through_reflection.klass, table_ids)
+
+ # Any subsequent joins / filters on owner attributes will act on the through association,
+ # so that's what we return for the conditions/keys of the overall association.
+ conditions = through_attrs[:conditions]
+ conditions += " AND #{interpolate_sql(reflection.klass.send(:sanitize_sql, reflection.options[:conditions]))}" if reflection.options[:conditions]
+
+ {
+ :joins => "%s INNER JOIN %s ON ( %s = %s.%s %s) %s %s" % [
+ source_attrs[:joins],
+ through_table_name == through_table_alias ? through_table_name : "#{through_table_name} #{through_table_alias}",
+ source_attrs[:remote_key],
+ through_table_alias, source_attrs[:local_key],
+ source_attrs[:conditions],
+ through_attrs[:joins],
+ reflection.options[:joins]
+ ],
+ :remote_key => through_attrs[:remote_key],
+ :local_key => through_attrs[:local_key],
+ :conditions => conditions
+ }
+ end
+
+
+ # reflection is not has_many :through; it's a standard has_many / belongs_to instead
+ # TODO: see if we can defer to rails code here a bit more
+ def construct_has_many_or_belongs_to_attributes(reflection, association_class, table_ids)
+ # Determine the alias used for remote_table_name, if any. In all cases this will already
+ # have been assigned an ID in table_ids (either through being involved in a previous join,
+ # or - if it's the first table in the query - as the default value of table_ids)
+ remote_table_alias = remote_table_name = association_class.table_name
+ remote_table_alias += "_#{table_ids[remote_table_name]}" unless table_ids[remote_table_name] == 1
+
+ # Assign a new alias for the local table.
+ local_table_alias = local_table_name = reflection.active_record.table_name
+ if table_ids[local_table_name]
+ table_id = table_ids[local_table_name] += 1
+ local_table_alias += "_#{table_id}"
+ else
+ table_ids[local_table_name] = 1
+ end
+
+ conditions = ''
+ # Add filter for single-table inheritance, if applicable.
+ conditions += " AND #{remote_table_alias}.#{association_class.inheritance_column} = #{association_class.quote_value(association_class.name.demodulize)}" unless association_class.descends_from_active_record?
+ # Add custom conditions
+ conditions += " AND (#{interpolate_sql(association_class.send(:sanitize_sql, reflection.options[:conditions]))})" if reflection.options[:conditions]
+
+ if reflection.macro == :belongs_to
+ if reflection.options[:polymorphic]
+ conditions += " AND #{local_table_alias}.#{reflection.options[:foreign_type]} = #{reflection.active_record.quote_value(association_class.base_class.name.to_s)}"
+ end
+ {
+ :joins => reflection.options[:joins],
+ :remote_key => "#{remote_table_alias}.#{association_class.primary_key}",
+ :local_key => reflection.primary_key_name,
+ :conditions => conditions
+ }
+ else
+ # Association is has_many (without :through)
+ if reflection.options[:as]
+ conditions += " AND #{remote_table_alias}.#{reflection.options[:as]}_type = #{reflection.active_record.quote_value(reflection.active_record.base_class.name.to_s)}"
+ end
+ {
+ :joins => "#{reflection.options[:joins]}",
+ :remote_key => "#{remote_table_alias}.#{reflection.primary_key_name}",
+ :local_key => reflection.klass.primary_key,
+ :conditions => conditions
+ }
+ end
+ end
+ end
+end
diff --git a/vendor/plugins/nested_has_many_through/spec/app.rb b/vendor/plugins/nested_has_many_through/spec/app.rb
new file mode 100644
index 0000000..71c7c4e
--- /dev/null
+++ b/vendor/plugins/nested_has_many_through/spec/app.rb
@@ -0,0 +1,84 @@
+# Testing app setup
+
+##################
+# Database schema
+##################
+
+ActiveRecord::Migration.suppress_messages do
+ ActiveRecord::Schema.define(:version => 0) do
+ create_table :users, :force => true do |t|
+ t.column "type", :string
+ end
+
+ create_table :posts, :force => true do |t|
+ t.column "author_id", :integer
+ t.column "category_id", :integer
+ t.column "inflamatory", :boolean
+ end
+
+ create_table :categories, :force => true do |t|
+ end
+
+ create_table :comments, :force => true do |t|
+ t.column "user_id", :integer
+ t.column "post_id", :integer
+ end
+ end
+end
+
+#########
+# Models
+#
+# Domain model is this:
+#
+# - authors (type of user) can create posts in categories
+# - users can comment on posts
+# - authors have similar_posts: posts in the same categories as ther posts
+# - authors have similar_authors: authors of the recommended_posts
+# - authors have posts_of_similar_authors: all posts by similar authors (not just the similar posts,
+# similar_posts is be a subset of this collection)
+# - authors have commenters: users who have commented on their posts
+#
+class User < ActiveRecord::Base
+ has_many :comments
+ has_many :commented_posts, :through => :comments, :source => :post, :uniq => true
+ has_many :commented_authors, :through => :commented_posts, :source => :author, :uniq => true
+ has_many :posts_of_interest, :through => :commented_authors, :source => :posts_of_similar_authors, :uniq => true
+ has_many :categories_of_interest, :through => :posts_of_interest, :source => :category, :uniq => true
+end
+
+class Author < User
+ has_many :posts
+ has_many :categories, :through => :posts
+ has_many :similar_posts, :through => :categories, :source => :posts
+ has_many :similar_authors, :through => :similar_posts, :source => :author, :uniq => true
+ has_many :posts_of_similar_authors, :through => :similar_authors, :source => :posts, :uniq => true
+ has_many :commenters, :through => :posts, :uniq => true
+end
+
+class Post < ActiveRecord::Base
+
+ # testing with_scope
+ def self.find_inflamatory(*args)
+ with_scope :find => {:conditions => {:inflamatory => true}} do
+ find(*args)
+ end
+ end
+
+ # only test named_scope in edge
+ named_scope(:inflamatory, :conditions => {:inflamatory => true}) if respond_to?(:named_scope)
+
+ belongs_to :author
+ belongs_to :category
+ has_many :comments
+ has_many :commenters, :through => :comments, :source => :user, :uniq => true
+end
+
+class Category < ActiveRecord::Base
+ has_many :posts
+end
+
+class Comment < ActiveRecord::Base
+ belongs_to :user
+ belongs_to :post
+end
\ No newline at end of file
diff --git a/vendor/plugins/nested_has_many_through/spec/models/author_spec.rb b/vendor/plugins/nested_has_many_through/spec/models/author_spec.rb
new file mode 100644
index 0000000..36ccf18
--- /dev/null
+++ b/vendor/plugins/nested_has_many_through/spec/models/author_spec.rb
@@ -0,0 +1,85 @@
+require File.expand_path(File.join(File.dirname(__FILE__), '../spec_helper'))
+require File.expand_path(File.join(File.dirname(__FILE__), '../app'))
+
+describe Author do
+ describe "(newly created)" do
+ before do
+ @category = Category.create!
+ @other_category = Category.create!
+ @author = Author.create!
+ end
+
+ it "#posts should == []" do
+ @author.posts.should == []
+ end
+
+ it "#categories should == []" do
+ @author.categories.should == []
+ end
+
+ it "#similar_posts should == []" do
+ @author.similar_posts.should == []
+ end
+
+ it "#similar_authors should == []" do
+ @author.similar_authors.should == []
+ end
+
+ it "#commenters should == []" do
+ @author.commenters.should == []
+ end
+
+ describe "who creates post with category" do
+ before do
+ @post = Post.create! :author => @author, :category => @category
+ end
+
+ it "#posts should == [post]" do
+ @author.posts.should == [@post]
+ end
+
+ it "#categories should == [category]" do
+ @author.categories.should == [@category]
+ end
+
+ describe "and @other_author creates post2 in category" do
+
+ before do
+ @other_author = Author.create!
+ @post2 = Post.create! :author => @other_author, :category => @category
+ end
+
+ it "#posts should == [post2]" do
+ @author.posts.should == [@post]
+ end
+
+ it "#categories should == [category]" do
+ @author.categories.should == [@category]
+ end
+
+ it "#similar_posts.should == [post, post2]" do
+ @author.similar_posts.should == [@post, @post2]
+ end
+
+ it "#similar_authors.should == [@author, @other_author]" do
+ @author.similar_authors.should == [@author, @other_author]
+ end
+
+ describe "and creates @other_post in @other_category" do
+ before do
+ @other_category = Category.create!
+ @other_post = Post.create! :author => @other_author, :category => @other_category
+ end
+
+ it "#similar_posts.should == [@post, @post2]" do
+ @author.similar_posts.should == [@post, @post2]
+ end
+
+ it "#posts_by_similar_authors.should == [@post, @post2, @other_post]" do
+ @author.posts_of_similar_authors.should == [@post, @post2, @other_post]
+ end
+ end
+ end
+ end
+ end
+end
\ No newline at end of file
diff --git a/vendor/plugins/nested_has_many_through/spec/models/commenter_spec.rb b/vendor/plugins/nested_has_many_through/spec/models/commenter_spec.rb
new file mode 100644
index 0000000..b57b3ce
--- /dev/null
+++ b/vendor/plugins/nested_has_many_through/spec/models/commenter_spec.rb
@@ -0,0 +1,109 @@
+require File.expand_path(File.join(File.dirname(__FILE__), '../spec_helper'))
+require File.expand_path(File.join(File.dirname(__FILE__), '../app'))
+
+describe 'Commenter use case (a1: p1>c1, a2: p2>c1, p3>c2, a3: p4>c3)' do
+ before do
+ @c1 = Category.create!
+ @c2 = Category.create!
+ @c3 = Category.create!
+ @a1 = Author.create!
+ @a2 = Author.create!
+ @a3 = Author.create!
+ @p1 = @a1.posts.create! :category => @c1
+ @p2 = @a2.posts.create! :category => @c1
+ @p3 = @a2.posts.create! :category => @c2
+ @p4 = @a3.posts.create! :category => @c3
+ @a1.reload
+ @a2.reload
+ end
+
+ it "a1.posts should == [p1]" do
+ @a1.posts.should == [@p1]
+ end
+
+ it "a1.categories should == [c1]" do
+ @a1.categories.should == [@c1]
+ end
+
+ it "a2.posts should == [p2, p3]" do
+ @a2.posts.should == [@p2, @p3]
+ end
+
+ it "a2.categories should == [c1, c2]" do
+ @a2.categories.should == [@c1, @c2]
+ end
+
+ describe "u1 comments on p2" do
+ before do
+ @u1 = User.create!
+ @comment = @p2.comments.create! :user => @u1
+ end
+
+ it "u1.comments should == [comment]" do
+ @u1.comments.should == [@comment]
+ end
+
+ it "a1.commenters should be empty" do
+ @a1.commenters.should be_empty
+ end
+
+ it "a2.commenters should == [u1]" do
+ @a2.commenters.should == [@u1]
+ end
+
+ it "u1.commented_posts should == [p2]" do
+ @u1.commented_posts.should == [@p2]
+ end
+
+ it "u1.commented_posts.find_inflamatory(:all) should be empty" do
+ @u1.commented_posts.find_inflamatory(:all).should be_empty
+ end
+
+ if ActiveRecord::Base.respond_to?(:named_scope)
+ it "u1.commented_posts.inflamatory should be empty" do
+ @u1.commented_posts.inflamatory.should be_empty
+ end
+ end
+
+ it "u1.commented_authors should == [a2]" do
+ @u1.commented_authors.should == [@a2]
+ end
+
+ it "u1.posts_of_interest should == [p1, p2, p3]" do
+ @u1.posts_of_interest.should == [@p1, @p2, @p3]
+ end
+
+ it "u1.categories_of_interest should == [c1, c2]" do
+ @u1.categories_of_interest.should == [@c1, @c2]
+ end
+
+ describe "when p2 is inflamatory" do
+ before do
+ @p2.toggle!(:inflamatory)
+ end
+
+ it "p2 should be inflamatory" do
+ @p2.should be_inflamatory
+ end
+
+ it "u1.commented_posts.find_inflamatory(:all) should == [p2]" do
+ # uniq ids is here (and next spec) because eager loading changed behaviour 2.0.2 => edge
+ @u1.commented_posts.find_inflamatory(:all).collect(&:id).uniq.should == [@p2.id]
+ end
+
+ it "u1.posts_of_interest.find_inflamatory(:all).uniq should == [p2]" do
+ @u1.posts_of_interest.find_inflamatory(:all).collect(&:id).uniq.should == [@p2.id]
+ end
+
+ if ActiveRecord::Base.respond_to?(:named_scope)
+ it "u1.commented_posts.inflamatory should == [p2]" do
+ @u1.commented_posts.inflamatory.should == [@p2]
+ end
+
+ it "u1.posts_of_interest.inflamatory should == [p2]" do
+ @u1.posts_of_interest.inflamatory.should == [@p2]
+ end
+ end
+ end
+ end
+end
diff --git a/vendor/plugins/nested_has_many_through/spec/spec_helper.rb b/vendor/plugins/nested_has_many_through/spec/spec_helper.rb
new file mode 100644
index 0000000..8e21f5b
--- /dev/null
+++ b/vendor/plugins/nested_has_many_through/spec/spec_helper.rb
@@ -0,0 +1,23 @@
+# This file is copied to ~/spec when you run 'ruby script/generate rspec'
+# from the project root directory.
+ENV["RAILS_ENV"] ||= "test"
+require File.expand_path(File.join(File.dirname(__FILE__), "../../../../config/environment"))
+require 'spec/rails'
+
+Spec::Runner.configure do |config|
+ config.use_transactional_fixtures = true
+ config.use_instantiated_fixtures = false
+ config.fixture_path = RAILS_ROOT + '/spec/fixtures'
+
+ # You can declare fixtures for each behaviour like this:
+ # describe "...." do
+ # fixtures :table_a, :table_b
+ #
+ # Alternatively, if you prefer to declare them only once, you can
+ # do so here, like so ...
+ #
+ # config.global_fixtures = :table_a, :table_b
+ #
+ # If you declare global fixtures, be aware that they will be declared
+ # for all of your examples, even those that don't use them.
+end
\ No newline at end of file
--
libgit2 0.21.2