moro-scope_do 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/ChangeLog ADDED
@@ -0,0 +1,8 @@
1
+ == 0.1.1 / 2009-02-18
2
+ * [FEATURE] add free_or_accessible scope
3
+ * [BUG] fixed hard-coded blog_id in User#accessible?
4
+
5
+ == 0.1.0 / 2009-01-09
6
+
7
+ * initial release
8
+
data/README.rdoc ADDED
@@ -0,0 +1,103 @@
1
+
2
+ = scope_do
3
+
4
+ named_scope utilities.
5
+
6
+ == Description
7
+
8
+ scope_do is a tiny utilities to define useful named_scope.
9
+ scope_do provides
10
+
11
+ - named_acl : enable User - Group - Target style access control list.
12
+ - chained_scope : enable defined named_scope method chain.
13
+ - has_children : define scope to load child records
14
+
15
+ == Installation
16
+
17
+ === Archive Installation
18
+
19
+ rake install
20
+
21
+ === Gem Installation
22
+
23
+ gem install scope_do
24
+
25
+
26
+ == Features/Problems
27
+ === named_acl
28
+ named_acl provides Target.accessible_by(users) scope that load target model accessible by the user.
29
+ And also provides User#accessible_#{target} methods which call Target.accessible_by(self).
30
+
31
+ class User < ActiveRecord::Base
32
+ scope_do :named_acl
33
+ named_acl :blogs
34
+ end
35
+
36
+ now you write below in controller.
37
+
38
+ class BlogsController < ApplicationCotnroller
39
+ def index
40
+ @blogs = current_user.accessible_blogs
41
+ # or method chain
42
+ # @blogs = current_user.accessible_blogs.find_by_keyword(params[:keyword])
43
+ end
44
+ end
45
+
46
+ === chained_scope
47
+ chained_scope provides named_scope macro that skip condition when all args are blank.
48
+ and it enable named_scope method-chainable.
49
+
50
+ class Blog < ActiveRecord::Base
51
+ scope_do :chained_scope
52
+ named_scope :title_like, proc{|part|
53
+ {:conditions => ["#{quoted_table_name}.title LIKE ?", "%#{part}%"]}
54
+ }
55
+ ...and more...
56
+
57
+ chainable_scope :title_like
58
+ end
59
+
60
+ without chained_scope, you must write below (or reject blank in each scope)
61
+
62
+ def index # In some controller
63
+ @blogs = Blog.some_scope
64
+ @blogs = @blogs.title_like(params[:q]) unless params[:q].blank?
65
+ @blogs = @blogs.month_in(params[:month]) unless params[:month].blank?
66
+ ...
67
+ @blogs = scope.find(:all, ...)
68
+ end
69
+
70
+ chained_scope enable below style
71
+
72
+ def index # In some controller
73
+ @blogs = Blog.some_scope.
74
+ title_like(params[:q]).
75
+ month_in(params[:month]).
76
+ find(:all, ...)
77
+ end
78
+
79
+ === has_children
80
+ define scope that have children records.
81
+
82
+ class Blog < ActiveRecord::Base
83
+ scope_do :has_children
84
+ has_many :entries
85
+ has_children :entries
86
+ end
87
+
88
+ add "has_entries" scope that have one or more entries.
89
+
90
+ Blog.has_entries.all?{|b| not b.entries.blank? } # => true
91
+
92
+ "has_entires" also accept children numbers
93
+
94
+ Blog.has_entries(2).all?{|b| b.entries.size >= 2 } # => true
95
+
96
+ == Synopsis
97
+ see spec/**/*_spec.rb
98
+
99
+ == Copyright
100
+
101
+ Author:: MOROHASHI Kyosuke <moronatural@>gmail.com
102
+ Copyright:: Copyright (c) 2009 MOROHASHI Kyosuke
103
+ License:: MIT
data/Rakefile ADDED
@@ -0,0 +1,112 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/clean'
4
+ require 'rake/testtask'
5
+ require 'rake/packagetask'
6
+ require 'rake/gempackagetask'
7
+ require 'rake/rdoctask'
8
+ require 'rake/contrib/rubyforgepublisher'
9
+ require 'rake/contrib/sshpublisher'
10
+ require 'fileutils'
11
+
12
+ $:.unshift "lib"
13
+ require 'scope_do'
14
+
15
+ require 'spec/rake/spectask'
16
+ include FileUtils
17
+
18
+ NAME = "scope_do"
19
+ AUTHOR = "MOROHASHI Kyosuke"
20
+ EMAIL = "moronatural@gmail.com"
21
+ DESCRIPTION = "named_scope utilities."
22
+ HOMEPATH = "http://github.com/moro/scope_do/tree/master"
23
+ BIN_FILES = %w( )
24
+
25
+ VERS = ScopeDo::VERSION
26
+ REV = File.read(".svn/entries")[/committed-rev="(d+)"/, 1] rescue nil
27
+ CLEAN.include ['**/.*.sw?', '*.gem', '.config']
28
+ RDOC_OPTS = [
29
+ '--title', "#{NAME} documentation",
30
+ "--charset", "utf-8",
31
+ "--opname", "index.html",
32
+ "--line-numbers",
33
+ "--main", "README.rdoc",
34
+ "--inline-source",
35
+ ]
36
+
37
+ task :default => [:test]
38
+ task :package => [:clean]
39
+
40
+ desc "Run all specs in spec directory"
41
+ Spec::Rake::SpecTask.new(:spec) do |t|
42
+ t.spec_opts = %w[--colour --format progress --loadby --reverse]
43
+ t.spec_files = FileList['spec/**/*_spec.rb']
44
+ end
45
+
46
+ spec = Gem::Specification.new do |s|
47
+ s.name = NAME
48
+ s.version = VERS
49
+ s.platform = Gem::Platform::RUBY
50
+ s.has_rdoc = true
51
+ s.extra_rdoc_files = ["README.rdoc", "ChangeLog"]
52
+ s.rdoc_options += RDOC_OPTS + ['--exclude', '^(examples|extras)/']
53
+ s.summary = DESCRIPTION
54
+ s.description = DESCRIPTION
55
+ s.author = AUTHOR
56
+ s.email = EMAIL
57
+ s.homepage = HOMEPATH
58
+ s.executables = BIN_FILES
59
+ s.bindir = "bin" unless BIN_FILES.empty?
60
+ s.require_path = "lib"
61
+ s.test_files = Dir["spec/**/*_spec.rb"]
62
+
63
+ s.files = %w(README.rdoc ChangeLog Rakefile) +
64
+ Dir.glob("{bin,doc,test,lib,templates,generator,extras,website,script}/**/*") +
65
+ Dir.glob("spec/**/*.rb") +
66
+ Dir.glob("ext/**/*.{h,c,rb}") +
67
+ Dir.glob("examples/**/*.rb") +
68
+ Dir.glob("tools/*.rb") +
69
+ Dir.glob("rails/*.rb")
70
+
71
+ s.extensions = FileList["ext/**/extconf.rb"].to_a
72
+ end
73
+
74
+ Rake::GemPackageTask.new(spec) do |p|
75
+ p.need_tar = true
76
+ p.gem_spec = spec
77
+ end
78
+
79
+ task :install do
80
+ name = "#{NAME}-#{VERS}.gem"
81
+ sh %{rake package}
82
+ sh %{sudo gem install pkg/#{name}}
83
+ end
84
+
85
+ task :uninstall => [:clean] do
86
+ sh %{sudo gem uninstall #{NAME}}
87
+ end
88
+
89
+
90
+ Rake::RDocTask.new do |rdoc|
91
+ rdoc.rdoc_dir = 'html'
92
+ rdoc.options += RDOC_OPTS
93
+ rdoc.template = "resh"
94
+ #rdoc.template = "#{ENV['template']}.rb" if ENV['template']
95
+ if ENV['DOC_FILES']
96
+ rdoc.rdoc_files.include(ENV['DOC_FILES'].split(/,\s*/))
97
+ else
98
+ rdoc.rdoc_files.include('README.rdoc', 'ChangeLog')
99
+ rdoc.rdoc_files.include('lib/**/*.rb')
100
+ rdoc.rdoc_files.include('ext/**/*.c')
101
+ end
102
+ end
103
+
104
+ desc 'Show information about the gem.'
105
+ task :debug_gem do
106
+ puts spec.to_ruby
107
+ end
108
+
109
+ desc 'Update gem spec'
110
+ task :gemspec do
111
+ open("#{NAME}.gemspec", 'w').write spec.to_ruby
112
+ end
data/lib/scope_do.rb ADDED
@@ -0,0 +1,14 @@
1
+ require 'scope_do/named_acl'
2
+ require 'scope_do/chained_scope'
3
+
4
+ module ScopeDo
5
+ VERSION = '0.1.1'
6
+ module Adapter
7
+ def scope_do *functions
8
+ functions.each do |function|
9
+ module_name = function.to_s.camelize
10
+ include ScopeDo.const_get(module_name)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,35 @@
1
+ module ScopeDo
2
+ module ChainedScope
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+
9
+ # Make specified named_scope(s) chainable
10
+ #
11
+ # options
12
+ #
13
+ # +halt+:: add always false condition (WHERE 1 = 2)
14
+ def chainable_scope(*scope_names)
15
+ opts = scope_names.extract_options!
16
+ opts.symbolize_keys!
17
+
18
+ scope_names.each do |scope_name|
19
+ if defined_scope = scopes[scope_name]
20
+ scopes[scope_name] = proc{|parent_scope, *args|
21
+ args.flatten.any?{|x| !x.blank? } ?
22
+ defined_scope.call(parent_scope, *args) : parent_scope.scoped(chain_condition(opts))
23
+ }
24
+ end
25
+ end
26
+ end
27
+
28
+ private
29
+ def chain_condition(options) # nodoc
30
+ options[:halt] ? {:conditions => "1 = 2"} : {}
31
+ end
32
+ end
33
+ end
34
+ end
35
+
@@ -0,0 +1,56 @@
1
+ # vim:set fileencoding=utf-8 filetype=ruby
2
+
3
+ module ScopeDo
4
+ module HasChildren
5
+ def self.included(base)
6
+ base.extend ClassMethods
7
+ end
8
+ end
9
+
10
+ class QueryBuilder
11
+ def self.has_children_condition(n, q)
12
+ select_cols, rest = q
13
+ if n
14
+ "#{n} <= (SELECT COUNT(#{select_cols}) #{rest})"
15
+ else
16
+ "EXISTS(SELECT #{select_cols} #{rest})"
17
+ end
18
+ end
19
+
20
+ def initialize(base, association)
21
+ @base = base
22
+ @association = association
23
+ end
24
+
25
+ def has_children_query_parts
26
+ if through = @association.through_reflection
27
+ query_parts(@base, through)
28
+ else
29
+ query_parts(@base, @association)
30
+ end
31
+ end
32
+
33
+ private
34
+ def query_parts(parent, association)
35
+ child_t = association.quoted_table_name
36
+ parent_t = parent.quoted_table_name
37
+ [
38
+ "#{child_t}.#{association.primary_key_name}",
39
+ "FROM #{child_t} WHERE #{parent_t}.#{parent.primary_key} = #{child_t}.#{association.primary_key_name}"
40
+ ]
41
+ end
42
+ end
43
+
44
+ module ClassMethods
45
+ def has_children(target)
46
+ association = reflections[target]
47
+ builder = QueryBuilder.new(self, association)
48
+ qs = builder.has_children_query_parts
49
+
50
+ named_scope "has_#{target}", proc{|*n|
51
+ {:conditions => QueryBuilder.has_children_condition(n.shift, qs)}
52
+ }
53
+ end
54
+ end
55
+ end
56
+
@@ -0,0 +1,61 @@
1
+ require 'scope_do/named_acl/builder'
2
+
3
+ module ScopeDo
4
+ module NamedAcl
5
+ def self.included(base)
6
+ base.extend ClassMethods
7
+ base.cattr_accessor :acl_query_builder
8
+ end
9
+
10
+ module ClassMethods
11
+ def named_acl(target, options={})
12
+ t_klass = target.to_s.classify.constantize
13
+ self.acl_query_builder = Builder.new(self, target, options)
14
+
15
+ define_accessible_scope(t_klass, acl_query_builder.query)
16
+ class_eval(<<-EOS)
17
+ def accessible_#{target}; #{t_klass.name}.accessed_by(self) ; end
18
+ EOS
19
+
20
+ if free = t_klass.scopes[:free]
21
+ define_free_or_accessible_scope(t_klass, free.call(t_klass), acl_query_builder.query)
22
+ class_eval(<<-EOS)
23
+ def free_or_accessible_#{target}; #{t_klass.name}.free_or_accessed_by(self); end
24
+ EOS
25
+ end
26
+ end
27
+
28
+ private
29
+ def define_accessible_scope(klass, query)
30
+ klass.named_scope :accessed_by, proc{|*users|
31
+ user_ids = users.map(&:id)
32
+ {:conditions => ["#{klass.quoted_table_name}.id IN (#{query})", {:user_ids => user_ids}]}
33
+ }
34
+ end
35
+
36
+ def define_free_or_accessible_scope(klass, free_scope, query)
37
+ free = merge_conditions( free_scope.proxy_options[:conditions] )
38
+
39
+ klass.named_scope :free_or_accessed_by, proc{|*users|
40
+ accessible = merge_conditions( klass.accessed_by(*users).proxy_options[:conditions] )
41
+ {:conditions => "(#{free}) OR (#{accessible})"}
42
+ }
43
+ end
44
+ end
45
+
46
+ def accessible?(record)
47
+ @accessibilities ||= load_accessibilities
48
+
49
+ fk = acl_query_builder.accessibility_target_id(false)
50
+ @accessibilities.any?{|a| a[fk] == record.id }
51
+ end
52
+
53
+ private
54
+ def load_accessibilities
55
+ q = acl_query_builder
56
+ q.accessibility_klass.find(:all, :joins => "JOIN #{q.join_on_group_id}",
57
+ :conditions => ["#{q.where}", {q.label.to_sym=> self}])
58
+ end
59
+ end
60
+ end
61
+
@@ -0,0 +1,49 @@
1
+ module ScopeDo
2
+ module NamedAcl
3
+ class Builder
4
+ attr_reader :label
5
+
6
+ def initialize(user_klass, target, options={})
7
+ options = {:via => :groups, :label => "user_ids"}.merge(options)
8
+ @label = options[:label]
9
+
10
+ @user = user_klass
11
+ @group = @user.reflections[options[:via]]
12
+ @membership = @user.reflections[options[:via]].through_reflection
13
+
14
+ @target = @group.klass.reflections[target]
15
+ @accessibility = @target.through_reflection
16
+ end
17
+
18
+ def accessibility_klass
19
+ @accessibility.klass
20
+ end
21
+
22
+ def query
23
+ "SELECT #{accessibility_target_id} FROM #{from} JOIN #{join_on_group_id} WHERE #{where}"
24
+ end
25
+
26
+ def accessibility_target_id(with_table_name = true)
27
+ if with_table_name
28
+ "#{@accessibility.quoted_table_name}.#{@target.association_foreign_key}"
29
+ else
30
+ @target.association_foreign_key
31
+ end
32
+ end
33
+
34
+ def where
35
+ "#{@membership.quoted_table_name}.#{@membership.primary_key_name} IN (:#{@label})"
36
+ end
37
+
38
+ def from
39
+ @accessibility.quoted_table_name
40
+ end
41
+
42
+ def join_on_group_id
43
+ "#{@membership.quoted_table_name} ON " +
44
+ "#{@membership.quoted_table_name}.#{@group.association_foreign_key} = " +
45
+ "#{@accessibility.quoted_table_name}.#{@accessibility.primary_key_name}"
46
+ end
47
+ end
48
+ end
49
+ end
data/rails/init.rb ADDED
@@ -0,0 +1,5 @@
1
+ #require File.expand_path("..", File.dirname(__FILE__))
2
+ require 'scope_do'
3
+
4
+ ActiveRecord::Base.extend(ScopeDo::Adapter)
5
+
@@ -0,0 +1,47 @@
1
+ require 'rubygems'
2
+ require 'active_record'
3
+ require 'active_record/fixtures'
4
+
5
+ RAILS_ENV = "test"
6
+
7
+ module RecrodExtention
8
+ module TestUtil
9
+ MEMORY_DB_OPTIONS = {
10
+ :adapter => "sqlite3",
11
+ :database => ":memory:",
12
+ }.with_indifferent_access.freeze
13
+
14
+ def setup
15
+ memory_db!
16
+ log_or_silent!
17
+ ActiveRecord::Base.extend(ClassMethods)
18
+ end
19
+
20
+ def memory_db!(options = {})
21
+ ActiveRecord::Base.configurations = {"test" => MEMORY_DB_OPTIONS.merge(options) }
22
+ ActiveRecord::Base.establish_connection(:test)
23
+ end
24
+
25
+ def log_or_silent!(dir = "log")
26
+ ActiveRecord::Base.logger = Logger.new(dir && File.directory?(dir) ? "#{dir}/#{RAILS_ENV}.log" : "/dev/null")
27
+ end
28
+
29
+ def next_schema_version
30
+ begin
31
+ ActiveRecord::Base.connection.select_one("SELECT version FROM schema_migrations")["version"].succ
32
+ rescue ActiveRecord::StatementInvalid
33
+ "1"
34
+ end
35
+ end
36
+ module_function :setup, :memory_db!, :log_or_silent!, :next_schema_version
37
+
38
+ module ClassMethods
39
+ def define_table(table_name = self.name.tableize, &migration)
40
+ ActiveRecord::Schema.define(:version => TestUtil.next_schema_version) do
41
+ create_table(table_name, &migration)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env ruby
2
+ # vim:set fileencoding=utf-8 filetype=ruby
3
+ # $KCODE = 'u'
4
+
5
+ require File.expand_path("../spec_helper", File.dirname(__FILE__))
6
+ require 'scope_do/chained_scope'
7
+
8
+ describe ScopeDo::ChainedScope do
9
+ before(:all) do
10
+ ::User.class_eval do
11
+ scope_do :chained_scope
12
+ named_scope :name_like, proc{|part|
13
+ {:conditions => ["#{quoted_table_name}.name LIKE ?", "%#{part}%"]}
14
+ }
15
+
16
+ named_scope :name_starts, proc{|part|
17
+ {:conditions => ["#{quoted_table_name}.name LIKE ?", "#{part}%"]}
18
+ }
19
+
20
+ chainable_scope :name_like
21
+ chainable_scope :name_starts, :halt => true
22
+ end
23
+
24
+ User.delete_all
25
+ u = Factory(:user)
26
+ Factory(:user, :name => "bob")
27
+ end
28
+
29
+ it "name_like('ali') should == [User.find_by_name('alice')]" do
30
+ User.name_like('ali').should == [User.find_by_name('alice')]
31
+ end
32
+
33
+ it "blank paramters (nil, [], '') on name_like should == User.all" do
34
+ [nil, [], ''].all?{|param| User.name_like(param) == User.all }.should be_true
35
+ end
36
+
37
+ it "blank paramters (nil, [], '') on name_starts should == []" do
38
+ [nil, [], ''].all?{|param| User.name_starts(param) == [] }.should be_true
39
+ end
40
+ end
41
+
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env ruby
2
+ # vim:set fileencoding=utf-8 filetype=ruby
3
+ # $KCODE = 'u'
4
+
5
+ require File.expand_path("../spec_helper", File.dirname(__FILE__))
6
+ require 'scope_do/has_children'
7
+
8
+ describe ScopeDo::HasChildren do
9
+ before(:all) do
10
+ ::Blog.class_eval do
11
+ scope_do :has_children
12
+ has_children :entries
13
+ end
14
+ end
15
+
16
+ before do
17
+ [Blog, Entry, Group, User].each(&:delete_all)
18
+ @blog = Factory(:blog)
19
+ @blog.entries << (@entry = Factory(:entry))
20
+
21
+ @empty = Factory(:blog)
22
+ end
23
+
24
+ it do
25
+ Blog.first.should have(1).entries
26
+ end
27
+
28
+ it do
29
+ Blog.all.should == [@blog, @empty]
30
+ end
31
+
32
+ it ".has_entries" do
33
+ Blog.has_entries.should == [@blog]
34
+ end
35
+
36
+ describe "specify children numbers" do
37
+ before do
38
+ @three_children = Factory(:blog)
39
+ @three_children.entries = (0..2).map{ Factory(:entry) }
40
+ end
41
+
42
+ it ".has_entries(3)" do
43
+ Blog.has_entries(3).should == [@three_children]
44
+ end
45
+
46
+ it ".has_entries(4) should be_empty" do
47
+ Blog.has_entries(4).should be_empty
48
+ end
49
+ end
50
+
51
+ describe "Group / has_many :through children" do
52
+ before(:all) do
53
+ Group.class_eval do
54
+ scope_do :has_children
55
+ has_children :users
56
+ end
57
+ end
58
+ before do
59
+ @group = Group.first
60
+ @group.users = [Factory(:user)]
61
+ @another_group = Factory(:group)
62
+ end
63
+
64
+ it ".has_users" do
65
+ Group.has_users.should == [@group]
66
+ end
67
+
68
+ describe "specify n" do
69
+ before do
70
+ @group.users << Factory(:user, :name =>"bob")
71
+ end
72
+
73
+ it ".has_users(2).should == [@group]" do
74
+ Group.has_users(2).should == [@group]
75
+ end
76
+
77
+ it ".has_users(5).should be_empty" do
78
+ Group.has_users(5).should be_empty
79
+ end
80
+ end
81
+ end
82
+ end
83
+
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+ # vim:set fileencoding=utf-8 filetype=ruby
3
+ # $KCODE = 'u'
4
+
5
+ require File.expand_path("../../spec_helper", File.dirname(__FILE__))
6
+ require 'scope_do/named_acl/builder'
7
+
8
+ describe ScopeDo::NamedAcl::Builder do
9
+ before do
10
+ @builder = ScopeDo::NamedAcl::Builder.new(User, :blogs, :via => :groups)
11
+ end
12
+
13
+ it do
14
+ @builder.should_not be_nil
15
+ end
16
+
17
+ it "#from" do
18
+ @builder.from.should == Accessibility.quoted_table_name
19
+ end
20
+
21
+ it "#join_on_group_id" do
22
+ @builder.join_on_group_id.should == "#{Membership.quoted_table_name} ON #{Membership.quoted_table_name}.group_id = #{Accessibility.quoted_table_name}.group_id"
23
+ end
24
+ end
25
+
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env ruby
2
+ # vim:set fileencoding=utf-8 filetype=ruby
3
+ # $KCODE = 'u'
4
+
5
+ require File.expand_path("../spec_helper", File.dirname(__FILE__))
6
+ require 'scope_do/named_acl'
7
+
8
+ describe ScopeDo::NamedAcl do
9
+ before(:all) do
10
+ ::Blog.class_eval do
11
+ named_scope :free, :conditions => ["public = ?", true]
12
+ end
13
+ ::User.class_eval do
14
+ scope_do :named_acl
15
+ named_acl :blogs
16
+ end
17
+
18
+ [Blog, User].each(&:delete_all)
19
+ u = Factory(:user)
20
+ b = Factory(:blog)
21
+ b.accessibilities.map(&:group).first.users << u
22
+ end
23
+
24
+ before do
25
+ @alice = User.find_by_name("alice")
26
+ @bob = Factory(:user, :name => "bob")
27
+ @blog = Blog.find(:first)
28
+ end
29
+
30
+ it do
31
+ Blog.should be_respond_to(:accessed_by)
32
+ end
33
+
34
+ it "alice.accessible_blogs should include @blog" do
35
+ @alice.accessible_blogs.should include(@blog)
36
+ end
37
+
38
+ it "alice should be accessible @blog" do
39
+ @alice.should be_accessible(@blog)
40
+ end
41
+
42
+ it "bob.accessible_blogs should not include @blog" do
43
+ @bob.accessible_blogs.should_not include(@blog)
44
+ end
45
+
46
+ it "bob.free_or_accessible_blogs should not include @blog" do
47
+ @bob.free_or_accessible_blogs.should include(@blog)
48
+ end
49
+
50
+ it "bob should not be accessible @blog" do
51
+ @bob.should_not be_accessible(@blog)
52
+ end
53
+ end
54
+
@@ -0,0 +1,89 @@
1
+ require 'rubygems'
2
+ require 'active_record'
3
+ require 'active_record/fixtures'
4
+ require 'factory_girl'
5
+
6
+ require File.expand_path("record_extention_test_util", File.dirname(__FILE__))
7
+ RecrodExtention::TestUtil.setup
8
+
9
+ class User < ActiveRecord::Base
10
+ define_table do |t|
11
+ t.string "name"
12
+ t.timestamps
13
+ end
14
+ has_many :memberships
15
+ has_many :groups, :through => :memberships
16
+ end
17
+
18
+ class Membership < ActiveRecord::Base
19
+ define_table do |t|
20
+ t.belongs_to :user
21
+ t.belongs_to :group
22
+ end
23
+ belongs_to :user
24
+ belongs_to :group
25
+ end
26
+
27
+ class Group < ActiveRecord::Base
28
+ define_table do |t|
29
+ t.string :name
30
+ end
31
+ has_many :memberships
32
+ has_many :users, :through => :memberships
33
+
34
+ has_many :accessibilities
35
+ has_many :blogs, :through => :accessibilities
36
+ end
37
+
38
+ class Accessibility < ActiveRecord::Base
39
+ define_table do |t|
40
+ t.belongs_to :blog
41
+ t.belongs_to :group
42
+ end
43
+ belongs_to :blog
44
+ belongs_to :group
45
+ end
46
+
47
+ class Blog < ActiveRecord::Base
48
+ define_table do |t|
49
+ t.string "title"
50
+ t.boolean "public"
51
+ t.timestamps
52
+ end
53
+ has_many :accessibilities
54
+ has_many :entries
55
+ end
56
+
57
+ class Entry < ActiveRecord::Base
58
+ define_table do |t|
59
+ t.string "title"
60
+ t.text "body"
61
+ t.belongs_to "blog"
62
+ end
63
+
64
+ belongs_to :blog
65
+ end
66
+
67
+ Factory.define(:group) do |g|
68
+ g.name "collaborators"
69
+ end
70
+
71
+ Factory.define(:accessibility) do |a|
72
+ a.group{|g| g.association(:group) }
73
+ end
74
+
75
+ Factory.define(:blog) do |b|
76
+ b.title "My Blog"
77
+ b.public true
78
+ b.accessibilities{|as| [Factory.build(:accessibility)] }
79
+ end
80
+
81
+ Factory.define(:user) do |u|
82
+ u.name "alice"
83
+ end
84
+
85
+ Factory.define(:entry) do |e|
86
+ e.title "My Entry"
87
+ e.body "!!! Body of the entry. !!!"
88
+ end
89
+
@@ -0,0 +1,39 @@
1
+ # ---- requirements
2
+ $KCODE = 'u' #activate regex unicode
3
+ require 'rubygems'
4
+ require 'spec'
5
+ $LOAD_PATH << File.expand_path("..", File.dirname(__FILE__))
6
+ $LOAD_PATH << File.expand_path("../lib", File.dirname(__FILE__))
7
+
8
+ # ---- bugfix
9
+ #`exit?': undefined method `run?' for Test::Unit:Module (NoMethodError)
10
+ #can be solved with require test/unit but this will result in extra test-output
11
+ unless defined? Test::Unit
12
+ module Test
13
+ module Unit
14
+ def self.run?
15
+ true
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ # ---- load active record
22
+ #gem 'activerecord', '2.0.2'
23
+ if ENV["AR"]
24
+ gem 'activerecord', ENV["AR"]
25
+ $stderr.puts("Using ActiveRecord #{ENV["AR"]}")
26
+ end
27
+ require 'active_record'
28
+ require "rails/init"
29
+
30
+ load File.expand_path("setup_test_model.rb", File.dirname(__FILE__))
31
+
32
+ # ---- fixtures
33
+ Spec::Example::ExampleGroupMethods.module_eval do
34
+ def fixtures(*tables)
35
+ dir = File.expand_path("fixtures", File.dirname(__FILE__))
36
+ tables.each{|table| Fixtures.create_fixtures(dir, table.to_s) }
37
+ end
38
+ end
39
+
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: moro-scope_do
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - MOROHASHI Kyosuke
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-02-18 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: named_scope utilities.
17
+ email: moronatural@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.rdoc
24
+ - ChangeLog
25
+ files:
26
+ - README.rdoc
27
+ - ChangeLog
28
+ - Rakefile
29
+ - lib/scope_do
30
+ - lib/scope_do/chained_scope.rb
31
+ - lib/scope_do/has_children.rb
32
+ - lib/scope_do/named_acl
33
+ - lib/scope_do/named_acl/builder.rb
34
+ - lib/scope_do/named_acl.rb
35
+ - lib/scope_do.rb
36
+ - spec/record_extention_test_util.rb
37
+ - spec/scope_do/chained_scope_spec.rb
38
+ - spec/scope_do/has_children_spec.rb
39
+ - spec/scope_do/named_acl/builder_spec.rb
40
+ - spec/scope_do/named_acl_spec.rb
41
+ - spec/setup_test_model.rb
42
+ - spec/spec_helper.rb
43
+ - rails/init.rb
44
+ has_rdoc: true
45
+ homepage: http://github.com/moro/scope_do/tree/master
46
+ post_install_message:
47
+ rdoc_options:
48
+ - --title
49
+ - scope_do documentation
50
+ - --charset
51
+ - utf-8
52
+ - --opname
53
+ - index.html
54
+ - --line-numbers
55
+ - --main
56
+ - README.rdoc
57
+ - --inline-source
58
+ - --exclude
59
+ - ^(examples|extras)/
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: "0"
67
+ version:
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: "0"
73
+ version:
74
+ requirements: []
75
+
76
+ rubyforge_project:
77
+ rubygems_version: 1.2.0
78
+ signing_key:
79
+ specification_version: 2
80
+ summary: named_scope utilities.
81
+ test_files:
82
+ - spec/scope_do/chained_scope_spec.rb
83
+ - spec/scope_do/has_children_spec.rb
84
+ - spec/scope_do/named_acl/builder_spec.rb
85
+ - spec/scope_do/named_acl_spec.rb