alchemy_cms 2.0.pre3 → 2.0.pre4
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/.rspec +3 -0
- data/Gemfile +10 -4
- data/alchemy_cms.gemspec +6 -2
- data/app/controllers/alchemy_controller.rb +4 -6
- data/app/helpers/pages_helper.rb +5 -15
- data/app/models/language.rb +10 -2
- data/app/models/page.rb +12 -20
- data/config/alchemy/config.yml +1 -0
- data/config/initializers/fast_gettext.rb +2 -1
- data/config/initializers/tiny_mce_hammer.rb +27 -27
- data/db/migrate/20110919110451_add_default_role_to_users.rb +9 -0
- data/lib/alchemy/capistrano.rb +93 -0
- data/lib/alchemy/version.rb +1 -1
- data/spec/dummy/db/schema.rb +9 -9
- data/spec/factories.rb +43 -0
- data/spec/integration/security_spec.rb +2 -2
- data/spec/language_spec.rb +29 -0
- data/spec/page_spec.rb +50 -0
- data/spec/spec_helper.rb +8 -5
- data/spec/user_spec.rb +10 -0
- metadata +64 -9
- data/app/helpers/errors_helper.rb +0 -37
- data/lib/vendor/i18n_label.rb +0 -23
- data/recipes/alchemy_capistrano_tasks.rb +0 -83
data/.rspec
ADDED
data/Gemfile
CHANGED
@@ -3,9 +3,15 @@ source "http://rubygems.org"
|
|
3
3
|
# Specify your gem's dependencies in alchemy.gemspec
|
4
4
|
gemspec
|
5
5
|
|
6
|
-
group :development do
|
6
|
+
group :development, :test do
|
7
7
|
gem 'gettext', '~>2.0', :git => 'git://github.com/cameel/gettext.git', :require => false
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
gem "rspec-rails", ">= 2.0.0.beta"
|
9
|
+
end
|
10
|
+
|
11
|
+
group :test do
|
12
|
+
gem 'factory_girl_rails'
|
13
|
+
gem "capybara", ">= 0.4.0"
|
14
|
+
gem "launchy"
|
15
|
+
gem "sqlite3"
|
16
|
+
gem "database_cleaner"
|
11
17
|
end
|
data/alchemy_cms.gemspec
CHANGED
@@ -9,8 +9,8 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.authors = ["Thomas von Deyen", "Robin Böning", "Carsten Fregin"]
|
10
10
|
s.email = ["alchemy@magiclabs.de"]
|
11
11
|
s.homepage = "http://alchemy-cms.com"
|
12
|
-
s.summary = %q{
|
13
|
-
s.description = %q{
|
12
|
+
s.summary = %q{An extremly flexbile CMS for Rails 3.}
|
13
|
+
s.description = %q{Alchemy is an awesome Rails CMS with an extremely flexible content storing architecture.}
|
14
14
|
s.requirements << 'ImageMagick (libmagick), v6.6 or greater.'
|
15
15
|
s.license = 'GPL-3'
|
16
16
|
|
@@ -33,4 +33,8 @@ Gem::Specification.new do |s|
|
|
33
33
|
s.add_runtime_dependency(%q<jquery-rails>, ["~> 1.0"])
|
34
34
|
s.add_runtime_dependency(%q<tinymce_hammer>, ["~> 0.2"])
|
35
35
|
s.add_runtime_dependency(%q<attachment_magic>, ["~> 0.1"])
|
36
|
+
|
37
|
+
s.add_development_dependency(%q<capybara>, [">= 0.4.0"])
|
38
|
+
s.add_development_dependency(%q<rspec-rails>, [">= 2.0.0.beta"])
|
39
|
+
s.add_development_dependency(%q<sqlite3>)
|
36
40
|
end
|
@@ -19,7 +19,7 @@ class AlchemyController < ApplicationController
|
|
19
19
|
before_filter :mailer_set_url_options
|
20
20
|
|
21
21
|
helper_method :current_server, :configuration, :multi_language?, :current_user, :clipboard_empty?, :trash_empty?, :get_clipboard
|
22
|
-
helper :
|
22
|
+
helper :layout
|
23
23
|
|
24
24
|
def render_errors_or_redirect(object, redicrect_url, flash_notice, button = nil)
|
25
25
|
if object.errors.empty?
|
@@ -32,7 +32,7 @@ class AlchemyController < ApplicationController
|
|
32
32
|
|
33
33
|
def render_remote_errors(object, button = nil)
|
34
34
|
render :update do |page|
|
35
|
-
page << "jQuery('#errors').html('<ul>" + object.errors.sum{|a, b| "<li>" + _(b) + "</li>"} + "</ul>')"
|
35
|
+
page << "jQuery('#errors').html('<ul>" + object.errors.sum { |a, b| "<li>" + _(b) + "</li>" } + "</ul>')"
|
36
36
|
page << "jQuery('#errors').show()"
|
37
37
|
page << "Alchemy.enableButton('#{button}')" unless button.blank?
|
38
38
|
end
|
@@ -137,7 +137,6 @@ private
|
|
137
137
|
end
|
138
138
|
|
139
139
|
def set_stamper
|
140
|
-
FastGettext.text_domain = 'alchemy'
|
141
140
|
User.stamper = self.current_user
|
142
141
|
end
|
143
142
|
|
@@ -152,7 +151,6 @@ private
|
|
152
151
|
protected
|
153
152
|
|
154
153
|
def init_gettext#:nodoc:
|
155
|
-
FastGettext.text_domain = 'alchemy'
|
156
154
|
FastGettext.available_locales = configuration(:translations).collect { |l| l[:language_code] }
|
157
155
|
end
|
158
156
|
|
@@ -160,9 +158,9 @@ protected
|
|
160
158
|
# You can set the default_translation in your config/alchemy/config.yml file
|
161
159
|
def set_translation
|
162
160
|
if current_user.blank? || current_user.language.blank?
|
163
|
-
FastGettext.locale = configuration(:default_translation)
|
161
|
+
FastGettext.locale = configuration(:default_translation) || I18n.locale
|
164
162
|
else
|
165
|
-
FastGettext.locale = current_user.language
|
163
|
+
FastGettext.locale = current_user.language || I18n.locale
|
166
164
|
end
|
167
165
|
end
|
168
166
|
|
data/app/helpers/pages_helper.rb
CHANGED
@@ -92,23 +92,15 @@ module PagesHelper
|
|
92
92
|
end
|
93
93
|
page = page_found_by_layout || page
|
94
94
|
page = (options[:link_to_public_child] ? (page.first_public_child.blank? ? nil : page.first_public_child) : nil) if !page.public?
|
95
|
-
|
95
|
+
|
96
96
|
if !page.blank?
|
97
97
|
active = session[:language_id] == page.language.id
|
98
|
-
|
99
|
-
if options[:linkname].to_sym == :code
|
100
|
-
linkname = page.language.code
|
101
|
-
else
|
102
|
-
linkname = I18n.t("alchemy.languages.#{page.language.code}.name", :default => page.language.name)
|
103
|
-
end
|
104
|
-
else
|
105
|
-
linkname = ""
|
106
|
-
end
|
98
|
+
linkname = page.language.label(options[:linkname])
|
107
99
|
if options[:as_select_box]
|
108
100
|
languages << [linkname, show_page_with_language_url(:urlname => page.urlname, :lang => page.language.code)]
|
109
101
|
else
|
110
102
|
languages << link_to(
|
111
|
-
"#{content_tag(:span, '', :class => "flag")}#{ content_tag(:span, linkname)}",
|
103
|
+
"#{content_tag(:span, '', :class => "flag")}#{ content_tag(:span, linkname)}".html_safe,
|
112
104
|
show_page_with_language_path(:urlname => page.urlname, :lang => page.language.code),
|
113
105
|
:class => "#{(active ? 'active ' : nil)}#{page.language.code} #{(i == 0) ? 'first' : (i==pages.length-1) ? 'last' : nil}",
|
114
106
|
:title => options[:show_title] ? I18n.t("alchemy.languages.#{page.language.code}.title", :default => page.language.name) : nil
|
@@ -128,13 +120,11 @@ module PagesHelper
|
|
128
120
|
)
|
129
121
|
else
|
130
122
|
if options[:spacer].blank?
|
131
|
-
return languages
|
123
|
+
return languages.html_safe
|
132
124
|
else
|
133
|
-
return languages.join(options[:spacer])
|
125
|
+
return languages.join(options[:spacer]).html_safe
|
134
126
|
end
|
135
127
|
end
|
136
|
-
else
|
137
|
-
""
|
138
128
|
end
|
139
129
|
end
|
140
130
|
|
data/app/models/language.rb
CHANGED
@@ -30,11 +30,19 @@ class Language < ActiveRecord::Base
|
|
30
30
|
self.find_by_default(true)
|
31
31
|
end
|
32
32
|
|
33
|
+
def label(attrib)
|
34
|
+
if attrib.to_sym == :code
|
35
|
+
self.code
|
36
|
+
else
|
37
|
+
I18n.t("name", :scope => "alchemy.languages.#{self.code}", :default => self.name)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
33
41
|
private
|
34
42
|
|
35
43
|
def publicity_of_default_language
|
36
44
|
if self.default? && !self.public?
|
37
|
-
errors.
|
45
|
+
errors.add(:base, N_("Defaut language has to be public"))
|
38
46
|
return false
|
39
47
|
else
|
40
48
|
return true
|
@@ -43,7 +51,7 @@ private
|
|
43
51
|
|
44
52
|
def presence_of_default_language
|
45
53
|
if Language.get_default == self && self.default_changed?
|
46
|
-
errors.
|
54
|
+
errors.add(:base, N_("we_need_at_least_one_default"))
|
47
55
|
return false
|
48
56
|
else
|
49
57
|
return true
|
data/app/models/page.rb
CHANGED
@@ -128,7 +128,7 @@ class Page < ActiveRecord::Base
|
|
128
128
|
end
|
129
129
|
|
130
130
|
def set_url_name
|
131
|
-
self.urlname =
|
131
|
+
self.urlname = convert_url_name((self.urlname.blank? ? self.name : self.urlname))
|
132
132
|
end
|
133
133
|
|
134
134
|
def set_title
|
@@ -201,6 +201,7 @@ class Page < ActiveRecord::Base
|
|
201
201
|
end
|
202
202
|
|
203
203
|
# Returns the translated explanation of seven the page stati.
|
204
|
+
# TODO: Let I18n do this!
|
204
205
|
def humanized_status
|
205
206
|
case self.status
|
206
207
|
when 0
|
@@ -319,7 +320,7 @@ class Page < ActiveRecord::Base
|
|
319
320
|
end
|
320
321
|
|
321
322
|
def first_public_child
|
322
|
-
self.children.where(:public => true).limit(1)
|
323
|
+
self.children.where(:public => true).limit(1).first
|
323
324
|
end
|
324
325
|
|
325
326
|
def self.language_root_for(language_id)
|
@@ -455,24 +456,15 @@ private
|
|
455
456
|
end
|
456
457
|
return Page.where(conditions).order(order_direction).limit(1)
|
457
458
|
end
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
new_url_name = new_url_name.gsub(/[ß]/, 'ss')
|
468
|
-
new_url_name = new_url_name.gsub(/[^a-zA-Z0-9_]+/, '-')
|
469
|
-
if(new_url_name.length < 3)
|
470
|
-
new_url_name = "-#{new_url_name}-"
|
471
|
-
else
|
472
|
-
new_url_name.gsub(/-+$/, '')
|
473
|
-
end
|
474
|
-
end
|
475
|
-
|
459
|
+
|
460
|
+
# Converts the given nbame into an url friendly string
|
461
|
+
# Names shorter than 3 will be filled with dashes, so it does not collidate with the language code.
|
462
|
+
def convert_url_name(name)
|
463
|
+
url_name = name.gsub(/[äÄ]/, 'ae').gsub(/[üÜ]/, 'ue').gsub(/[öÖ]/, 'oe').parameterize
|
464
|
+
url_name = ('-' * (3 - url_name.length)) + url_name if url_name.length < 3
|
465
|
+
return url_name
|
466
|
+
end
|
467
|
+
|
476
468
|
# Looks in the layout_descripion, if there are elements to autogenerate.
|
477
469
|
# If so, it generates them.
|
478
470
|
def autogenerate_elements
|
data/config/alchemy/config.yml
CHANGED
@@ -93,6 +93,7 @@ default_language:
|
|
93
93
|
:page_layout_name: contact
|
94
94
|
:forward_to_page: false
|
95
95
|
:mail_success_page: thanks
|
96
|
+
:mail_from: your.mail@your-domain.com
|
96
97
|
:fields: [salutation, firstname, lastname, address, zip, city, phone, email, message]
|
97
98
|
:validate_fields:
|
98
99
|
:lastname:
|
@@ -1,2 +1,3 @@
|
|
1
1
|
require 'fast_gettext'
|
2
|
-
FastGettext.add_text_domain 'alchemy', :path => File.join(File.dirname(__FILE__), '..', '..', 'locale')
|
2
|
+
FastGettext.add_text_domain 'alchemy', :path => File.join(File.dirname(__FILE__), '..', '..', 'locale')
|
3
|
+
FastGettext.default_text_domain = 'alchemy'
|
@@ -2,31 +2,31 @@ if defined?(Tinymce::Hammer)
|
|
2
2
|
Tinymce::Hammer.install_path = '/javascripts/alchemy/tiny_mce'
|
3
3
|
Tinymce::Hammer.plugins = %w(safari paste fullscreen inlinepopups alchemy_link)
|
4
4
|
Tinymce::Hammer.languages = ['de', 'en']
|
5
|
-
Tinymce::Hammer.init =
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
5
|
+
Tinymce::Hammer.init = {
|
6
|
+
:paste_convert_headers_to_strong => true,
|
7
|
+
:paste_convert_middot_lists => true,
|
8
|
+
:paste_remove_spans => true,
|
9
|
+
:paste_remove_styles => true,
|
10
|
+
:paste_strip_class_attributes => true,
|
11
|
+
:theme => 'advanced',
|
12
|
+
:skin => 'o2k7',
|
13
|
+
:skin_variant => 'silver',
|
14
|
+
:inlinepopups_skin => 'alchemy',
|
15
|
+
:popup_css => "/stylesheets/alchemy/alchemy_tinymce_dialog.css",
|
16
|
+
:content_css => "/stylesheets/alchemy/alchemy_tinymce_content.css",
|
17
|
+
:dialog_type => "modal",
|
18
|
+
:width => "100%",
|
19
|
+
:height => '185',
|
20
|
+
:theme_advanced_toolbar_align => 'left',
|
21
|
+
:theme_advanced_toolbar_location => 'top',
|
22
|
+
:theme_advanced_statusbar_location => 'bottom',
|
23
|
+
:theme_advanced_buttons1 => 'bold,italic,underline,strikethrough,sub,sup,|,numlist,bullist,indent,outdent,|,alchemy_link,unlink,|,removeformat,cleanup,|,fullscreen',
|
24
|
+
:theme_advanced_buttons2 => 'pastetext,pasteword,charmap,code,help',
|
25
|
+
:theme_advanced_buttons3 => '',
|
26
|
+
:theme_advanced_resizing => 'true',
|
27
|
+
:theme_advanced_resize_horizontal => false,
|
28
|
+
:theme_advanced_resizing_min_height => '185',
|
29
|
+
:fix_list_elements => true,
|
30
|
+
:convert_urls => false
|
31
|
+
}
|
32
32
|
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# This recipe contains Capistrano recipes for handling the uploads, ferret index and picture cache files while deploying your application.
|
2
|
+
# It also contains a ferret:rebuild_index task to rebuild the index after deploying your application.
|
3
|
+
|
4
|
+
Capistrano::Configuration.instance(:must_exist).load do
|
5
|
+
|
6
|
+
after "deploy:setup", "alchemy:shared_folders:create"
|
7
|
+
after "deploy:symlink", "alchemy:shared_folders:symlink"
|
8
|
+
|
9
|
+
before "deploy:restart", "alchemy:files:copy"
|
10
|
+
|
11
|
+
namespace :alchemy do
|
12
|
+
|
13
|
+
namespace :shared_folders do
|
14
|
+
|
15
|
+
# This task creates the shared folders for uploads, picture cache and ferret index while setting up your server.
|
16
|
+
# Call after deploy:setup like +after "deploy:setup", "alchemy:create_shared_folders"+ in your +deploy.rb+.
|
17
|
+
desc "Creates the uploads and picture cache directory in the shared folder. Call after deploy:setup"
|
18
|
+
task :create, :roles => :app do
|
19
|
+
run "mkdir -p #{shared_path}/uploads"
|
20
|
+
run "mkdir -p #{shared_path}/index"
|
21
|
+
run "mkdir -p #{shared_path}/uploads/pictures"
|
22
|
+
run "mkdir -p #{shared_path}/uploads/attachments"
|
23
|
+
run "mkdir -p #{shared_path}/cache"
|
24
|
+
run "mkdir -p #{shared_path}/cache/pictures"
|
25
|
+
end
|
26
|
+
|
27
|
+
# This task sets the symlinks for uploads, picture cache and ferret index folder.
|
28
|
+
# Call after deploy:symlink like +after "deploy:symlink", "alchemy:symlink_folders"+ in your +deploy.rb+.
|
29
|
+
desc "Sets the symlinks for uploads, picture cache and ferret index folder. Call after deploy:symlink"
|
30
|
+
task :symlink, :roles => :app do
|
31
|
+
run "rm -rf #{current_path}/public/uploads/*"
|
32
|
+
run "ln -nfs #{shared_path}/uploads/pictures/ #{current_path}/uploads/pictures"
|
33
|
+
run "ln -nfs #{shared_path}/uploads/attachments/ #{current_path}/uploads/attachments"
|
34
|
+
run "rm -rf #{current_path}/public/pictures"
|
35
|
+
run "ln -nfs #{shared_path}/cache/pictures/ #{current_path}/public/pictures"
|
36
|
+
run "rm -rf #{current_path}/index"
|
37
|
+
run "ln -nfs #{shared_path}/index/ #{current_path}/index"
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
namespace :files do
|
43
|
+
|
44
|
+
desc "Copies all assets and migration files from Alchemy to project"
|
45
|
+
task :copy do
|
46
|
+
run "cd #{current_path} && RAILS_ENV=production #{rake} alchemy:assets:copy:all"
|
47
|
+
run "cd #{current_path} && RAILS_ENV=production #{rake} alchemy:migrations:sync"
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
namespace :database_yml do
|
53
|
+
|
54
|
+
desc "Creates the database.yml file"
|
55
|
+
task :create do
|
56
|
+
db_config = ERB.new <<-EOF
|
57
|
+
production:
|
58
|
+
adapter: mysql
|
59
|
+
encoding: utf8
|
60
|
+
reconnect: false
|
61
|
+
pool: 5
|
62
|
+
database: #{ Capistrano::CLI.ui.ask("Database name: ") }
|
63
|
+
username: #{ Capistrano::CLI.ui.ask("Database username: ") }
|
64
|
+
password: #{ Capistrano::CLI.ui.ask("Database password: ") }
|
65
|
+
socket: #{ Capistrano::CLI.ui.ask("Database socket: ") }
|
66
|
+
host: #{ Capistrano::CLI.ui.ask("Database host: ") }
|
67
|
+
EOF
|
68
|
+
run "mkdir -p #{shared_path}/config"
|
69
|
+
put db_config.result, "#{shared_path}/config/database.yml"
|
70
|
+
end
|
71
|
+
|
72
|
+
desc "Symlinks the database.yml file from shared folder into config folder"
|
73
|
+
task :symlink, :except => { :no_release => true } do
|
74
|
+
run "ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml"
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
namespace :ferret do
|
82
|
+
|
83
|
+
# This task rebuilds the ferret index for the EssenceText and EssenceRichtext Models.
|
84
|
+
# Call it before deploy:restart like +before "deploy:restart", "alchemy:rebuild_index"+ in your +deploy.rb+.
|
85
|
+
# It uses the +alchemy:rebuild_index+ rake task found in +vendor/plugins/alchemy/lib/tasks+.
|
86
|
+
desc "Rebuild the ferret index. Call before deploy:restart"
|
87
|
+
task :rebuild_index, :roles => :app do
|
88
|
+
run "cd #{current_path} && RAILS_ENV=production #{rake} ferret:rebuild_index"
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
data/lib/alchemy/version.rb
CHANGED
data/spec/dummy/db/schema.rb
CHANGED
@@ -10,7 +10,7 @@
|
|
10
10
|
#
|
11
11
|
# It's strongly recommended to check this file into your version control system.
|
12
12
|
|
13
|
-
ActiveRecord::Schema.define(:version =>
|
13
|
+
ActiveRecord::Schema.define(:version => 20110919110451) do
|
14
14
|
|
15
15
|
create_table "attachments", :force => true do |t|
|
16
16
|
t.string "name"
|
@@ -242,20 +242,20 @@ ActiveRecord::Schema.define(:version => 20110711142057) do
|
|
242
242
|
t.string "login"
|
243
243
|
t.string "email"
|
244
244
|
t.string "gender"
|
245
|
-
t.string "role"
|
245
|
+
t.string "role", :default => "registered"
|
246
246
|
t.string "language"
|
247
|
-
t.string "crypted_password", :limit => 128, :default => "",
|
248
|
-
t.string "password_salt", :limit => 128, :default => "",
|
249
|
-
t.integer "login_count", :default => 0,
|
250
|
-
t.integer "failed_login_count", :default => 0,
|
247
|
+
t.string "crypted_password", :limit => 128, :default => "", :null => false
|
248
|
+
t.string "password_salt", :limit => 128, :default => "", :null => false
|
249
|
+
t.integer "login_count", :default => 0, :null => false
|
250
|
+
t.integer "failed_login_count", :default => 0, :null => false
|
251
251
|
t.datetime "last_request_at"
|
252
252
|
t.datetime "current_login_at"
|
253
253
|
t.datetime "last_login_at"
|
254
254
|
t.string "current_login_ip"
|
255
255
|
t.string "last_login_ip"
|
256
|
-
t.string "persistence_token",
|
257
|
-
t.string "single_access_token",
|
258
|
-
t.string "perishable_token",
|
256
|
+
t.string "persistence_token", :null => false
|
257
|
+
t.string "single_access_token", :null => false
|
258
|
+
t.string "perishable_token", :null => false
|
259
259
|
t.datetime "created_at"
|
260
260
|
t.datetime "updated_at"
|
261
261
|
t.integer "creator_id"
|
data/spec/factories.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
|
3
|
+
factory :user do
|
4
|
+
email 'john@doe.com'
|
5
|
+
login "jdoe"
|
6
|
+
password 's3cr3t'
|
7
|
+
password_confirmation 's3cr3t'
|
8
|
+
|
9
|
+
factory :admin_user do
|
10
|
+
role "admin"
|
11
|
+
end
|
12
|
+
|
13
|
+
factory :registered_user do
|
14
|
+
role "registered"
|
15
|
+
end
|
16
|
+
|
17
|
+
factory :author_user do
|
18
|
+
role "author"
|
19
|
+
end
|
20
|
+
|
21
|
+
factory :editor_user do
|
22
|
+
role "editor"
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
factory :language do
|
28
|
+
code "kl"
|
29
|
+
name 'Klingonian'
|
30
|
+
default false
|
31
|
+
frontpage_name 'tuq'
|
32
|
+
page_layout 'intro'
|
33
|
+
public true
|
34
|
+
end
|
35
|
+
|
36
|
+
factory :page do
|
37
|
+
name "tuq"
|
38
|
+
page_layout "intro"
|
39
|
+
association :language
|
40
|
+
public false
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -14,8 +14,8 @@ describe "Security: " do
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
context "If users are present" do
|
18
|
-
it "
|
17
|
+
context "If on or more users are present" do
|
18
|
+
it "a visitor should not be able to signup" do
|
19
19
|
@user = User.create({:login => 'foo', :email => 'foo@bar.com', :password => 's3cr3t', :password_confirmation => 's3cr3t'})
|
20
20
|
visit '/admin/signup'
|
21
21
|
within('#alchemy_greeting') { page.should_not have_content('have to signup') }
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Language do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
@language = Factory(:language)
|
7
|
+
end
|
8
|
+
|
9
|
+
after(:all) do
|
10
|
+
@language.destroy if @language
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should return a label for code" do
|
14
|
+
@language.label(:code).should == 'kl'
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should return a label for name" do
|
18
|
+
@language.label(:name).should == 'Klingonian'
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should not be deletable if it is the default language" do
|
22
|
+
@default_language = Language.find_by_default(true)
|
23
|
+
if !@default_language
|
24
|
+
@default_language = Factory(:language, :name => "default", :code => "aa", :frontpage_name => "intro", :default => true)
|
25
|
+
end
|
26
|
+
expect { @default_language.destroy }.should raise_error
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
data/spec/page_spec.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Page do
|
4
|
+
|
5
|
+
it "should get a webfriendly urlname on create" do
|
6
|
+
page = Factory(:page, :name => 'klingon$&stößel ')
|
7
|
+
page.urlname.should == 'klingon-stoessel'
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should generate a three letter urlname from two letter name" do
|
11
|
+
page = Factory(:page, :name => 'Au')
|
12
|
+
page.urlname.should == '-au'
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should generate a three letter urlname from two letter name with umlaut" do
|
16
|
+
page = Factory(:page, :name => 'Aü')
|
17
|
+
page.urlname.should == 'aue'
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should generate a three letter urlname from one letter name" do
|
21
|
+
page = Factory(:page, :name => 'A')
|
22
|
+
page.urlname.should == '--a'
|
23
|
+
end
|
24
|
+
|
25
|
+
context "Root pages" do
|
26
|
+
it "should contain one ore more rootpages" do
|
27
|
+
Page.where(:parent_id => nil).any?
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "with children" do
|
32
|
+
before(:each) do
|
33
|
+
@page = Factory(:page)
|
34
|
+
@first_child = Factory(:page, :name => "First child", :language => @page.language, :public => false)
|
35
|
+
@first_child.move_to_child_of(@page)
|
36
|
+
|
37
|
+
@first_public_child = Factory(:page, :name => "First public child", :language => @page.language, :public => true)
|
38
|
+
@first_public_child.move_to_child_of(@page)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should return a page object (or nil if no public children exists) for first_public_child" do
|
42
|
+
if @page.children.any?
|
43
|
+
@page.first_public_child.should == @first_public_child
|
44
|
+
else
|
45
|
+
@page.first_public_child.should == nil
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -8,6 +8,12 @@ FastGettext.text_domain = 'alchemy'
|
|
8
8
|
require File.expand_path("../dummy/config/environment.rb", __FILE__)
|
9
9
|
require "rails/test_help"
|
10
10
|
require "rspec/rails"
|
11
|
+
require 'factory_girl'
|
12
|
+
require 'database_cleaner'
|
13
|
+
require 'factories.rb'
|
14
|
+
|
15
|
+
DatabaseCleaner.strategy = :truncation
|
16
|
+
DatabaseCleaner.clean
|
11
17
|
|
12
18
|
ActionMailer::Base.delivery_method = :test
|
13
19
|
ActionMailer::Base.perform_deliveries = true
|
@@ -27,14 +33,11 @@ ActiveRecord::Migrator.migrate File.expand_path("../dummy/db/migrate/", __FILE__
|
|
27
33
|
Alchemy::Seeder.seed!
|
28
34
|
|
29
35
|
# Load support files
|
30
|
-
Dir[
|
36
|
+
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
|
31
37
|
|
32
38
|
RSpec.configure do |config|
|
33
|
-
# Remove this line if you don't want RSpec's should and should_not
|
34
|
-
# methods or matchers
|
35
39
|
require 'rspec/expectations'
|
36
40
|
config.include RSpec::Matchers
|
37
|
-
|
38
|
-
# == Mock Framework
|
39
41
|
config.mock_with :rspec
|
42
|
+
config.use_transactional_fixtures = true
|
40
43
|
end
|
data/spec/user_spec.rb
ADDED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: alchemy_cms
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 1923831921
|
5
5
|
prerelease: 4
|
6
6
|
segments:
|
7
7
|
- 2
|
8
8
|
- 0
|
9
9
|
- pre
|
10
|
-
-
|
11
|
-
version: 2.0.
|
10
|
+
- 4
|
11
|
+
version: 2.0.pre4
|
12
12
|
platform: ruby
|
13
13
|
authors:
|
14
14
|
- Thomas von Deyen
|
@@ -18,7 +18,7 @@ autorequire:
|
|
18
18
|
bindir: bin
|
19
19
|
cert_chain: []
|
20
20
|
|
21
|
-
date: 2011-09-
|
21
|
+
date: 2011-09-28 00:00:00 Z
|
22
22
|
dependencies:
|
23
23
|
- !ruby/object:Gem::Dependency
|
24
24
|
name: rails
|
@@ -232,7 +232,54 @@ dependencies:
|
|
232
232
|
version: "0.1"
|
233
233
|
type: :runtime
|
234
234
|
version_requirements: *id014
|
235
|
-
|
235
|
+
- !ruby/object:Gem::Dependency
|
236
|
+
name: capybara
|
237
|
+
prerelease: false
|
238
|
+
requirement: &id015 !ruby/object:Gem::Requirement
|
239
|
+
none: false
|
240
|
+
requirements:
|
241
|
+
- - ">="
|
242
|
+
- !ruby/object:Gem::Version
|
243
|
+
hash: 15
|
244
|
+
segments:
|
245
|
+
- 0
|
246
|
+
- 4
|
247
|
+
- 0
|
248
|
+
version: 0.4.0
|
249
|
+
type: :development
|
250
|
+
version_requirements: *id015
|
251
|
+
- !ruby/object:Gem::Dependency
|
252
|
+
name: rspec-rails
|
253
|
+
prerelease: false
|
254
|
+
requirement: &id016 !ruby/object:Gem::Requirement
|
255
|
+
none: false
|
256
|
+
requirements:
|
257
|
+
- - ">="
|
258
|
+
- !ruby/object:Gem::Version
|
259
|
+
hash: 31098209
|
260
|
+
segments:
|
261
|
+
- 2
|
262
|
+
- 0
|
263
|
+
- 0
|
264
|
+
- beta
|
265
|
+
version: 2.0.0.beta
|
266
|
+
type: :development
|
267
|
+
version_requirements: *id016
|
268
|
+
- !ruby/object:Gem::Dependency
|
269
|
+
name: sqlite3
|
270
|
+
prerelease: false
|
271
|
+
requirement: &id017 !ruby/object:Gem::Requirement
|
272
|
+
none: false
|
273
|
+
requirements:
|
274
|
+
- - ">="
|
275
|
+
- !ruby/object:Gem::Version
|
276
|
+
hash: 3
|
277
|
+
segments:
|
278
|
+
- 0
|
279
|
+
version: "0"
|
280
|
+
type: :development
|
281
|
+
version_requirements: *id017
|
282
|
+
description: Alchemy is an awesome Rails CMS with an extremely flexible content storing architecture.
|
236
283
|
email:
|
237
284
|
- alchemy@magiclabs.de
|
238
285
|
executables:
|
@@ -243,6 +290,7 @@ extra_rdoc_files: []
|
|
243
290
|
|
244
291
|
files:
|
245
292
|
- .gitignore
|
293
|
+
- .rspec
|
246
294
|
- .yardopts
|
247
295
|
- Gemfile
|
248
296
|
- LICENSE
|
@@ -278,7 +326,6 @@ files:
|
|
278
326
|
- app/helpers/admin/pictures_helper.rb
|
279
327
|
- app/helpers/alchemy_helper.rb
|
280
328
|
- app/helpers/elements_helper.rb
|
281
|
-
- app/helpers/errors_helper.rb
|
282
329
|
- app/helpers/layout_helper.rb
|
283
330
|
- app/helpers/pages_helper.rb
|
284
331
|
- app/mailers/messages.rb
|
@@ -688,6 +735,8 @@ files:
|
|
688
735
|
- db/migrate/20110530102804_change_pages_page_layout_column.rb
|
689
736
|
- db/migrate/20110707190728_add_render_size_to_essence_pictures.rb
|
690
737
|
- db/migrate/20110711142057_change_open_link_in_new_window_to_link_target.rb
|
738
|
+
- db/migrate/20110919110451_add_default_role_to_users.rb
|
739
|
+
- lib/alchemy/capistrano.rb
|
691
740
|
- lib/alchemy/config.rb
|
692
741
|
- lib/alchemy/controller.rb
|
693
742
|
- lib/alchemy/engine.rb
|
@@ -721,7 +770,6 @@ files:
|
|
721
770
|
- lib/tasks/install.rake
|
722
771
|
- lib/tasks/upgrade.rake
|
723
772
|
- lib/translation_extras/alchemy_core_modules.rb
|
724
|
-
- lib/vendor/i18n_label.rb
|
725
773
|
- locale/alchemy.pot
|
726
774
|
- locale/de/LC_MESSAGES/alchemy.mo
|
727
775
|
- locale/de/alchemy.po
|
@@ -729,7 +777,6 @@ files:
|
|
729
777
|
- locale/en/alchemy.po
|
730
778
|
- locale/missing_translations.rb
|
731
779
|
- locale/model_attributes.rb
|
732
|
-
- recipes/alchemy_capistrano_tasks.rb
|
733
780
|
- spec/alchemy_spec.rb
|
734
781
|
- spec/config_spec.rb
|
735
782
|
- spec/dummy/Rakefile
|
@@ -909,9 +956,13 @@ files:
|
|
909
956
|
- spec/dummy/public/stylesheets/alchemy/jquery.sb.css
|
910
957
|
- spec/dummy/public/stylesheets/alchemy/standard_set.css
|
911
958
|
- spec/dummy/script/rails
|
959
|
+
- spec/factories.rb
|
912
960
|
- spec/integration/navigation_spec.rb
|
913
961
|
- spec/integration/security_spec.rb
|
962
|
+
- spec/language_spec.rb
|
963
|
+
- spec/page_spec.rb
|
914
964
|
- spec/spec_helper.rb
|
965
|
+
- spec/user_spec.rb
|
915
966
|
homepage: http://alchemy-cms.com
|
916
967
|
licenses:
|
917
968
|
- GPL-3
|
@@ -946,7 +997,7 @@ rubyforge_project:
|
|
946
997
|
rubygems_version: 1.8.10
|
947
998
|
signing_key:
|
948
999
|
specification_version: 3
|
949
|
-
summary:
|
1000
|
+
summary: An extremly flexbile CMS for Rails 3.
|
950
1001
|
test_files:
|
951
1002
|
- spec/alchemy_spec.rb
|
952
1003
|
- spec/config_spec.rb
|
@@ -1127,6 +1178,10 @@ test_files:
|
|
1127
1178
|
- spec/dummy/public/stylesheets/alchemy/jquery.sb.css
|
1128
1179
|
- spec/dummy/public/stylesheets/alchemy/standard_set.css
|
1129
1180
|
- spec/dummy/script/rails
|
1181
|
+
- spec/factories.rb
|
1130
1182
|
- spec/integration/navigation_spec.rb
|
1131
1183
|
- spec/integration/security_spec.rb
|
1184
|
+
- spec/language_spec.rb
|
1185
|
+
- spec/page_spec.rb
|
1132
1186
|
- spec/spec_helper.rb
|
1187
|
+
- spec/user_spec.rb
|
@@ -1,37 +0,0 @@
|
|
1
|
-
module ErrorsHelper
|
2
|
-
|
3
|
-
def error_messages_for(*params)
|
4
|
-
options = params.extract_options!.symbolize_keys
|
5
|
-
if object = options.delete(:object)
|
6
|
-
objects = [object].flatten
|
7
|
-
else
|
8
|
-
objects = params.collect {|object_name| instance_variable_get("@#{object_name}") }.compact
|
9
|
-
end
|
10
|
-
count = objects.inject(0) {|sum, object| sum + object.errors.length }
|
11
|
-
unless count.zero?
|
12
|
-
html = {}
|
13
|
-
[:id, :class].each do |key|
|
14
|
-
if options.include?(key)
|
15
|
-
value = options[key]
|
16
|
-
html[key] = value unless value.blank?
|
17
|
-
else
|
18
|
-
html[key] = 'errorExplanation'
|
19
|
-
end
|
20
|
-
end
|
21
|
-
options[:object_name] ||= params.first
|
22
|
-
options[:header_message] = I18n.t("activerecord.errors.template.header", {:count => count, :model => object.class.to_s.humanize}) unless options.include?(:header_message)
|
23
|
-
options[:message] ||= I18n.t('activerecord.errors.template.body') unless options.include?(:message)
|
24
|
-
error_messages = objects.map {|object| object.errors.collect{ |column,error| content_tag( :li, error ) } }
|
25
|
-
|
26
|
-
contents = ''
|
27
|
-
contents << content_tag(options[:header_tag] || :h2, options[:header_message]) unless options[:header_message].blank?
|
28
|
-
contents << content_tag(:p, options[:message]) unless options[:message].blank?
|
29
|
-
contents << content_tag(:ul, error_messages)
|
30
|
-
|
31
|
-
content_tag(:div, contents, html)
|
32
|
-
else
|
33
|
-
''
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
end
|
data/lib/vendor/i18n_label.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
# Took from https://github.com/iain/i18n_label
|
2
|
-
module ActionView
|
3
|
-
module Helpers
|
4
|
-
class InstanceTag
|
5
|
-
def to_label_tag(text = nil, options = {})
|
6
|
-
options = options.stringify_keys
|
7
|
-
name_and_id = options.dup
|
8
|
-
add_default_name_and_id(name_and_id)
|
9
|
-
options.delete("index")
|
10
|
-
options["for"] ||= name_and_id["id"]
|
11
|
-
if text.blank?
|
12
|
-
content = method_name.humanize
|
13
|
-
if object.class.respond_to?(:human_attribute_name)
|
14
|
-
content = object.class.human_attribute_name(method_name)
|
15
|
-
end
|
16
|
-
else
|
17
|
-
content = text.to_s
|
18
|
-
end
|
19
|
-
label_tag(name_and_id["id"], content, options)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,83 +0,0 @@
|
|
1
|
-
# This recipe contains Capistrano recipes for handling the uploads, ferret index and picture cache files while deploying your application.
|
2
|
-
# It also contains a ferret:rebuild_index task to rebuild the index after deploying your application.
|
3
|
-
|
4
|
-
namespace :alchemy do
|
5
|
-
|
6
|
-
namespace :shared_folders do
|
7
|
-
|
8
|
-
# This task creates the shared folders for uploads, picture cache and ferret index while setting up your server.
|
9
|
-
# Call after deploy:setup like +after "deploy:setup", "alchemy:create_shared_folders"+ in your +deploy.rb+.
|
10
|
-
desc "Creates the uploads and picture cache directory in the shared folder. Call after deploy:setup"
|
11
|
-
task :create, :roles => :app do
|
12
|
-
run "mkdir -p #{shared_path}/uploads"
|
13
|
-
run "mkdir -p #{shared_path}/index"
|
14
|
-
run "mkdir -p #{shared_path}/uploads/pictures"
|
15
|
-
run "mkdir -p #{shared_path}/uploads/attachments"
|
16
|
-
run "mkdir -p #{shared_path}/cache"
|
17
|
-
run "mkdir -p #{shared_path}/cache/pictures"
|
18
|
-
end
|
19
|
-
|
20
|
-
# This task sets the symlinks for uploads, picture cache and ferret index folder.
|
21
|
-
# Call after deploy:symlink like +after "deploy:symlink", "alchemy:symlink_folders"+ in your +deploy.rb+.
|
22
|
-
desc "Sets the symlinks for uploads, picture cache and ferret index folder. Call after deploy:symlink"
|
23
|
-
task :symlink, :roles => :app do
|
24
|
-
run "rm -rf #{current_path}/public/uploads/*"
|
25
|
-
run "ln -nfs #{shared_path}/uploads/pictures/ #{current_path}/uploads/pictures"
|
26
|
-
run "ln -nfs #{shared_path}/uploads/attachments/ #{current_path}/uploads/attachments"
|
27
|
-
run "rm -rf #{current_path}/public/pictures"
|
28
|
-
run "ln -nfs #{shared_path}/cache/pictures/ #{current_path}/public/pictures"
|
29
|
-
run "rm -rf #{current_path}/index"
|
30
|
-
run "ln -nfs #{shared_path}/index/ #{current_path}/index"
|
31
|
-
end
|
32
|
-
|
33
|
-
end
|
34
|
-
|
35
|
-
namespace :assets do
|
36
|
-
|
37
|
-
desc "Copies all assets from Alchemy plugin folder to public folder"
|
38
|
-
task :copy do
|
39
|
-
run "cd #{current_path} && RAILS_ENV=production rake alchemy:assets:copy:all"
|
40
|
-
end
|
41
|
-
|
42
|
-
end
|
43
|
-
|
44
|
-
namespace :database_yml do
|
45
|
-
|
46
|
-
desc "Creates the database.yml file"
|
47
|
-
task :create do
|
48
|
-
db_config = ERB.new <<-EOF
|
49
|
-
production:
|
50
|
-
adapter: mysql
|
51
|
-
encoding: utf8
|
52
|
-
reconnect: false
|
53
|
-
pool: 5
|
54
|
-
database: #{ Capistrano::CLI.ui.ask("Database name: ") }
|
55
|
-
username: #{ Capistrano::CLI.ui.ask("Database username: ") }
|
56
|
-
password: #{ Capistrano::CLI.ui.ask("Database password: ") }
|
57
|
-
socket: #{ Capistrano::CLI.ui.ask("Database socket: ") }
|
58
|
-
host: #{ Capistrano::CLI.ui.ask("Database host: ") }
|
59
|
-
EOF
|
60
|
-
run "mkdir -p #{shared_path}/config"
|
61
|
-
put db_config.result, "#{shared_path}/config/database.yml"
|
62
|
-
end
|
63
|
-
|
64
|
-
desc "Symlinks the database.yml file from shared folder into config folder"
|
65
|
-
task :symlink, :except => { :no_release => true } do
|
66
|
-
run "ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml"
|
67
|
-
end
|
68
|
-
|
69
|
-
end
|
70
|
-
|
71
|
-
end
|
72
|
-
|
73
|
-
namespace :ferret do
|
74
|
-
|
75
|
-
# This task rebuilds the ferret index for the EssenceText and EssenceRichtext Models.
|
76
|
-
# Call it before deploy:restart like +before "deploy:restart", "alchemy:rebuild_index"+ in your +deploy.rb+.
|
77
|
-
# It uses the +alchemy:rebuild_index+ rake task found in +vendor/plugins/alchemy/lib/tasks+.
|
78
|
-
desc "Rebuild the ferret index. Call before deploy:restart"
|
79
|
-
task :rebuild_index, :roles => :app do
|
80
|
-
run "cd #{current_path} && RAILS_ENV=production rake ferret:rebuild_index"
|
81
|
-
end
|
82
|
-
|
83
|
-
end
|