trusty-multi-site-extension 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|