kristopher-scoped-associations 0.0.3

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/CHANGELOG ADDED
@@ -0,0 +1,3 @@
1
+ v0.0.3. Cleaned up package internals.
2
+ v0.0.2. Initial gem release, github only.
3
+ v0.0.1. Initial release.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Kristopher Chambers and Elijah Miller
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/Manifest ADDED
@@ -0,0 +1,13 @@
1
+ CHANGELOG
2
+ init.rb
3
+ lib/scope_reflection.rb
4
+ lib/scoped_associations.rb
5
+ LICENSE
6
+ Manifest
7
+ Rakefile
8
+ README.rdoc
9
+ scoped-associations.gemspec
10
+ spec/models.rb
11
+ spec/scoped_associations_spec.rb
12
+ spec/spec_helper.rb
13
+ TODO
data/README.rdoc ADDED
@@ -0,0 +1,34 @@
1
+ = ScopedAssociations
2
+
3
+ Use your named scopes to add conditions to associations! Keep your code DRY
4
+ and allows eager loading of scoped associations.
5
+
6
+ Currently this only works for has_many associations, and probably only on
7
+ Rails 2.2.
8
+
9
+ == Example
10
+
11
+ class User < ActiveRecord::Base
12
+ has_many :published_posts, :scope => :published
13
+ has_many :published_and_approved_posts, :scope => [:published, :approved]
14
+ end
15
+
16
+ class Post < ActiveRecord::Base
17
+ named_scope :published, :conditions => { :published => true }
18
+ named_scope :approved, :conditions => { :approved => true }
19
+ end
20
+
21
+ == Install
22
+
23
+ As a Rails plugin:
24
+
25
+ ./script_plugin install git://github.com/kristopher/scoped-associations.git
26
+
27
+ Prefer gems?
28
+
29
+ gem sources -a http://gems.github.com
30
+ gem install kristopher-scoped-associations
31
+
32
+
33
+ Homepage:: http://github.com/kristopher/scoped-associations
34
+ License:: Copyright (c) 2008 Kristopher Chambers <mailto:kristopher.chambers@gmail.com> and Elijah Miller <mailto:elijah.miller@gmail.com>, released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ require 'spec/rake/spectask'
2
+
3
+ require 'echoe'
4
+ Echoe.new 'scoped-associations' do |p|
5
+ p.description = "DRY up your associations with named_scope conditions!"
6
+ # p.url = "http://scoped-associations.rubyforge.org"
7
+ p.author = "Kristopher Chambers"
8
+ p.email = "kristopher.chambers@gmail.com"
9
+ p.retain_gemspec = true
10
+ p.need_tar_gz = false
11
+ p.extra_deps = [
12
+ ]
13
+ p.ignore_pattern = ['spec/test.sqlite3']
14
+ end
15
+
16
+ desc 'Default: run specs'
17
+ task :default => :spec
18
+ Spec::Rake::SpecTask.new do |t|
19
+ t.spec_files = FileList["spec/**/*_spec.rb"]
20
+ end
21
+
22
+ task :test => :spec
data/TODO ADDED
@@ -0,0 +1,9 @@
1
+ A shortcut for generating multiple associations that are scoped:
2
+ has_many :posts
3
+ has_many :published_posts, :scope => :published
4
+ has_many :archived_posts, :scope => :archived
5
+
6
+ Could be shortened to:
7
+
8
+ has_many :posts, :and_scopes => [:published, :archived]
9
+
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'scoped_associations'
@@ -0,0 +1,32 @@
1
+ module ActiveRecord
2
+ module Associations
3
+ module ScopeReflection
4
+ def initialize(owner, reflection)
5
+ scope_reflection(reflection)
6
+ super
7
+ end
8
+
9
+ def scope_reflection(reflection)
10
+
11
+ source_reflection_class =
12
+ if reflection.is_a? ActiveRecord::Reflection::ThroughReflection
13
+ reflection.source_reflection.klass
14
+ else
15
+ reflection.klass
16
+ end
17
+
18
+ scope_names = [reflection.options[:scope]].flatten.compact
19
+ final_scope = scope_names.inject(source_reflection_class) do |accumulated_scope, scope|
20
+ if accumulated_scope.respond_to?(scope)
21
+ accumulated_scope.send(scope)
22
+ else
23
+ raise ActiveRecord::UndefinedScopeReflectionError.new(self, scope)
24
+ end
25
+ end
26
+
27
+ current_scoped_methods = final_scope.send(:current_scoped_methods) || {}
28
+ reflection.options.merge!(current_scoped_methods[:find] || {})
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,18 @@
1
+ module ActiveRecord # :nodoc:
2
+ class UndefinedScopeReflectionError < ActiveRecordError # :nodoc:
3
+ def initialize(reflection, scope)
4
+ super("Undefined Scope '#{scope}' for #{reflection.class_name}.")
5
+ end
6
+ end
7
+
8
+ module Associations # :nodoc:
9
+ module ClassMethods # :nodoc:
10
+ @@valid_keys_for_has_many_association << :scope
11
+ end
12
+ end
13
+ end
14
+
15
+ require File.join(File.dirname(__FILE__), 'scope_reflection')
16
+
17
+ ActiveRecord::Associations::HasManyAssociation.send(:include, ActiveRecord::Associations::ScopeReflection)
18
+ ActiveRecord::Associations::HasManyThroughAssociation.send(:include, ActiveRecord::Associations::ScopeReflection)
@@ -0,0 +1,34 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{scoped-associations}
5
+ s.version = "0.0.3"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Kristopher Chambers"]
9
+ s.date = %q{2008-12-07}
10
+ s.description = %q{DRY up your associations with named_scope conditions!}
11
+ s.email = %q{kristopher.chambers@gmail.com}
12
+ s.extra_rdoc_files = ["CHANGELOG", "lib/scope_reflection.rb", "lib/scoped_associations.rb", "LICENSE", "README.rdoc", "TODO"]
13
+ s.files = ["CHANGELOG", "init.rb", "lib/scope_reflection.rb", "lib/scoped_associations.rb", "LICENSE", "Manifest", "Rakefile", "README.rdoc", "scoped-associations.gemspec", "spec/models.rb", "spec/scoped_associations_spec.rb", "spec/spec_helper.rb", "TODO"]
14
+ s.has_rdoc = true
15
+ s.homepage = %q{}
16
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Scoped-associations", "--main", "README.rdoc"]
17
+ s.require_paths = ["lib"]
18
+ s.rubyforge_project = %q{scoped-associations}
19
+ s.rubygems_version = %q{1.3.1}
20
+ s.summary = %q{DRY up your associations with named_scope conditions!}
21
+
22
+ if s.respond_to? :specification_version then
23
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
24
+ s.specification_version = 2
25
+
26
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
27
+ s.add_development_dependency(%q<echoe>, [">= 0"])
28
+ else
29
+ s.add_dependency(%q<echoe>, [">= 0"])
30
+ end
31
+ else
32
+ s.add_dependency(%q<echoe>, [">= 0"])
33
+ end
34
+ end
data/spec/models.rb ADDED
@@ -0,0 +1,30 @@
1
+ class GrandChild < ActiveRecord::Base
2
+ belongs_to :child
3
+
4
+ named_scope :alive, :conditions => { :alive => true }
5
+ end
6
+
7
+ class Child < ActiveRecord::Base
8
+ belongs_to :parent
9
+ has_many :grand_children
10
+
11
+ named_scope :alive, :conditions => { :alive => true }
12
+ end
13
+
14
+ class Parent < ActiveRecord::Base
15
+ # Standard
16
+ has_many :children
17
+ has_many :grand_children, :through => :children
18
+
19
+ # Scope on direct assocation
20
+ has_many :children_direct, :scope => 'alive', :class_name => 'Child'
21
+ has_many :grand_children_direct, :through => :children_direct, :source => :grand_children
22
+
23
+ # Scope on inderect assocation
24
+ has_many :children_indirect, :class_name => 'Child'
25
+ has_many :grand_children_indirect, :through => :children_indirect, :scope => 'alive', :source => :grand_children
26
+
27
+ # Scope on direct and indirect assocation
28
+ has_many :children_direct_and_indirect, :scope => 'alive', :class_name => 'Child'
29
+ has_many :grand_children_direct_and_indirect, :through => :children_direct_and_indirect, :scope => 'alive', :source => :grand_children
30
+ end
@@ -0,0 +1,68 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe "ScopedAssociation" do
4
+ before(:each) do
5
+ @parent = Parent.first
6
+ end
7
+
8
+ describe "standard assocations" do
9
+ describe "has_many" do
10
+ it "should return all children" do
11
+ @parent.children.collect(&:name).should == ['aa', 'ab']
12
+ end
13
+ end
14
+
15
+ describe "has_many :through" do
16
+ it "should return all grand children" do
17
+ @parent.grand_children.collect(&:name).should == ['aaa', 'aab', 'aba', 'abb']
18
+ end
19
+ end
20
+ end
21
+
22
+
23
+ describe "scope on direct assocation" do
24
+ describe "has_many" do
25
+ it "should should return all live children" do
26
+ @parent.children_direct.collect(&:name).should == ['aa']
27
+ end
28
+ end
29
+
30
+ describe "has_many :through" do
31
+ it "should should return all grand children with a live parent" do
32
+ @parent.grand_children_direct.collect(&:name).should == ['aaa', 'aab']
33
+ end
34
+ end
35
+ end
36
+
37
+
38
+ describe "scope on indrect assocation" do
39
+ describe "has_many" do
40
+ it "should return all children" do
41
+ @parent.children_indirect.collect(&:name).should == ['aa', 'ab']
42
+ end
43
+ end
44
+
45
+ describe "has_many :through" do
46
+ it "should should return all live grand children" do
47
+ @parent.grand_children_indirect.collect(&:name).should == ['aaa', 'aba']
48
+ end
49
+ end
50
+ end
51
+
52
+
53
+ describe "scope on direct and indrect assocation" do
54
+ describe "has_many" do
55
+ it "should return all live children" do
56
+ @parent.children_direct_and_indirect.collect(&:name).should == ['aa']
57
+ end
58
+ end
59
+
60
+ describe "has_many :through" do
61
+ it "should return all live grandchildren with a live parent" do
62
+ @parent.grand_children_direct_and_indirect.collect(&:name).should == ['aaa']
63
+ end
64
+ end
65
+ end
66
+
67
+
68
+ end
@@ -0,0 +1,57 @@
1
+ require 'rubygems'
2
+ require 'active_support'
3
+ require 'active_support/test_case'
4
+
5
+ require 'active_record'
6
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'scoped_associations')
7
+
8
+ require File.join(File.dirname(__FILE__), 'models')
9
+
10
+ TEST_DATABASE_FILE = File.join(File.dirname(__FILE__), 'test.sqlite3')
11
+
12
+ def setup_database
13
+ File.unlink(TEST_DATABASE_FILE) if File.exist?(TEST_DATABASE_FILE)
14
+ ActiveRecord::Base.establish_connection(
15
+ "adapter" => "sqlite3", "timeout" => 5000, "database" => TEST_DATABASE_FILE
16
+ )
17
+ create_tables
18
+ load_fixtures
19
+ end
20
+
21
+ def create_tables
22
+ c = ActiveRecord::Base.connection
23
+
24
+ c.create_table :parents, :force => true do |t|
25
+ t.string :name
26
+ t.boolean :alive, :default => false
27
+ t.timestamps
28
+ end
29
+
30
+ c.create_table :children, :force => true do |t|
31
+ t.string :name
32
+ t.references :parent
33
+ t.boolean :alive, :default => false
34
+ t.timestamps
35
+ end
36
+
37
+ c.create_table :grand_children, :force => true do |t|
38
+ t.string :name
39
+ t.references :child
40
+ t.boolean :alive, :default => false
41
+ t.timestamps
42
+ end
43
+ end
44
+
45
+ def load_fixtures
46
+ a = Parent.create(:name => 'a', :alive => true)
47
+
48
+ a_a = a.children.create(:name => 'aa', :alive => true)
49
+ a_a_a = a_a.grand_children.create(:name => 'aaa', :alive => true)
50
+ a_a_b = a_a.grand_children.create(:name => 'aab', :alive => false)
51
+
52
+ a_b = a.children.create(:name => 'ab', :alive => false)
53
+ a_b_a = a_b.grand_children.create(:name => 'aba', :alive => true)
54
+ a_b_b = a_b.grand_children.create(:name => 'abb', :alive => false)
55
+ end
56
+
57
+ setup_database
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kristopher-scoped-associations
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - Kristopher Chambers
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-12-07 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: echoe
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: "0"
23
+ version:
24
+ description: DRY up your associations with named_scope conditions!
25
+ email: kristopher.chambers@gmail.com
26
+ executables: []
27
+
28
+ extensions: []
29
+
30
+ extra_rdoc_files:
31
+ - CHANGELOG
32
+ - lib/scope_reflection.rb
33
+ - lib/scoped_associations.rb
34
+ - LICENSE
35
+ - README.rdoc
36
+ - TODO
37
+ files:
38
+ - CHANGELOG
39
+ - init.rb
40
+ - lib/scope_reflection.rb
41
+ - lib/scoped_associations.rb
42
+ - LICENSE
43
+ - Manifest
44
+ - Rakefile
45
+ - README.rdoc
46
+ - scoped-associations.gemspec
47
+ - spec/models.rb
48
+ - spec/scoped_associations_spec.rb
49
+ - spec/spec_helper.rb
50
+ - TODO
51
+ has_rdoc: true
52
+ homepage: ""
53
+ post_install_message:
54
+ rdoc_options:
55
+ - --line-numbers
56
+ - --inline-source
57
+ - --title
58
+ - Scoped-associations
59
+ - --main
60
+ - README.rdoc
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: "0"
68
+ version:
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: "1.2"
74
+ version:
75
+ requirements: []
76
+
77
+ rubyforge_project: scoped-associations
78
+ rubygems_version: 1.2.0
79
+ signing_key:
80
+ specification_version: 2
81
+ summary: DRY up your associations with named_scope conditions!
82
+ test_files: []
83
+