kristopher-scoped-associations 0.0.3

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