radiant-vhost-extension 2.1.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitmodules CHANGED
@@ -1,3 +0,0 @@
1
- [submodule "vendor/scoped_access"]
2
- path = vendor/scoped_access
3
- url = git://github.com/maiha/scoped_access.git
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.1.0
1
+ 2.2.0
@@ -0,0 +1,150 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{radiant-vhost-extension}
8
+ s.version = "2.2.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Jason Garber", "Kaleb Walton", "Jim Gay"]
12
+ s.date = %q{2010-06-13}
13
+ s.description = %q{Host more than one site in a single instance of Radiant.}
14
+ s.email = %q{jim@saturnflyer.com}
15
+ s.extra_rdoc_files = [
16
+ "README"
17
+ ]
18
+ s.files = [
19
+ ".gitmodules",
20
+ "README",
21
+ "Rakefile",
22
+ "VERSION",
23
+ "app/controllers/admin/sites_controller.rb",
24
+ "app/models/site.rb",
25
+ "app/models/site_association_observer.rb",
26
+ "app/views/admin/sites/_form.html.haml",
27
+ "app/views/admin/sites/edit.html.haml",
28
+ "app/views/admin/sites/index.html.haml",
29
+ "app/views/admin/sites/new.html.haml",
30
+ "app/views/admin/sites/remove.html.haml",
31
+ "app/views/admin/users/_edit_sites.html.haml",
32
+ "app/views/admin/users/_site_admin_roles.html.haml",
33
+ "app/views/admin/users/_sites_td.html.haml",
34
+ "app/views/admin/users/_sites_th.html.haml",
35
+ "config/routes.rb",
36
+ "db/migrate/001_create_sites.rb",
37
+ "db/migrate/002_add_sites_users.rb",
38
+ "db/migrate/003_replace_snippet_name_unique_index.rb",
39
+ "db/migrate/004_add_site_admin_to_users.rb",
40
+ "db/templates/empty.yml",
41
+ "db/templates/simple-blog.yml",
42
+ "lib/bootstrap_with_site_id.rb",
43
+ "lib/radiant-vhost-extension.rb",
44
+ "lib/site_scope.rb",
45
+ "lib/tasks/add_site_columns.rb",
46
+ "lib/tasks/vhost_extension_tasks.rake",
47
+ "lib/vhost/admin_users_controller_extensions.rb",
48
+ "lib/vhost/admin_users_helper_extensions.rb",
49
+ "lib/vhost/application_controller_extensions.rb",
50
+ "lib/vhost/application_helper_extensions.rb",
51
+ "lib/vhost/controller_access_extensions.rb",
52
+ "lib/vhost/pages_controller_extensions.rb",
53
+ "lib/vhost/radiant_cache_extensions.rb",
54
+ "lib/vhost/site_scoped_model_extensions.rb",
55
+ "lib/vhost_default_config.yml",
56
+ "radiant-vhost-extension.gemspec",
57
+ "spec/controllers/admin/pages_controller_spec.rb",
58
+ "spec/controllers/admin/sites_controller_spec.rb",
59
+ "spec/controllers/site_controller_spec.rb",
60
+ "spec/datasets/site_home_pages_dataset.rb",
61
+ "spec/datasets/site_pages_dataset.rb",
62
+ "spec/datasets/site_users_dataset.rb",
63
+ "spec/datasets/sites_dataset.rb",
64
+ "spec/datasets/sites_site_users_and_site_pages_dataset.rb",
65
+ "spec/datasets/sites_site_users_dataset.rb",
66
+ "spec/fixtures/page_parts.yml",
67
+ "spec/fixtures/pages.yml",
68
+ "spec/fixtures/sites.yml",
69
+ "spec/fixtures/sites_users.yml",
70
+ "spec/fixtures/users.yml",
71
+ "spec/models/page_spec.rb",
72
+ "spec/models/site_spec.rb",
73
+ "spec/models/user_spec.rb",
74
+ "spec/spec.opts",
75
+ "spec/spec_helper.rb",
76
+ "test/fixtures/page_parts.yml",
77
+ "test/fixtures/pages.yml",
78
+ "test/fixtures/sites.yml",
79
+ "test/fixtures/sites_users.yml",
80
+ "test/fixtures/users.yml",
81
+ "test/functional/admin/pages_controller_test.rb",
82
+ "test/functional/admin/site_controller_test.rb",
83
+ "test/functional/vhost_extension_test.rb",
84
+ "test/helpers/page_part_test_helper.rb",
85
+ "test/test_helper.rb",
86
+ "test/unit/site_test.rb",
87
+ "vendor/scoped_access/README",
88
+ "vendor/scoped_access/Rakefile",
89
+ "vendor/scoped_access/init.rb",
90
+ "vendor/scoped_access/install.rb",
91
+ "vendor/scoped_access/lib/scoped_access.rb",
92
+ "vendor/scoped_access/scoped_access.gemspec",
93
+ "vendor/scoped_access/tasks/scoped_access_tasks.rake",
94
+ "vendor/scoped_access/test/database.yml",
95
+ "vendor/scoped_access/test/filter_test.rb",
96
+ "vendor/scoped_access/test/fixtures/favorite.rb",
97
+ "vendor/scoped_access/test/fixtures/favorites.yml",
98
+ "vendor/scoped_access/test/fixtures/group.rb",
99
+ "vendor/scoped_access/test/fixtures/groups.yml",
100
+ "vendor/scoped_access/test/fixtures/member.rb",
101
+ "vendor/scoped_access/test/fixtures/members.yml",
102
+ "vendor/scoped_access/test/fixtures/song.rb",
103
+ "vendor/scoped_access/test/method_scoping_test.rb",
104
+ "vendor/scoped_access/test/schema.rb",
105
+ "vendor/scoped_access/test/scoped_access_test.rb",
106
+ "vendor/scoped_access/test/sql_condition_test.rb",
107
+ "vendor/scoped_access/test/test_helper.rb",
108
+ "vhost_extension.rb"
109
+ ]
110
+ s.homepage = %q{http://github.com/saturnflyer/radiant-vhost-extension}
111
+ s.rdoc_options = ["--charset=UTF-8"]
112
+ s.require_paths = ["lib"]
113
+ s.rubygems_version = %q{1.3.7}
114
+ s.summary = %q{Vhost Extension for Radiant CMS}
115
+ s.test_files = [
116
+ "spec/controllers/admin/pages_controller_spec.rb",
117
+ "spec/controllers/admin/sites_controller_spec.rb",
118
+ "spec/controllers/site_controller_spec.rb",
119
+ "spec/datasets/site_home_pages_dataset.rb",
120
+ "spec/datasets/site_pages_dataset.rb",
121
+ "spec/datasets/site_users_dataset.rb",
122
+ "spec/datasets/sites_dataset.rb",
123
+ "spec/datasets/sites_site_users_and_site_pages_dataset.rb",
124
+ "spec/datasets/sites_site_users_dataset.rb",
125
+ "spec/models/page_spec.rb",
126
+ "spec/models/site_spec.rb",
127
+ "spec/models/user_spec.rb",
128
+ "spec/spec_helper.rb",
129
+ "test/functional/admin/pages_controller_test.rb",
130
+ "test/functional/admin/site_controller_test.rb",
131
+ "test/functional/vhost_extension_test.rb",
132
+ "test/helpers/page_part_test_helper.rb",
133
+ "test/test_helper.rb",
134
+ "test/unit/site_test.rb"
135
+ ]
136
+
137
+ if s.respond_to? :specification_version then
138
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
139
+ s.specification_version = 3
140
+
141
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
142
+ s.add_development_dependency(%q<radiant>, [">= 0"])
143
+ else
144
+ s.add_dependency(%q<radiant>, [">= 0"])
145
+ end
146
+ else
147
+ s.add_dependency(%q<radiant>, [">= 0"])
148
+ end
149
+ end
150
+
@@ -0,0 +1,4 @@
1
+ ScopedAccess
2
+ ============
3
+
4
+ See http://habtm.com/articles/2006/02/22/nested-with_scope
@@ -0,0 +1,22 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Test the scoped_access plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.pattern = 'test/**/*_test.rb'
12
+ t.verbose = true
13
+ end
14
+
15
+ desc 'Generate documentation for the scoped_access plugin.'
16
+ Rake::RDocTask.new(:rdoc) do |rdoc|
17
+ rdoc.rdoc_dir = 'rdoc'
18
+ rdoc.title = 'ScopedAccess'
19
+ rdoc.options << '--line-numbers --inline-source'
20
+ rdoc.rdoc_files.include('README')
21
+ rdoc.rdoc_files.include('lib/**/*.rb')
22
+ end
@@ -0,0 +1,42 @@
1
+ ActionController::Base.instance_eval do
2
+ def scoped_access (*args, &block)
3
+ options = (Hash === args.last && !(args.last.keys & [:only, :except]).empty?) ? args.pop : {}
4
+ send(:around_filter, ScopedAccess::Filter.new(*args, &block), options)
5
+ end
6
+ end
7
+
8
+ require 'dispatcher'
9
+ if ActionController.const_defined?(:Dispatcher)
10
+ # Rails2.1
11
+ ActionController::Dispatcher.class_eval do
12
+ class << self
13
+ def define_dispatcher_callbacks_with_reset(cache_classes)
14
+ define_dispatcher_callbacks_without_reset(cache_classes)
15
+ ScopedAccess.reset
16
+ end
17
+ alias_method_chain :define_dispatcher_callbacks, :reset
18
+ end
19
+ end
20
+
21
+ else
22
+ # Rails1.2 or Rails2.0
23
+ class ::Dispatcher
24
+ app = respond_to?(:prepare_application, true) ? (class << self; self end) : self
25
+ app.class_eval do
26
+ private
27
+ def prepare_application_with_reset
28
+ ScopedAccess.reset
29
+ prepare_application_without_reset
30
+ end
31
+
32
+ alias_method :prepare_application_without_reset, :prepare_application
33
+ alias_method :prepare_application, :prepare_application_with_reset
34
+ end
35
+ end
36
+ end
37
+
38
+ ActiveRecord::Base.instance_eval do
39
+ def reset_scope
40
+ scoped_methods.clear
41
+ end
42
+ end
@@ -0,0 +1 @@
1
+ # Install hook code here
@@ -0,0 +1,197 @@
1
+ module ScopedAccess
2
+ class SqlCondition
3
+ attr_reader :attributes, :constrains
4
+
5
+ Constrain = Struct.new(:statement, :parameters)
6
+
7
+ def initialize (attributes = nil)
8
+ if attributes.is_a?(SqlCondition)
9
+ constrains = attributes.constrains.dup
10
+ attributes = attributes.attributes
11
+ end
12
+
13
+ @attributes = HashWithIndifferentAccess.new(attributes ? attributes.dup : {})
14
+ @constrains = constrains || []
15
+ @cached = nil
16
+ end
17
+
18
+ def add (statement, *parameters)
19
+ @constrains << Constrain.new(normalize_statement(statement), parameters)
20
+ updated
21
+ end
22
+
23
+ def []= (key, val)
24
+ @attributes[key] = val
25
+ updated
26
+ end
27
+
28
+ def generate
29
+ @cached ||= parse
30
+ end
31
+
32
+ def + (other)
33
+ other.attributes.to_a.inject(self.class.new(@attributes)){|obj, (key, val)| obj[key] = val; obj}
34
+ end
35
+
36
+ def empty?
37
+ @attributes.empty? && @constrains.empty?
38
+ end
39
+
40
+ protected
41
+ def normalize_column_name (column_name)
42
+ column_name
43
+ end
44
+
45
+ def normalize_statement (statement)
46
+ # statement.sub(/\A\s*\(\s*(.*?)\s*\)\s*\Z/) {$2} # strip parentheses
47
+ # this is buggy for the case: "(date1 <= ?) AND (date2 BETWEEN ? AND ?)"
48
+ statement
49
+ end
50
+
51
+ def updated
52
+ @cached = nil
53
+ end
54
+
55
+ def parse
56
+ constrains = @attributes.keys.sort.inject(@constrains.dup) {|array, key| array << parse_attribute(key, @attributes[key])}
57
+ statements = constrains.collect{|constrain| "( %s )" % constrain.statement}
58
+ parameters = constrains.inject([]){|array, constrain| array += constrain.parameters unless constrain.parameters.empty?; array}
59
+ [statements.join(" AND ")] + parameters
60
+ end
61
+
62
+ def parse_attribute (column_name, value)
63
+ column_name = normalize_column_name(column_name)
64
+ if value.nil?
65
+ Constrain.new("#{column_name} is NULL", [])
66
+ elsif value.is_a? Array
67
+ Constrain.new("#{column_name} in (?)", value)
68
+ else
69
+ Constrain.new("#{column_name} = ?", [value])
70
+ end
71
+ end
72
+ end
73
+
74
+ class MethodScoping < SqlCondition
75
+ attr_accessor :find_options, :options
76
+
77
+ def initialize (attributes = nil, options = {}, finder_options = {})
78
+ super(attributes)
79
+ @options = HashWithIndifferentAccess.new(options || {})
80
+ @find_options = finder_options || {}
81
+ end
82
+
83
+ def method_scoping
84
+ constrains = {
85
+ :find => construct_finder,
86
+ :create => @attributes,
87
+ }
88
+ constrains.delete(:find) if constrains[:find] == {:conditions => [""]}
89
+ return constrains
90
+ end
91
+
92
+ protected
93
+ def construct_finder
94
+ (generate == [""]) ? @find_options : @find_options.merge(:conditions => generate)
95
+ end
96
+ end
97
+
98
+ class ClassScoping < MethodScoping
99
+ def initialize (klass, *args)
100
+ (@klass = klass).is_a?(Class) or
101
+ raise ArgumentError, "A subclass of ActiveRecord::Base is required for '#{klass.class}'"
102
+ super(*args)
103
+ end
104
+
105
+ protected
106
+ def normalize_column_name (column_name)
107
+ "#{ @klass.table_name }.#{ column_name }"
108
+ end
109
+
110
+ def column_name_regexp_string
111
+ @column_name_regexp_string ||= "(%s)" % @klass.column_names.join('|')
112
+ end
113
+
114
+ def normalize_statement (statement)
115
+ super.sub(/\A#{column_name_regexp_string}(\s*=|\s+(is|in)\s+)/mi) {
116
+ "%s%s" % [normalize_column_name($1), $2]
117
+ }
118
+ end
119
+
120
+ end
121
+
122
+ class Filter
123
+ @applied_classes = Set.new
124
+ class << self
125
+ def reset
126
+ ActiveRecord::Base.logger.debug("ScopedAccess: reset %s" % @applied_classes.to_a.inspect)
127
+ @applied_classes.each(&:reset_scope)
128
+ @applied_classes.clear
129
+ end
130
+
131
+ def mark(klass)
132
+ @applied_classes << klass
133
+ ActiveRecord::Base.logger.debug("ScopedAccess: mark %s" % klass)
134
+ end
135
+
136
+ def unmark(klass)
137
+ @applied_classes.delete(klass)
138
+ ActiveRecord::Base.logger.debug("ScopedAccess: unmark %s" % klass)
139
+ end
140
+ end
141
+
142
+ def initialize (klass, scoping = :method_scoping, &block)
143
+ @klass = klass
144
+ @scoping = block || scoping
145
+ end
146
+
147
+ def before (controller)
148
+ constrain = self.class.generate_constrain(@klass, @scoping, :table_name=>@klass.table_name, :controller=>controller)
149
+ @klass.logger.debug("ScopedAccessFilter#before (called from %s):\n\t[%s] scope becomes %s" %
150
+ [controller.class, @klass, constrain.inspect])
151
+ @klass.instance_eval do
152
+ Filter.mark(self)
153
+ scoped_methods << with_scope(constrain){current_scoped_methods}
154
+ end
155
+ end
156
+
157
+ def after (controller)
158
+ @klass.instance_eval do
159
+ scoped_methods.pop
160
+ end
161
+ @klass.logger.debug("ScopedAccess::Filter#after (called from %s):\n\t[%s] scope is restored to %s" %
162
+ [controller.class, @klass, @klass.send(:scoped_methods).inspect])
163
+ end
164
+
165
+ class << self
166
+ def generate_constrain (klass, scoping, scoping_options = {})
167
+ case scoping
168
+ when Symbol
169
+ controller = scoping_options[:controller] or raise RuntimeError, "[plugin bug???] missing controller"
170
+ method_scoping = controller.__send__(scoping)
171
+ raise RuntimeError, "generate_constrain got infinite loop!" if method_scoping.is_a?(Symbol)
172
+ return generate_constrain(klass, method_scoping, scoping_options)
173
+ when Proc
174
+ method_scoping = scoping.call(scoping_options[:controller])
175
+ raise RuntimeError, "generate_constrain got infinite loop!" if method_scoping.is_a?(Proc)
176
+ return generate_constrain(klass, method_scoping, scoping_options)
177
+ when Hash, ClassScoping
178
+ return scoping
179
+ when SqlCondition
180
+ method_scoping = ClassScoping.new(klass, scoping, scoping_options.reject{|k,| k==:controller})
181
+ return generate_constrain(klass, method_scoping)
182
+ when Array, String
183
+ method_scoping = ClassScoping.new(klass, {}, scoping_options.reject{|k,| k==:controller})
184
+ method_scoping.add(*scoping)
185
+ return generate_constrain(klass, method_scoping)
186
+ else
187
+ raise TypeError, "cannot generate constrain from this type: (%s)" % scoping.class
188
+ end
189
+ end
190
+ end
191
+ end
192
+
193
+ module_function
194
+ def reset
195
+ Filter.reset
196
+ end
197
+ end
@@ -0,0 +1,12 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "scoped_access"
3
+ s.version = "0.1"
4
+ s.date = "2008-10-03"
5
+ s.summary = ""
6
+ s.email = "maiha@wota.jp"
7
+ s.homepage = "http://github.com/maiha/scoped_access"
8
+ s.description = ""
9
+ s.has_rdoc = true
10
+ s.authors = ["maiha"]
11
+ s.files = ["README", "Rakefile", "init.rb", "install.rb", "lib/scoped_access.rb", "tasks/scoped_access_tasks.rake", "test/database.yml", "test/filter_test.rb", "test/fixtures/favorite.rb", "test/fixtures/favorites.yml", "test/fixtures/group.rb", "test/fixtures/groups.yml", "test/fixtures/member.rb", "test/fixtures/members.yml", "test/fixtures/song.rb", "test/method_scoping_test.rb", "test/schema.rb", "test/scoped_access_test.rb", "test/sql_condition_test.rb", "test/test_helper.rb"]
12
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :scoped_access do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,22 @@
1
+ sqlite:
2
+ :adapter: sqlite
3
+ :dbfile: scoped_access_plugin_test.sqlite.db
4
+
5
+ sqlite3:
6
+ :adapter: sqlite3
7
+ :dbfile: scoped_access_plugin_test.sqlite3.db
8
+
9
+ postgresql:
10
+ :adapter: postgresql
11
+ :username: postgres
12
+ :password: postgres
13
+ :database: scoped_access_plugin_test
14
+ :min_messages: ERROR
15
+
16
+ mysql:
17
+ :adapter: mysql
18
+ :host: localhost
19
+ :username: rails
20
+ :password:
21
+ :database: scoped_access_plugin_test
22
+
@@ -0,0 +1,143 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+ require __DIR__ + '/fixtures/member'
3
+
4
+ class FilterGenerateConstrainTest < Test::Unit::TestCase
5
+ def test_generate_constrain_from_hash
6
+ scoping = Filter.generate_constrain(Member, {:find=>{:limit=>10}})
7
+ expected = {
8
+ :find => { :limit => 10 }
9
+ }
10
+ assert_equal expected, scoping
11
+ end
12
+
13
+ def test_generate_constrain_from_string
14
+ scoping = Filter.generate_constrain(Member, 'name = "Maiha"').method_scoping
15
+ expected = {
16
+ :find => { :conditions => ['( members.name = "Maiha" )'] },
17
+ :create => { },
18
+ }
19
+ assert_equal expected, scoping
20
+ end
21
+
22
+ def test_generate_constrain_from_array
23
+ scoping = Filter.generate_constrain(Member, ['name = ?', "Maiha"]).method_scoping
24
+ expected = {
25
+ :find => { :conditions => ['( members.name = ? )', "Maiha"] },
26
+ :create => { },
27
+ }
28
+ assert_equal expected, scoping
29
+ end
30
+
31
+ def test_generate_constrain_from_symbol
32
+ assert_raise(NoMethodError) {
33
+ Filter.generate_constrain(Member, :method_scoping, :controller=>:dummy)
34
+ }
35
+ end
36
+
37
+ def test_generate_constrain_from_proc
38
+ expected = {:find=>{}, :create=>{}}
39
+ proc = Proc.new{expected}
40
+ assert_equal expected, Filter.generate_constrain(Member, proc)
41
+ end
42
+
43
+ def test_generate_constrain_from_sql_condition
44
+ condition = SqlCondition.new(:name => "Maiha")
45
+
46
+ scoping = Filter.generate_constrain(Member, condition).method_scoping
47
+ expected = {
48
+ :find => { :conditions => ['( members.name = ? )', "Maiha"] },
49
+ :create => { 'name' => "Maiha" },
50
+ }
51
+ assert_equal expected, scoping
52
+ end
53
+
54
+ def test_generate_constrain_from_method_scoping
55
+ method_scoping = MethodScoping.new(:name => "Maiha")
56
+
57
+ scoping = Filter.generate_constrain(Member, method_scoping).method_scoping
58
+ expected = {
59
+ :find => { :conditions => ['( members.name = ? )', "Maiha"] },
60
+ :create => { 'name' => "Maiha" },
61
+ }
62
+ assert_equal expected, scoping
63
+ end
64
+ end
65
+
66
+
67
+
68
+ class FilterWithMethodScopingTest < Test::Unit::TestCase
69
+ def setup
70
+ @controller = Struct.new(:method_scoping).new # faked
71
+ @class = Member
72
+ @filter = Filter.new(@class)
73
+ @nested_depth = @class.instance_eval{scoped_methods}.size
74
+ end
75
+
76
+ def teardown
77
+ current_scopings = @class.instance_eval{scoped_methods}
78
+ nested_depth = current_scopings.size - @nested_depth
79
+ @class.instance_eval{nested_depth.times{scoped_methods.pop}}
80
+ end
81
+
82
+ def test_generate_constrain_from_hash
83
+ @controller.method_scoping = {:find=>{:limit=>10}}
84
+ scoping = @filter.before(@controller).last
85
+ expected = {
86
+ :find => { :limit => 10 }
87
+ }
88
+ assert_equal expected, scoping
89
+ end
90
+
91
+ def test_generate_constrain_from_string
92
+ @controller.method_scoping = 'name = "Maiha"'
93
+ scoping = @filter.before(@controller).last
94
+ expected = {
95
+ :find => { :conditions => ['( members.name = "Maiha" )'] },
96
+ :create => { },
97
+ }
98
+ assert_equal expected, scoping
99
+ end
100
+
101
+ def test_generate_constrain_from_array
102
+ @controller.method_scoping = ['name = ?', "Maiha"]
103
+ scoping = @filter.before(@controller).last
104
+ expected = {
105
+ :find => { :conditions => ['( members.name = ? )', "Maiha"] },
106
+ :create => { },
107
+ }
108
+ assert_equal expected, scoping
109
+ end
110
+
111
+ def test_generate_constrain_from_symbol
112
+ expected = {:find=>{}, :create=>{}}
113
+ @controller.method_scoping = expected
114
+ assert_equal expected, scoping = @filter.before(@controller).last
115
+ end
116
+
117
+ def test_generate_constrain_from_proc
118
+ expected = {:find=>{}, :create=>{}}
119
+ @controller.method_scoping = Proc.new{expected}
120
+ assert_equal expected, scoping = @filter.before(@controller).last
121
+ end
122
+
123
+ def test_generate_constrain_from_sql_condition
124
+ @controller.method_scoping = SqlCondition.new(:name => "Maiha")
125
+ scoping = @filter.before(@controller).last
126
+ expected = {
127
+ :find => { :conditions => ['( members.name = ? )', "Maiha"] },
128
+ :create => { 'name' => "Maiha" },
129
+ }
130
+ assert_equal expected, scoping
131
+ end
132
+
133
+ def test_generate_constrain_from_method_scoping
134
+ @controller.method_scoping = MethodScoping.new(:name => "Maiha")
135
+ scoping = @filter.before(@controller).last
136
+ expected = {
137
+ :find => { :conditions => ['( members.name = ? )', "Maiha"] },
138
+ :create => { 'name' => "Maiha" },
139
+ }
140
+ assert_equal expected, scoping
141
+ end
142
+ end
143
+
@@ -0,0 +1,4 @@
1
+ class Favorite < ActiveRecord::Base
2
+ belongs_to :member
3
+ validates_presence_of :name, :member_id
4
+ end
@@ -0,0 +1,17 @@
1
+ ---
2
+ record_1:
3
+ name: "miso soup"
4
+ member_id: 1
5
+ id: 1
6
+ record_2:
7
+ name: "strawberry"
8
+ member_id: 2
9
+ id: 2
10
+ record_3:
11
+ name: "natto"
12
+ member_id: 3
13
+ id: 3
14
+ record_4:
15
+ name: "golf"
16
+ member_id: 10
17
+ id: 4
@@ -0,0 +1,4 @@
1
+ class Group < ActiveRecord::Base
2
+ has_many :members, :include=>"favorites", :order=>"members", :dependent=>true
3
+ validates_presence_of :name
4
+ end
@@ -0,0 +1,13 @@
1
+ ---
2
+ record_1:
3
+ name: Berryz
4
+ id: 1
5
+ deleted: false
6
+ record_2:
7
+ name: Cute
8
+ id: 2
9
+ deleted: false
10
+ record_5:
11
+ name: ZYX
12
+ id: 5
13
+ deleted: false
@@ -0,0 +1,5 @@
1
+ class Member < ActiveRecord::Base
2
+ belongs_to :group
3
+ has_many :favorites, :dependent=>true
4
+ validates_presence_of :yomi, :name, :comments, :group_id
5
+ end
@@ -0,0 +1,32 @@
1
+ # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
2
+ saki:
3
+ id: 1
4
+ name: Saki
5
+ group_id: 1
6
+ grade: 2
7
+ deleted: false
8
+ maiha:
9
+ id: 2
10
+ name: Maiha
11
+ group_id: 1
12
+ grade: 2
13
+ deleted: true
14
+ yurina:
15
+ id: 3
16
+ name: Yurina
17
+ group_id: 1
18
+ grade: 1
19
+ deleted: false
20
+ risako:
21
+ id: 4
22
+ name: Risako
23
+ group_id: 1
24
+ grade: 1
25
+ deleted: false
26
+ airi:
27
+ id: 10
28
+ name: Airi
29
+ group_id: 2
30
+ grade: 2
31
+ deleted: false
32
+
@@ -0,0 +1,4 @@
1
+ class Song < ActiveRecord::Base
2
+ belongs_to :group
3
+ validates_presence_of :name, :content, :group_id
4
+ end
@@ -0,0 +1,87 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class MethodScopingTest < Test::Unit::TestCase
4
+ def test_no_conditions
5
+ assert_equal({ :find=>{}, :create=>{} }, MethodScoping.new(nil).method_scoping)
6
+ assert_equal({ :find=>{}, :create=>{} }, MethodScoping.new({}).method_scoping)
7
+ end
8
+
9
+ def test_create_method_scoping
10
+ method_scoping = MethodScoping.new(:name => "Maiha")
11
+ expected = {
12
+ :find => { :conditions => ['( name = ? )', "Maiha"] },
13
+ :create => { 'name' => "Maiha" },
14
+ }
15
+ assert_equal expected, method_scoping.method_scoping
16
+ end
17
+
18
+ def test_create_method_scoping_with_attributed_and_conditioned_values
19
+ method_scoping = MethodScoping.new(:name => "Maiha")
20
+ method_scoping.add("grade IN ?", [1,2])
21
+ method_scoping[:group] = 'Berryz'
22
+
23
+ expected = {
24
+ :find => { :conditions => ["( grade IN ? ) AND ( group = ? ) AND ( name = ? )", [1,2], "Berryz", "Maiha"] },
25
+ :create => { 'name' => "Maiha", 'group' => "Berryz" },
26
+ }
27
+ assert_equal expected, method_scoping.method_scoping
28
+ end
29
+
30
+ def test_plus_method_with_merge
31
+ scoping1 = MethodScoping.new(:name => "Maiha")
32
+ scoping2 = MethodScoping.new(:group => "Berryz")
33
+
34
+ expected = {
35
+ "name" => "Maiha",
36
+ "group" => "Berryz",
37
+ }
38
+ assert_equal expected, (scoping1 + scoping2).attributes
39
+ end
40
+
41
+ def test_plus_method_with_overwrite
42
+ scoping1 = MethodScoping.new(:name => "Maiha", :group => "Berryz")
43
+ scoping2 = MethodScoping.new(:name => "Saki")
44
+
45
+ expected = {
46
+ "name" => "Saki",
47
+ "group" => "Berryz",
48
+ }
49
+ assert_equal expected, (scoping1 + scoping2).attributes
50
+ end
51
+ end
52
+
53
+
54
+ class ClassScopingTest < Test::Unit::TestCase
55
+ def test_create_class_scoping
56
+ class_scoping = ClassScoping.new(Member, :name => "Maiha")
57
+ expected = {
58
+ :find => { :conditions => ['( members.name = ? )', "Maiha"] },
59
+ :create => { 'name' => "Maiha" },
60
+ }
61
+ assert_equal expected, class_scoping.method_scoping
62
+ end
63
+
64
+ def test_create_class_scoping_from_method_scoping
65
+ method_scoping = MethodScoping.new(:name => "Maiha")
66
+ class_scoping = ClassScoping.new(Member, method_scoping.attributes)
67
+
68
+ expected = {
69
+ :find => { :conditions => ['( members.name = ? )', "Maiha"] },
70
+ :create => { 'name' => "Maiha" },
71
+ }
72
+ assert_equal expected, class_scoping.method_scoping
73
+ end
74
+
75
+ def test_create_class_scoping_with_attributed_and_conditioned_values
76
+ class_scoping = ClassScoping.new(Member, :name => "Maiha")
77
+ class_scoping.add("grade IN ?", [1,2])
78
+ class_scoping[:group] = 'Berryz'
79
+
80
+ expected = {
81
+ :find => { :conditions => ["( members.grade IN ? ) AND ( members.group = ? ) AND ( members.name = ? )",
82
+ [1,2], "Berryz", "Maiha"] },
83
+ :create => { 'name' => "Maiha", 'group' => "Berryz" },
84
+ }
85
+ assert_equal expected, class_scoping.method_scoping
86
+ end
87
+ end
@@ -0,0 +1,20 @@
1
+ ActiveRecord::Schema.define(:version => 2) do
2
+
3
+ create_table :groups, :force => true do |t|
4
+ t.column :name, :string
5
+ t.column :deleted, :boolean, :default=>0
6
+ end
7
+
8
+ create_table :members, :force => true do |t|
9
+ t.column :name, :string
10
+ t.column :grade, :integer
11
+ t.column :deleted, :boolean, :default=>0
12
+ t.column :group_id,:integer
13
+ end
14
+
15
+ create_table :favorites, :force => true do |t|
16
+ t.column :name, :string
17
+ t.column :member_id,:integer
18
+ end
19
+
20
+ end
@@ -0,0 +1,247 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
+ require File.join(File.dirname(__FILE__), '..', 'init')
3
+
4
+ module Scopings
5
+ ActiveMember = MethodScoping.new(:deleted => false)
6
+ ElementarySchool = MethodScoping.new(:grade => 1)
7
+ JuniorHighSchool = MethodScoping.new(:grade => 2)
8
+ end
9
+
10
+ class TestController < ActionController::Base
11
+ attr_reader :members, :member
12
+
13
+ def list
14
+ @members = Member.find(:all, :order=>:id)
15
+ render :text=>''
16
+ end
17
+
18
+ def show
19
+ @member = Member.find(params[:id])
20
+ render :text=>''
21
+ end
22
+ end
23
+
24
+ class ScopedAccessTestCase < Test::Unit::TestCase
25
+ fixtures :members
26
+
27
+ def setup
28
+ Member.instance_eval{scoped_methods.clear}
29
+ @request = ActionController::TestRequest.new
30
+ @response = ActionController::TestResponse.new
31
+ end
32
+
33
+ def test_dummy
34
+ end
35
+
36
+ private
37
+ def test_process(controller, action = "show")
38
+ request = ActionController::TestRequest.new
39
+ request.action = action
40
+ controller.process(request, ActionController::TestResponse.new)
41
+ end
42
+
43
+ end
44
+
45
+
46
+ class WithoutFilterTest < ScopedAccessTestCase
47
+ class WithoutFilterController < TestController
48
+ end
49
+
50
+ def setup
51
+ super
52
+ @controller = WithoutFilterController.new
53
+ end
54
+
55
+ def test_filter_list
56
+ get :list
57
+ assert_response :success
58
+ assert_equal %w( Saki Maiha Yurina Risako Airi ), @controller.members.map{|o| o.name}
59
+ end
60
+
61
+ def test_filter_show
62
+ get :show, {'id' => "2"}
63
+ assert_response :success
64
+ assert_equal members(:maiha), @controller.member
65
+ end
66
+ end
67
+
68
+ class ActiveMemberTest < ScopedAccessTestCase
69
+ class ActiveMemberController < TestController
70
+ around_filter ScopedAccess::Filter.new(Member, Scopings::ActiveMember)
71
+
72
+ def nested_scoping_with_elementary_school
73
+ Member.with_scope(Scopings::ElementarySchool) do
74
+ @members = Member.find(:all)
75
+ end
76
+ render :text=>''
77
+ end
78
+ end
79
+
80
+ def setup
81
+ super
82
+ @controller = ActiveMemberController.new
83
+ end
84
+
85
+ def test_filter_list
86
+ get :list
87
+ assert_response :success
88
+ expected = %w( saki yurina risako airi ).collect{|name| members(name)}
89
+ assert_equal expected, @controller.members
90
+ end
91
+
92
+ def test_filter_show
93
+ assert_raises(ActiveRecord::RecordNotFound) {
94
+ get :show, {'id' => "2"}
95
+ }
96
+ end
97
+
98
+ def test_filter_nested_scoping
99
+ get :nested_scoping_with_elementary_school
100
+ assert_response :success
101
+ assert_equal [members(:yurina), members(:risako)], @controller.members
102
+ end
103
+ end
104
+
105
+
106
+ class DoubleAroundWithMergedScopedFilterTest < ScopedAccessTestCase
107
+ class DoubleAroundWithMergedScopedFilterController < TestController
108
+ scoped_access Member, Scopings::ActiveMember
109
+ scoped_access Member, Scopings::JuniorHighSchool
110
+
111
+ def list_with_exclusive_scope
112
+ Member.with_exclusive_scope(Scopings::ElementarySchool) do
113
+ @members = Member.find(:all)
114
+ end
115
+ render :text=>''
116
+ end
117
+ end
118
+
119
+ def setup
120
+ super
121
+ @controller = DoubleAroundWithMergedScopedFilterController.new
122
+ end
123
+
124
+ def test_filter_list
125
+ get :list
126
+ assert_response :success
127
+ assert_equal [members(:saki), members(:airi)], @controller.members
128
+ end
129
+
130
+ def test_filter_show_active_member
131
+ get :show, {'id' => "1"}
132
+ assert_response :success
133
+ assert_equal members(:saki), @controller.member
134
+ end
135
+
136
+ def test_filter_show_deleted_member
137
+ assert_raises(ActiveRecord::RecordNotFound) {
138
+ get :show, {'id' => "2"}
139
+ }
140
+ end
141
+
142
+ def test_list_with_exclusive_scope
143
+ get :list_with_exclusive_scope
144
+ assert_response :success
145
+ assert_equal [members(:yurina), members(:risako)], @controller.members
146
+ end
147
+ end
148
+
149
+
150
+ class InheritedDoubleAroundFilterTest < ScopedAccessTestCase
151
+ class ParentAroundFilterController < TestController
152
+ scoped_access Member, Scopings::ActiveMember
153
+ end
154
+
155
+ class InheritedDoubleAroundFilterController < ParentAroundFilterController
156
+ scoped_access Member, Scopings::JuniorHighSchool
157
+
158
+ def list_with_conflicted_condition
159
+ Member.with_scope(Scopings::ElementarySchool) do
160
+ @members = Member.find(:all)
161
+ end
162
+ render :text=>''
163
+ end
164
+ end
165
+
166
+ def setup
167
+ super
168
+ @controller = InheritedDoubleAroundFilterController.new
169
+ end
170
+
171
+ def test_filter_list
172
+ get :list
173
+ assert_response :success
174
+ assert_equal [members(:saki), members(:airi)], @controller.members
175
+ end
176
+
177
+ def test_filter_show
178
+ assert_raises(ActiveRecord::RecordNotFound) {
179
+ get :show, {'id' => "2"}
180
+ }
181
+ end
182
+
183
+ def test_filter_list_with_conflicted_condition
184
+ get :list_with_conflicted_condition
185
+ assert_response :success
186
+ assert_equal [], @controller.members
187
+ end
188
+ end
189
+
190
+
191
+ class ConditionalAroundFilterTest < ScopedAccessTestCase
192
+ class ConditionalParentAroundFilterController < TestController
193
+ scoped_access Member, Scopings::ActiveMember, :except=>:all
194
+ scoped_access Member, Scopings::JuniorHighSchool
195
+ end
196
+
197
+ class InheritedDoubleConditionalAroundFilterController < ConditionalParentAroundFilterController
198
+ scoped_access Member, Scopings::ElementarySchool, :only=>:list_with_conflicted_condition
199
+
200
+ def list_with_conflicted_condition
201
+ @members = Member.find(:all)
202
+ render :text=>''
203
+ end
204
+
205
+ def list
206
+ @members = Member.find(:all)
207
+ render :text=>''
208
+ end
209
+
210
+ def all
211
+ @members = Member.find(:all)
212
+ render :text=>''
213
+ end
214
+ end
215
+
216
+ def setup
217
+ super
218
+ @controller = InheritedDoubleConditionalAroundFilterController.new
219
+ end
220
+
221
+ def test_filter_list_out_of_only_condition
222
+ expected = Member.with_exclusive_scope(Scopings::ActiveMember+Scopings::JuniorHighSchool){Member.find(:all)}
223
+ get :list
224
+ assert_response :success
225
+ assert_equal expected, @controller.members
226
+ end
227
+
228
+ def test_filter_show
229
+ assert_raises(ActiveRecord::RecordNotFound) {
230
+ get :show, {'id' => "2"}
231
+ }
232
+ end
233
+
234
+ def test_filter_list_with_conflicted_condition
235
+ get :list_with_conflicted_condition
236
+ assert_response :success
237
+ assert_equal [], @controller.members
238
+ end
239
+
240
+ def test_filter_except_condition
241
+ expected = Member.with_exclusive_scope(Scopings::JuniorHighSchool){Member.find(:all)}
242
+ get :all
243
+ assert_response :success
244
+ assert_equal expected, @controller.members
245
+ end
246
+ end
247
+
@@ -0,0 +1,78 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class SqlConditionTest < Test::Unit::TestCase
4
+ def setup
5
+ attributes = { :name => 'Maiha' }
6
+ @condition = SqlCondition.new(attributes)
7
+ end
8
+
9
+ def test_immutable_attributes
10
+ assert_equal "Maiha", @condition.attributes[:name]
11
+ attributes = { :name => 'Saki' }
12
+ assert_equal "Maiha", @condition.attributes[:name]
13
+ end
14
+
15
+ def test_add_attribute
16
+ @condition[:group] = 'Berryz'
17
+ assert_equal({'name'=>"Maiha", 'group'=>'Berryz'}, @condition.attributes)
18
+ end
19
+
20
+ def test_overwrite_attribute
21
+ @condition[:name] = 'Saki'
22
+ assert_equal({'name'=>"Saki"}, @condition.attributes)
23
+ end
24
+
25
+ def test_generate_with_one_attribute
26
+ assert_equal(["( name = ? )", "Maiha"], @condition.generate)
27
+ end
28
+
29
+ def test_generate_with_one_condition
30
+ @condition = SqlCondition.new
31
+ @condition.add("name = 'Maiha'")
32
+ assert_equal ["( name = 'Maiha' )"], @condition.generate
33
+ end
34
+
35
+ def test_generate_with_one_attribute_and_one_condition
36
+ @condition.add("group = 'Berryz'")
37
+ assert_equal "( group = 'Berryz' ) AND ( name = 'Maiha' )", sanitize_sql(@condition.generate)
38
+ end
39
+
40
+ def test_generate_same_sqls_in_attributed_and_conditioned_ways
41
+ attributed = @condition
42
+ conditioned = SqlCondition.new
43
+
44
+ conditioned.add("name = 'Maiha'")
45
+ assert_equal sanitize_sql(attributed.generate), sanitize_sql(conditioned.generate)
46
+ end
47
+
48
+ def test_generate_with_one_and_two_place_folders
49
+ @condition.add("group = ?", 'Berryz')
50
+ @condition.add("age BETWEEN ? AND ?", 12, 14)
51
+ expected_sql = "( group = 'Berryz' ) AND ( age BETWEEN 12 AND 14 ) AND ( name = 'Maiha' )"
52
+ assert_equal expected_sql, sanitize_sql(@condition.generate)
53
+ end
54
+
55
+ def test_generate_with_complex_constrains
56
+ @condition.add("group = ?", 'Berryz')
57
+ @condition.add("state IN (?)", [1,2])
58
+ @condition[:graduate] = 1
59
+ expected_sql = "( group = 'Berryz' ) AND ( state IN (1,2) ) AND ( graduate = 1 ) AND ( name = 'Maiha' )"
60
+ assert_equal expected_sql, sanitize_sql(@condition.generate)
61
+ end
62
+
63
+ def test_generate_from_sql_condition
64
+ @condition.add("group = ?", 'Berryz')
65
+ cond = SqlCondition.new(@condition)
66
+ assert_equal({"name"=>'Maiha'}, cond.attributes)
67
+ assert_equal([SqlCondition::Constrain.new("group = ?", ['Berryz'])], cond.constrains)
68
+ end
69
+
70
+ private
71
+ def sanitize_sql (sql)
72
+ ActiveRecord::Base.instance_eval do
73
+ sanitize_sql(sql)
74
+ end
75
+ end
76
+
77
+ end
78
+
@@ -0,0 +1,39 @@
1
+ def __DIR__; File.dirname(__FILE__); end
2
+
3
+ $:.unshift(__DIR__ + '/../lib')
4
+ # begin
5
+ # require 'rubygems'
6
+ # rescue LoadError
7
+ $:.unshift(__DIR__ + '/../../../rails/activerecord/lib')
8
+ $:.unshift(__DIR__ + '/../../../rails/activesupport/lib')
9
+ $:.unshift(__DIR__ + '/../../../rails/actionpack/lib')
10
+ #end
11
+ require 'test/unit'
12
+ require 'active_support'
13
+ require 'active_record'
14
+ require 'active_record/fixtures'
15
+
16
+ config = YAML::load_file(__DIR__ + '/database.yml')
17
+ ActiveRecord::Base.logger = Logger.new(__DIR__ + "/debug.log")
18
+ ActiveRecord::Base.establish_connection(config[ENV['DB'] || 'sqlite3'])
19
+
20
+
21
+ # create tables
22
+ load(__DIR__ + "/schema.rb")
23
+
24
+ # insert sample data to the tables from 'fixtures/*.yml'
25
+ Test::Unit::TestCase.fixture_path = __DIR__ + "/fixtures/"
26
+ $LOAD_PATH.unshift(Test::Unit::TestCase.fixture_path)
27
+ Test::Unit::TestCase.use_instantiated_fixtures = false
28
+
29
+ # for controller test
30
+ require 'action_pack'
31
+ require 'action_controller'
32
+ require 'action_controller/test_process'
33
+
34
+ ActionController::Base.ignore_missing_templates = true
35
+ ActionController::Routing::Routes.reload rescue nil
36
+ class ActionController::Base; def rescue_action(e) raise e end; end
37
+
38
+ include ScopedAccess
39
+
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: radiant-vhost-extension
3
3
  version: !ruby/object:Gem::Version
4
- hash: 11
4
+ hash: 7
5
5
  prerelease: false
6
6
  segments:
7
7
  - 2
8
- - 1
8
+ - 2
9
9
  - 0
10
- version: 2.1.0
10
+ version: 2.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Jason Garber
@@ -80,6 +80,7 @@ files:
80
80
  - lib/vhost/radiant_cache_extensions.rb
81
81
  - lib/vhost/site_scoped_model_extensions.rb
82
82
  - lib/vhost_default_config.yml
83
+ - radiant-vhost-extension.gemspec
83
84
  - spec/controllers/admin/pages_controller_spec.rb
84
85
  - spec/controllers/admin/sites_controller_spec.rb
85
86
  - spec/controllers/site_controller_spec.rb
@@ -110,6 +111,27 @@ files:
110
111
  - test/helpers/page_part_test_helper.rb
111
112
  - test/test_helper.rb
112
113
  - test/unit/site_test.rb
114
+ - vendor/scoped_access/README
115
+ - vendor/scoped_access/Rakefile
116
+ - vendor/scoped_access/init.rb
117
+ - vendor/scoped_access/install.rb
118
+ - vendor/scoped_access/lib/scoped_access.rb
119
+ - vendor/scoped_access/scoped_access.gemspec
120
+ - vendor/scoped_access/tasks/scoped_access_tasks.rake
121
+ - vendor/scoped_access/test/database.yml
122
+ - vendor/scoped_access/test/filter_test.rb
123
+ - vendor/scoped_access/test/fixtures/favorite.rb
124
+ - vendor/scoped_access/test/fixtures/favorites.yml
125
+ - vendor/scoped_access/test/fixtures/group.rb
126
+ - vendor/scoped_access/test/fixtures/groups.yml
127
+ - vendor/scoped_access/test/fixtures/member.rb
128
+ - vendor/scoped_access/test/fixtures/members.yml
129
+ - vendor/scoped_access/test/fixtures/song.rb
130
+ - vendor/scoped_access/test/method_scoping_test.rb
131
+ - vendor/scoped_access/test/schema.rb
132
+ - vendor/scoped_access/test/scoped_access_test.rb
133
+ - vendor/scoped_access/test/sql_condition_test.rb
134
+ - vendor/scoped_access/test/test_helper.rb
113
135
  - vhost_extension.rb
114
136
  has_rdoc: true
115
137
  homepage: http://github.com/saturnflyer/radiant-vhost-extension