trusty-multi-site-extension 1.0.0
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/README.markdown +116 -0
- data/Rakefile +120 -0
- data/app/assets/images/admin/move_higher.png +0 -0
- data/app/assets/images/admin/move_lower.png +0 -0
- data/app/assets/images/admin/move_to_bottom.png +0 -0
- data/app/assets/images/admin/move_to_top.png +0 -0
- data/app/assets/images/admin/remove.png +0 -0
- data/app/assets/stylesheets/admin/multi_site.scss +121 -0
- data/app/assets/stylesheets/admin/site_chooser.scss +0 -0
- data/app/controllers/admin/sites_controller.rb +14 -0
- data/app/helpers/scoped_helper.rb +19 -0
- data/app/helpers/sites_helper.rb +10 -0
- data/app/models/site.rb +86 -0
- data/app/views/admin/layouts/_choose_site.html.haml +8 -0
- data/app/views/admin/layouts/_site_chooser.html.haml +2 -0
- data/app/views/admin/sites/_form.haml +43 -0
- data/app/views/admin/sites/edit.haml +7 -0
- data/app/views/admin/sites/index.haml +43 -0
- data/app/views/admin/sites/new.haml +7 -0
- data/app/views/admin/snippets/_choose_site.html.haml +6 -0
- data/app/views/admin/users/_choose_site.html.haml +8 -0
- data/app/views/site/not_configured.html.haml +7 -0
- data/config/initializers/radiant_config.rb +5 -0
- data/config/routes.rb +13 -0
- data/db/migrate/001_create_sites.rb +13 -0
- data/db/migrate/002_add_order_to_sites.rb +9 -0
- data/db/migrate/003_add_base_domain_to_sites.rb +9 -0
- data/db/migrate/004_add_admin_fields_to_sites.rb +17 -0
- data/db/migrate/005_add_sites.rb +13 -0
- data/db/migrate/006_remove_user_login_index.rb +8 -0
- data/db/migrate/20090810145840_site_abbreviation.rb +9 -0
- data/db/migrate/201411031415046078_recreate_non_unique_index_on_snippets_name.rb +11 -0
- data/lib/multi_site/admin_ui.rb +46 -0
- data/lib/multi_site/application_controller_extensions.rb +40 -0
- data/lib/multi_site/application_controller_filter_extensions.rb +21 -0
- data/lib/multi_site/engine.rb +5 -0
- data/lib/multi_site/page_extensions.rb +43 -0
- data/lib/multi_site/pages_controller_extensions.rb +48 -0
- data/lib/multi_site/resource_controller_extensions.rb +41 -0
- data/lib/multi_site/route_extensions.rb +21 -0
- data/lib/multi_site/route_set_extensions.rb +16 -0
- data/lib/multi_site/scoped_model.rb +145 -0
- data/lib/multi_site/scoped_validation.rb +32 -0
- data/lib/multi_site/site_chooser_helper.rb +14 -0
- data/lib/multi_site/site_controller_extensions.rb +12 -0
- data/lib/tasks/multi_site_extension_tasks.rake +28 -0
- data/lib/tasks/scoped_admin_extension_tasks.rake +28 -0
- data/lib/trusty-multi-site-extension.rb +1 -0
- data/multi_site_extension.rb +66 -0
- data/spec/controllers/extended_site_controller_spec.rb +61 -0
- data/spec/datasets/site_pages_dataset.rb +13 -0
- data/spec/datasets/sites_dataset.rb +10 -0
- data/spec/functional/multi_site_routing_spec.rb +37 -0
- data/spec/lib/multi_site/admin_ui_spec.rb +35 -0
- data/spec/lib/multi_site/scoped_model_spec.rb +182 -0
- data/spec/matchers/route_matcher.rb +38 -0
- data/spec/models/extended_page_spec.rb +48 -0
- data/spec/models/site_spec.rb +83 -0
- data/spec/spec.opts +6 -0
- data/spec/spec_helper.rb +36 -0
- data/trusty-multi-site-extension.gemspec +28 -0
- metadata +164 -0
@@ -0,0 +1,17 @@
|
|
1
|
+
class AddAdminFieldsToSites < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
add_column :sites, :created_by_id, :integer
|
4
|
+
add_column :sites, :created_at, :datetime
|
5
|
+
add_column :sites, :updated_by_id, :integer
|
6
|
+
add_column :sites, :updated_at, :datetime
|
7
|
+
add_column :sites, :subtitle, :string
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.down
|
11
|
+
remove_column :sites, :created_by_id
|
12
|
+
remove_column :sites, :created_at
|
13
|
+
remove_column :sites, :udpated_by_id
|
14
|
+
remove_column :sites, :updated_at
|
15
|
+
remove_column :sites, :subtitle
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class AddSites < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
[:layouts, :snippets, :users].each do |table|
|
4
|
+
add_column table, :site_id, :integer
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.down
|
9
|
+
[:layouts, :snippets, :users].each do |table|
|
10
|
+
add_column table, :site_id, :integer
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class RecreateNonUniqueIndexOnSnippetsName < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
remove_index :snippets, :name => "name"
|
4
|
+
add_index :snippets, [:name, :site_id ], :name => "name_site_id", :unique => true
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.down
|
8
|
+
remove_index :snippets, :name => "name_site_id"
|
9
|
+
add_index :snippets, :name, :name => "name", :unique => true
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# This is included into AdminUI and defines editing regions for the site administration pages.
|
2
|
+
# Note that the AdminUI object is a singleton and it is not sufficient to add to its initialization routines: you also have to call load_default_site_regions on the admin singleton that has already been defined.
|
3
|
+
|
4
|
+
module MultiSite::AdminUI
|
5
|
+
|
6
|
+
def self.included(base)
|
7
|
+
base.class_eval do
|
8
|
+
|
9
|
+
attr_accessor :site
|
10
|
+
alias_method :sites, :site
|
11
|
+
|
12
|
+
protected
|
13
|
+
|
14
|
+
# The site-admin pages have these regions:
|
15
|
+
|
16
|
+
# Edit view:
|
17
|
+
# * main: edit_header, edit_form
|
18
|
+
# * form: edit_name edit_domain edit_homepage
|
19
|
+
# * form_bottom: edit_timestamp edit_buttons
|
20
|
+
|
21
|
+
# Index view
|
22
|
+
# * thead: title_header domain_header basedomain_header modify_header order_header
|
23
|
+
# * tbody: title_cell domain_cell basedomain_cell modify_cell order_cell (repeating row)
|
24
|
+
# * bottom: new_button
|
25
|
+
|
26
|
+
def load_default_site_regions
|
27
|
+
OpenStruct.new.tap do |site|
|
28
|
+
site.edit = TrustyCms::AdminUI::RegionSet.new do |edit|
|
29
|
+
edit.main.concat %w{edit_header edit_form}
|
30
|
+
edit.form.concat %w{edit_name edit_domain edit_homepage}
|
31
|
+
edit.form_bottom.concat %w{edit_timestamp edit_buttons}
|
32
|
+
end
|
33
|
+
site.index = TrustyCms::AdminUI::RegionSet.new do |index|
|
34
|
+
index.thead.concat %w{title_header domain_header basedomain_header modify_header order_header}
|
35
|
+
index.tbody.concat %w{title_cell domain_cell basedomain_cell modify_cell order_cell}
|
36
|
+
index.bottom.concat %w{new_button}
|
37
|
+
end
|
38
|
+
site.remove = site.index
|
39
|
+
site.new = site.edit
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module MultiSite::ApplicationControllerExtensions
|
2
|
+
|
3
|
+
def current_site
|
4
|
+
Page.current_site
|
5
|
+
end
|
6
|
+
|
7
|
+
def current_site=(site=nil)
|
8
|
+
Page.current_site = site
|
9
|
+
end
|
10
|
+
|
11
|
+
# this is overridden in Admin::ResourceController to respond correctly
|
12
|
+
|
13
|
+
def sited_model?
|
14
|
+
false
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
def set_site
|
19
|
+
true if self.current_site = discover_current_site
|
20
|
+
end
|
21
|
+
|
22
|
+
# chains will attach here
|
23
|
+
|
24
|
+
def discover_current_site
|
25
|
+
site_from_host
|
26
|
+
end
|
27
|
+
|
28
|
+
# and add more ways to determine the current site
|
29
|
+
|
30
|
+
def site_from_host
|
31
|
+
Site.find_for_host(request.host)
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.included(base)
|
35
|
+
base.class_eval {
|
36
|
+
helper_method :current_site, :current_site=
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module MultiSite::ApplicationControllerFilterExtensions
|
2
|
+
|
3
|
+
def self.included(base)
|
4
|
+
base.class_eval {
|
5
|
+
prepend_before_filter :set_site
|
6
|
+
alias_method_chain :authenticate, :site
|
7
|
+
}
|
8
|
+
end
|
9
|
+
|
10
|
+
protected
|
11
|
+
|
12
|
+
def authenticate_with_site
|
13
|
+
self.current_site = discover_current_site
|
14
|
+
authenticate_without_site
|
15
|
+
end
|
16
|
+
|
17
|
+
def set_site
|
18
|
+
true if self.current_site = discover_current_site
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# Unlike other scoped classes, there is no site association in the Page class. Instead, Site has a homepage association and Page has some retrieval methods that turn a page request into site information.
|
2
|
+
|
3
|
+
module MultiSite::PageExtensions
|
4
|
+
def self.included(base)
|
5
|
+
base.class_eval {
|
6
|
+
alias_method_chain :url, :sites
|
7
|
+
mattr_accessor :current_site
|
8
|
+
has_one :site, :foreign_key => "homepage_id", :dependent => :nullify
|
9
|
+
}
|
10
|
+
base.extend ClassMethods
|
11
|
+
class << base
|
12
|
+
def find_by_path(path, live=true)
|
13
|
+
root = homepage
|
14
|
+
raise Page::MissingRootPageError unless root
|
15
|
+
root.find_by_path(path, live)
|
16
|
+
end
|
17
|
+
def current_site
|
18
|
+
@current_site ||= Site.default
|
19
|
+
end
|
20
|
+
def current_site=(site)
|
21
|
+
@current_site = site
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
module ClassMethods
|
27
|
+
def homepage
|
28
|
+
if current_site.is_a?(Site)
|
29
|
+
homepage = self.current_site.homepage
|
30
|
+
end
|
31
|
+
homepage ||= find_by_parent_id(nil)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def url_with_sites
|
36
|
+
if parent
|
37
|
+
parent.child_url(self)
|
38
|
+
else
|
39
|
+
"/"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module MultiSite::PagesControllerExtensions
|
2
|
+
def self.included(base)
|
3
|
+
base.class_eval {
|
4
|
+
alias_method_chain :discover_current_site, :root
|
5
|
+
alias_method_chain :index, :site
|
6
|
+
alias_method_chain :continue_url, :site
|
7
|
+
alias_method_chain :remove, :back
|
8
|
+
responses.destroy.default do
|
9
|
+
return_url = session[:came_from]
|
10
|
+
session[:came_from] = nil
|
11
|
+
if model.class == Page
|
12
|
+
redirect_to return_url || admin_pages_url(:root => model.root.id)
|
13
|
+
else
|
14
|
+
redirect_to continue_url(params)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
# for compatibility with the standard issue of multi_site,
|
21
|
+
# a root parameter overrides other ways of setting site
|
22
|
+
|
23
|
+
def discover_current_site_with_root
|
24
|
+
site_from_root || discover_current_site_without_root
|
25
|
+
end
|
26
|
+
|
27
|
+
def site_from_root
|
28
|
+
if params[:root] && @homepage = Page.find(params[:root])
|
29
|
+
@site = @homepage.root.site
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def index_with_site
|
34
|
+
@site ||= Page.current_site
|
35
|
+
@homepage ||= @site.homepage if @site
|
36
|
+
@homepage ||= Page.homepage
|
37
|
+
response_for :plural
|
38
|
+
end
|
39
|
+
|
40
|
+
def remove_with_back
|
41
|
+
session[:came_from] = request.env["HTTP_REFERER"]
|
42
|
+
remove_without_back
|
43
|
+
end
|
44
|
+
|
45
|
+
def continue_url_with_site(options={})
|
46
|
+
options[:redirect_to] || (params[:continue] ? edit_admin_page_url(model) : admin_pages_url(:root => model.root.id))
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module MultiSite::ResourceControllerExtensions
|
2
|
+
|
3
|
+
def self.included(base)
|
4
|
+
base.class_eval {
|
5
|
+
alias_method_chain :discover_current_site, :input
|
6
|
+
}
|
7
|
+
end
|
8
|
+
|
9
|
+
def current_site=(site=nil)
|
10
|
+
Page.current_site = site
|
11
|
+
set_session_site
|
12
|
+
end
|
13
|
+
|
14
|
+
# among other things this determines whether the site chooser is shown in the submenu
|
15
|
+
|
16
|
+
def sited_model?
|
17
|
+
model_class == Page || model_class.is_site_scoped?
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
def discover_current_site_with_input
|
23
|
+
site_from_param || site_from_session || discover_current_site_without_input
|
24
|
+
end
|
25
|
+
|
26
|
+
# for interface consistency we want to be able to remember site choices between requests
|
27
|
+
|
28
|
+
def set_session_site(site_id=nil)
|
29
|
+
site_id ||= current_site.id.to_s if current_site.is_a? Site
|
30
|
+
session[:site_id] = site_id
|
31
|
+
end
|
32
|
+
|
33
|
+
def site_from_session
|
34
|
+
session[:site_id] && Site.find(session[:site_id]) rescue nil
|
35
|
+
end
|
36
|
+
|
37
|
+
def site_from_param
|
38
|
+
params[:site_id] && Site.find(params[:site_id]) rescue nil
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module MultiSite
|
2
|
+
module RouteExtensions
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.alias_method_chain(:recognition_conditions, :site)
|
6
|
+
end
|
7
|
+
|
8
|
+
def recognition_conditions_with_site
|
9
|
+
result = recognition_conditions_without_site
|
10
|
+
if site_names = conditions.delete(:site)
|
11
|
+
domains = [*site_names].map{ |site| Regexp.compile(::Site.find_by_name(site).domain) }
|
12
|
+
conditions[:site] = Regexp.union(*domains)
|
13
|
+
result << "conditions[:site] === env[:site]"
|
14
|
+
end
|
15
|
+
result
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
ActionController::Routing::Route.send :include, MultiSite::RouteExtensions
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module MultiSite
|
2
|
+
module RouteSetExtensions
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.alias_method_chain :extract_request_environment, :site
|
6
|
+
end
|
7
|
+
|
8
|
+
def extract_request_environment_with_site(request)
|
9
|
+
env = extract_request_environment_without_site(request)
|
10
|
+
env.merge! :site => request.host
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
ActionController::Routing::RouteSet.send :include, MultiSite::RouteSetExtensions
|
@@ -0,0 +1,145 @@
|
|
1
|
+
module MultiSite
|
2
|
+
|
3
|
+
module ScopedModel
|
4
|
+
def self.included(base)
|
5
|
+
base.extend ClassMethods
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
def is_site_scoped?
|
10
|
+
false
|
11
|
+
end
|
12
|
+
|
13
|
+
# only option at the moment is :shareable, which we take to mean that sites are optional:
|
14
|
+
# if true it causes us not to set the site automatically or to validate its presence,
|
15
|
+
# and to extend the scoping conditions so that objects with no site are returned as
|
16
|
+
# well as objects with the specified site
|
17
|
+
# that is, anything without a site is considered to be shared among all sites
|
18
|
+
# the default is false
|
19
|
+
|
20
|
+
def is_site_scoped(options={})
|
21
|
+
return if is_site_scoped?
|
22
|
+
|
23
|
+
options = {
|
24
|
+
:shareable => false
|
25
|
+
}.merge(options)
|
26
|
+
|
27
|
+
class_eval <<-EO
|
28
|
+
extend MultiSite::ScopedModel::ScopedClassMethods
|
29
|
+
include MultiSite::ScopedModel::ScopedInstanceMethods
|
30
|
+
EO
|
31
|
+
|
32
|
+
belongs_to :site
|
33
|
+
Site.send(:has_many, plural_symbol_for_class)
|
34
|
+
|
35
|
+
before_validation :set_site
|
36
|
+
validates_presence_of :site unless options[:shareable]
|
37
|
+
|
38
|
+
class << self
|
39
|
+
attr_accessor :shareable
|
40
|
+
alias_method_chain :all, :site
|
41
|
+
alias_method_chain :where, :site
|
42
|
+
alias_method_chain :paginate, :site
|
43
|
+
%w{count average minimum maximum sum}.each do |getter|
|
44
|
+
alias_method_chain getter.intern, :site
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
self.shareable = options[:shareable]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
module ScopedClassMethods
|
53
|
+
def all_with_site(options = {})
|
54
|
+
return all_without_site(options) unless sites?
|
55
|
+
with_scope(:find => {:conditions => site_scope_condition}) do
|
56
|
+
all_without_site(options)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def where_with_site(options = {})
|
61
|
+
return where_without_site(options) unless sites?
|
62
|
+
with_scope(:find => {:conditions => site_scope_condition}) do
|
63
|
+
where_without_site(options)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def paginate_with_site(options={})
|
68
|
+
return paginate_without_site(options) unless sites?
|
69
|
+
with_scope(:find => {:conditions => site_scope_condition}) do
|
70
|
+
paginate_without_site(options)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
%w{count average minimum maximum sum}.each do |getter|
|
75
|
+
define_method("#{getter}_with_site") do |*args|
|
76
|
+
return send("#{getter}_without_site".intern, *args) unless sites?
|
77
|
+
with_scope(:find => {:conditions => site_scope_condition}) do
|
78
|
+
send "#{getter}_without_site".intern, *args
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# this only works with :all and :first
|
84
|
+
# and should only be used in odd cases like migration.
|
85
|
+
def find_without_site(*args)
|
86
|
+
options = args.extract_options!
|
87
|
+
#set_readonly_option!(options)
|
88
|
+
|
89
|
+
case args.first
|
90
|
+
when :first then find_initial_without_site(options) # defined here
|
91
|
+
when :all then all_without_site(options) # already defined by the alias chain
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def find_initial_without_site(options)
|
96
|
+
options.update(:limit => 1)
|
97
|
+
all_without_site(options).first
|
98
|
+
end
|
99
|
+
|
100
|
+
def sites?
|
101
|
+
Site.table_exists? && Site.several?
|
102
|
+
end
|
103
|
+
|
104
|
+
def current_site!
|
105
|
+
raise(ActiveRecord::SiteNotFound, "#{self} is site-scoped but current_site is #{self.current_site.inspect}", caller) if sites? && !self.current_site && !self.is_shareable?
|
106
|
+
self.current_site
|
107
|
+
end
|
108
|
+
|
109
|
+
def current_site
|
110
|
+
Page.current_site
|
111
|
+
end
|
112
|
+
|
113
|
+
def site_scope_condition
|
114
|
+
if self.shareable
|
115
|
+
condition = ""
|
116
|
+
condition << "#{self.table_name}.site_id = #{self.current_site.id} OR " if self.current_site
|
117
|
+
condition << "#{self.table_name}.site_id IS NULL"
|
118
|
+
else
|
119
|
+
condition = "#{self.table_name}.site_id = #{self.current_site!.id}"
|
120
|
+
end
|
121
|
+
condition
|
122
|
+
end
|
123
|
+
|
124
|
+
def plural_symbol_for_class
|
125
|
+
self.to_s.pluralize.underscore.intern
|
126
|
+
end
|
127
|
+
|
128
|
+
def is_site_scoped?
|
129
|
+
true
|
130
|
+
end
|
131
|
+
|
132
|
+
def is_shareable?
|
133
|
+
!!self.shareable
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
module ScopedInstanceMethods
|
138
|
+
protected
|
139
|
+
def set_site
|
140
|
+
self.site ||= self.class.current_site! unless self.class.is_shareable?
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module MultiSite::ScopedValidation
|
2
|
+
|
3
|
+
def self.included(base)
|
4
|
+
|
5
|
+
base.class_eval do
|
6
|
+
# scoping validations to the site should be very simple
|
7
|
+
# all you would normally need is something like this:
|
8
|
+
#
|
9
|
+
# validates_uniqueness_of :email, :scope => :site_id
|
10
|
+
#
|
11
|
+
# but if you want to scope core trusty classes, you have a problem:
|
12
|
+
# their uniqueness validations have already been declared
|
13
|
+
# The only answer is to reach right back and change the validates_uniqueness_of method
|
14
|
+
# and to make it more awkward, that has to happen so early that we can't reflect on the site association.
|
15
|
+
# Hence the check for a site_id column. It's a hack, but a fairly harmless one.
|
16
|
+
|
17
|
+
def validates_uniqueness_of_with_site(*attr)
|
18
|
+
if table_exists? && column_names.include?('site_id')
|
19
|
+
configuration = attr.extract_options!
|
20
|
+
configuration[:scope] ||= :site_id
|
21
|
+
attr.push(configuration)
|
22
|
+
end
|
23
|
+
validates_uniqueness_of_without_site(*attr)
|
24
|
+
end
|
25
|
+
|
26
|
+
alias_method_chain :validates_uniqueness_of, :site
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
ActiveRecord::Validations::ClassMethods.send :include, MultiSite::ScopedValidation
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module MultiSite::SiteChooserHelper
|
2
|
+
|
3
|
+
def sites_chooser_thing
|
4
|
+
return "" unless admin? && defined?(Site) && defined?(controller) && controller.sited_model? && controller.template_name == 'index' && Site.several?
|
5
|
+
options = Site.find(:all).map{ |site| "<li>" + link_to( site.name, "#{request.path}?site_id=#{site.id}", :class => site == current_site ? 'fg' : '') + "</li>" }.join("")
|
6
|
+
chooser = %{<div id="site_chooser">}
|
7
|
+
#chooser << link_to("sites", admin_sites_url, {:id => 'show_site_list', :class => 'expandable'})
|
8
|
+
chooser << %{<ul id="nav"><li>Current Site: #{current_site.name}}
|
9
|
+
chooser << %{<ul class="expansion">#{options}</ul></li></ul>}
|
10
|
+
chooser << %{</div>}
|
11
|
+
chooser
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
namespace :trusty do
|
2
|
+
namespace :extensions do
|
3
|
+
namespace :multi_site do
|
4
|
+
|
5
|
+
desc "Runs the migration of the Multi Site extension"
|
6
|
+
task :migrate => :environment do
|
7
|
+
require 'trusty_cms/extension_migrator'
|
8
|
+
if ENV["VERSION"]
|
9
|
+
MultiSiteExtension.migrator.migrate(ENV["VERSION"].to_i)
|
10
|
+
else
|
11
|
+
MultiSiteExtension.migrator.migrate
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "Copies public assets of the Multi Site to the instance public/ directory."
|
16
|
+
task :update => :environment do
|
17
|
+
is_svn_or_dir = proc {|path| path =~ /\.svn/ || File.directory?(path) }
|
18
|
+
puts "Copying assets from MultiSiteExtension"
|
19
|
+
Dir[MultiSiteExtension.root + "/public/**/*"].reject(&is_svn_or_dir).each do |file|
|
20
|
+
path = file.sub(MultiSiteExtension.root, '')
|
21
|
+
directory = File.dirname(path)
|
22
|
+
mkdir_p RAILS_ROOT + directory, :verbose => false
|
23
|
+
cp file, RAILS_ROOT + path, :verbose => false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
namespace :radiant do
|
2
|
+
namespace :extensions do
|
3
|
+
namespace :scoped_admin do
|
4
|
+
|
5
|
+
desc "Runs the migration of the Scoped Admin extension"
|
6
|
+
task :migrate => :environment do
|
7
|
+
require 'radiant/extension_migrator'
|
8
|
+
if ENV["VERSION"]
|
9
|
+
ScopedAdminExtension.migrator.migrate(ENV["VERSION"].to_i)
|
10
|
+
else
|
11
|
+
ScopedAdminExtension.migrator.migrate
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "Copies public assets of the Scoped Admin to the instance public/ directory."
|
16
|
+
task :update => :environment do
|
17
|
+
is_svn_or_dir = proc {|path| path =~ /\.svn/ || File.directory?(path) }
|
18
|
+
puts "Copying assets from ScopedAdminExtension"
|
19
|
+
Dir[ScopedAdminExtension.root + "/public/**/*"].reject(&is_svn_or_dir).each do |file|
|
20
|
+
path = file.sub(ScopedAdminExtension.root, '')
|
21
|
+
directory = File.dirname(path)
|
22
|
+
mkdir_p RAILS_ROOT + directory
|
23
|
+
cp file, RAILS_ROOT + path
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
# Nothing to see here
|