moro-scope_do 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/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