alchemy_cms 2.0.pre3 → 2.0.pre4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|