content_engine 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +40 -0
- data/README.md +43 -0
- data/Rakefile +86 -0
- data/VERSION +1 -0
- data/app/controllers/content_engine/articles_controller.rb +54 -0
- data/app/controllers/content_engine/pages_controller.rb +76 -0
- data/app/controllers/content_engine_controller.rb +14 -0
- data/app/helpers/application_helper.rb +2 -0
- data/app/models/article.rb +29 -0
- data/app/models/content.rb +64 -0
- data/app/models/page.rb +40 -0
- data/app/models/site.rb +26 -0
- data/app/models/tag.rb +53 -0
- data/app/models/user.rb +5 -0
- data/app/views/content_engine/articles/_form.erb +8 -0
- data/app/views/content_engine/articles/edit.html.erb +7 -0
- data/app/views/content_engine/articles/index.html.erb +10 -0
- data/app/views/content_engine/articles/new.html.erb +6 -0
- data/app/views/content_engine/articles/show.html.erb +9 -0
- data/app/views/content_engine/pages/_form.erb +8 -0
- data/app/views/content_engine/pages/edit.html.erb +7 -0
- data/app/views/content_engine/pages/index.html.erb +10 -0
- data/app/views/content_engine/pages/new.html.erb +6 -0
- data/app/views/content_engine/pages/show.html.erb +9 -0
- data/app/views/layouts/application.html.erb +16 -0
- data/config/application.rb +1 -0
- data/config/locales/en.yml +5 -0
- data/config/routes.rb +25 -0
- data/content_engine.gemspec +167 -0
- data/db/migrate/20100225105011_create_contents.rb +22 -0
- data/db/migrate/20100225105903_create_users.rb +8 -0
- data/db/migrate/20100225110024_create_sites.rb +15 -0
- data/db/migrate/20100225110037_create_memberships.rb +12 -0
- data/db/migrate/20100225112236_acts_as_taggable_on.rb +26 -0
- data/db/schema.rb +58 -0
- data/lib/content_engine.rb +24 -0
- data/lib/tasks/content_engine.rake +24 -0
- data/spec/blueprint.rb +41 -0
- data/spec/models/article_spec.rb +56 -0
- data/spec/models/page_spec.rb +158 -0
- data/spec/models/site_spec.rb +32 -0
- data/spec/rails_app/.gitignore +4 -0
- data/spec/rails_app/Rakefile +10 -0
- data/spec/rails_app/app/controllers/admins_controller.rb +6 -0
- data/spec/rails_app/app/controllers/application_controller.rb +6 -0
- data/spec/rails_app/app/controllers/home_controller.rb +4 -0
- data/spec/rails_app/app/controllers/sessions_controller.rb +6 -0
- data/spec/rails_app/app/controllers/users_controller.rb +12 -0
- data/spec/rails_app/app/helpers/application_helper.rb +3 -0
- data/spec/rails_app/app/views/home/index.html.erb +1 -0
- data/spec/rails_app/app/views/layouts/application.html.erb +19 -0
- data/spec/rails_app/config/application.rb +30 -0
- data/spec/rails_app/config/boot.rb +9 -0
- data/spec/rails_app/config/database.yml +16 -0
- data/spec/rails_app/config/environment.rb +5 -0
- data/spec/rails_app/config/environments/development.rb +19 -0
- data/spec/rails_app/config/environments/production.rb +33 -0
- data/spec/rails_app/config/environments/test.rb +29 -0
- data/spec/rails_app/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/rails_app/config/initializers/cookie_verification_secret.rb +7 -0
- data/spec/rails_app/config/initializers/inflections.rb +2 -0
- data/spec/rails_app/config/initializers/session_store.rb +15 -0
- data/spec/rails_app/config/routes.rb +21 -0
- data/spec/rails_app/config.ru +4 -0
- data/spec/rails_app/db/migrate/20100225105011_create_contents.rb +22 -0
- data/spec/rails_app/db/migrate/20100225105903_create_users.rb +8 -0
- data/spec/rails_app/db/migrate/20100225110024_create_sites.rb +15 -0
- data/spec/rails_app/db/migrate/20100225110037_create_memberships.rb +12 -0
- data/spec/rails_app/db/migrate/20100225112236_acts_as_taggable_on.rb +26 -0
- data/spec/rails_app/db/schema.rb +59 -0
- data/spec/rails_app/public/404.html +26 -0
- data/spec/rails_app/public/422.html +26 -0
- data/spec/rails_app/public/500.html +26 -0
- data/spec/rails_app/public/favicon.ico +0 -0
- data/spec/rails_app/public/images/rails.png +0 -0
- data/spec/rails_app/public/javascripts/application.js +2 -0
- data/spec/rails_app/public/javascripts/controls.js +963 -0
- data/spec/rails_app/public/javascripts/dragdrop.js +973 -0
- data/spec/rails_app/public/javascripts/effects.js +1128 -0
- data/spec/rails_app/public/javascripts/prototype.js +4320 -0
- data/spec/rails_app/public/javascripts/rails.js +110 -0
- data/spec/rails_app/public/robots.txt +5 -0
- data/spec/rails_app/public/stylesheets/.gitkeep +0 -0
- data/spec/rails_app/script/rails +10 -0
- data/spec/requests/user_manage_articles_spec.rb +85 -0
- data/spec/requests/user_manage_pages_spec.rb +92 -0
- data/spec/requests/webrat.log +17 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +36 -0
- metadata +226 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# Edit this Gemfile to bundle your application's dependencies.
|
2
|
+
source 'http://gemcutter.org'
|
3
|
+
|
4
|
+
gem "rails", "3.0.0.beta"
|
5
|
+
|
6
|
+
## Bundle edge rails:
|
7
|
+
# gem "rails", :git => "git://github.com/rails/rails.git"
|
8
|
+
|
9
|
+
# ActiveRecord requires a database adapter. By default,
|
10
|
+
# Rails has selected sqlite3.
|
11
|
+
gem "sqlite3-ruby", :require => "sqlite3"
|
12
|
+
|
13
|
+
# Application dependencies
|
14
|
+
|
15
|
+
gem "will_paginate"
|
16
|
+
gem "rdiscount"
|
17
|
+
gem "formtastic"
|
18
|
+
gem "permalink_fu" , :git => 'git://github.com/idealian/permalink_fu.git'
|
19
|
+
gem "acts-as-taggable-on", :git => 'git://github.com/fousa/acts-as-taggable-on.git'
|
20
|
+
|
21
|
+
|
22
|
+
group :development do
|
23
|
+
gem "launchy"
|
24
|
+
gem "jeweler"
|
25
|
+
end
|
26
|
+
|
27
|
+
group :cucumber do
|
28
|
+
gem 'webrat', :require => nil
|
29
|
+
gem 'cucumber-rails', :git => 'git://github.com/aslakhellesoy/cucumber-rails.git'
|
30
|
+
gem 'rspec-rails', :git => 'git://github.com/rspec/rspec-rails.git'
|
31
|
+
end
|
32
|
+
|
33
|
+
# bundler requires these gems while running tests
|
34
|
+
group :test do
|
35
|
+
gem 'test-unit', "1.2.3"
|
36
|
+
gem 'machinist', :git => 'git://github.com/notahat/machinist.git'
|
37
|
+
gem 'rspec-rails', :git => 'git://github.com/rspec/rspec-rails.git'
|
38
|
+
gem 'webrat', :require => nil
|
39
|
+
gem 'faker', :require => nil
|
40
|
+
end
|
data/README.md
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
Content Engine
|
2
|
+
===
|
3
|
+
|
4
|
+
Rails3 Engine for awesome Site and content management
|
5
|
+
|
6
|
+
|
7
|
+
Dependencies
|
8
|
+
---
|
9
|
+
- Rails 3
|
10
|
+
- Idealian UserEngine or existence of users table
|
11
|
+
|
12
|
+
Install
|
13
|
+
---
|
14
|
+
|
15
|
+
Add following to your Gemfile
|
16
|
+
|
17
|
+
gem "permalink_fu" , :git => 'git://github.com/idealian/permalink_fu.git'
|
18
|
+
gem "acts-as-taggable-on", :git => 'git://github.com/fousa/acts-as-taggable-on.git'
|
19
|
+
gem "content_engine", :git => "git@github.com:idealian/content_engine.git"
|
20
|
+
|
21
|
+
And run `bundle install`
|
22
|
+
|
23
|
+
Features
|
24
|
+
---
|
25
|
+
sites
|
26
|
+
pages
|
27
|
+
articles
|
28
|
+
tags
|
29
|
+
|
30
|
+
Customization
|
31
|
+
---
|
32
|
+
|
33
|
+
To override a controller
|
34
|
+
|
35
|
+
class PagesController < ContentEngine::PagesController
|
36
|
+
def index
|
37
|
+
end
|
38
|
+
|
39
|
+
def show
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
Copyright (c) 2010 Taylor Luk, Idealian Pty Ltd All right reserved
|
data/Rakefile
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
2
|
+
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
3
|
+
|
4
|
+
require File.expand_path('../spec/rails_app/config/application', __FILE__)
|
5
|
+
|
6
|
+
require 'rake'
|
7
|
+
require 'rake/testtask'
|
8
|
+
require 'rake/rdoctask'
|
9
|
+
|
10
|
+
# gem "will_paginate"
|
11
|
+
# gem "rdiscount"
|
12
|
+
# gem "formtastic"
|
13
|
+
# gem "permalink_fu", :git => 'git://github.com/idealian/permalink_fu.git'
|
14
|
+
# gem "acts-as-taggable-on", :git => 'git://github.com/fousa/acts-as-taggable-on.git'
|
15
|
+
|
16
|
+
begin
|
17
|
+
require 'jeweler'
|
18
|
+
Jeweler::Tasks.new do |gem|
|
19
|
+
gem.name = "content_engine"
|
20
|
+
gem.summary = %Q{A Rails 3 Engine for sexier site and content management}
|
21
|
+
gem.description = %Q{Extracted from shop2, site-rest}
|
22
|
+
gem.email = "taylor.luk@idealian.net"
|
23
|
+
gem.homepage = "http://github.com/idealian/content_engine"
|
24
|
+
gem.authors = ["Taylor Luk"]
|
25
|
+
gem.add_dependency "will_paginate"
|
26
|
+
gem.add_dependency "rdiscount"
|
27
|
+
gem.add_dependency "formtastic"
|
28
|
+
gem.add_development_dependency "rspec", ">= 1.2.9"
|
29
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
30
|
+
end
|
31
|
+
Jeweler::GemcutterTasks.new
|
32
|
+
rescue LoadError
|
33
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
34
|
+
end
|
35
|
+
|
36
|
+
begin
|
37
|
+
require 'rspec/core'
|
38
|
+
require 'rspec/core/rake_task'
|
39
|
+
rescue MissingSourceFile
|
40
|
+
end
|
41
|
+
|
42
|
+
task :default => :spec
|
43
|
+
|
44
|
+
desc "Run all specs in spec directory (excluding plugin specs)"
|
45
|
+
Rspec::Core::RakeTask.new(:spec)
|
46
|
+
|
47
|
+
namespace :spec do
|
48
|
+
[:requests, :models, :controllers, :views, :helpers, :mailers, :lib].each do |sub|
|
49
|
+
desc "Run the code examples in spec/#{sub}"
|
50
|
+
Rspec::Core::RakeTask.new do |t|
|
51
|
+
t.pattern = "./spec/#{sub}/**/*_spec.rb"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
#
|
56
|
+
# begin
|
57
|
+
# require 'spec/rake/spectask'
|
58
|
+
# rescue LoadError
|
59
|
+
# puts 'To use rspec for testing you must install rspec gem:'
|
60
|
+
# puts '$ sudo gem install rspec'
|
61
|
+
# exit
|
62
|
+
# end
|
63
|
+
#
|
64
|
+
# Spec::Rake::SpecTask.new(:spec) do |spec|
|
65
|
+
# spec.libs << 'lib' << 'spec'
|
66
|
+
# spec.spec_files = FileList['spec/**/*_spec.rb']
|
67
|
+
# end
|
68
|
+
#
|
69
|
+
# Spec::Rake::SpecTask.new(:rcov) do |spec|
|
70
|
+
# spec.libs << 'lib' << 'spec'
|
71
|
+
# spec.pattern = 'spec/**/*_spec.rb'
|
72
|
+
# spec.rcov = true
|
73
|
+
# end
|
74
|
+
|
75
|
+
|
76
|
+
task :default => :spec
|
77
|
+
|
78
|
+
require 'rake/rdoctask'
|
79
|
+
Rake::RDocTask.new do |rdoc|
|
80
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
81
|
+
|
82
|
+
rdoc.rdoc_dir = 'rdoc'
|
83
|
+
rdoc.title = "very_nifty_generators #{version}"
|
84
|
+
rdoc.rdoc_files.include('README*')
|
85
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
86
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module ContentEngine
|
2
|
+
class ArticlesController < ContentEngineController
|
3
|
+
respond_to :html, :xml
|
4
|
+
|
5
|
+
# GET /articles
|
6
|
+
# GET /articles.xml
|
7
|
+
def index
|
8
|
+
@articles = @site.articles.order('created_at desc').all.paginate(:page => params[:page])
|
9
|
+
respond_with @articles
|
10
|
+
end
|
11
|
+
|
12
|
+
# GET /articles/1
|
13
|
+
# GET /articles/1.xml
|
14
|
+
def show
|
15
|
+
respond_with @article = @site.articles.find(params[:id])
|
16
|
+
end
|
17
|
+
|
18
|
+
# GET /articles/new
|
19
|
+
# GET /articles/new.xml
|
20
|
+
def new
|
21
|
+
respond_with @article = @site.articles.new
|
22
|
+
end
|
23
|
+
|
24
|
+
# GET /articles/1/edit
|
25
|
+
def edit
|
26
|
+
respond_with @article = @site.articles.find(params[:id])
|
27
|
+
end
|
28
|
+
|
29
|
+
# POST /articles
|
30
|
+
# POST /articles.xml
|
31
|
+
def create
|
32
|
+
@article = @site.articles.new(params[:article])
|
33
|
+
flash[:notice] = "Article was successfully created." if @article.save
|
34
|
+
respond_with @article
|
35
|
+
end
|
36
|
+
|
37
|
+
# PUT /articles/1
|
38
|
+
# PUT /articles/1.xml
|
39
|
+
def update
|
40
|
+
@article = @site.articles.find(params[:id])
|
41
|
+
flash[:notice] = "Article was successfully updated." if @article.update_attributes(params[:article])
|
42
|
+
respond_with @article
|
43
|
+
end
|
44
|
+
|
45
|
+
# DELETE /articles/1
|
46
|
+
# DELETE /articles/1.xml
|
47
|
+
def destroy
|
48
|
+
@article = @site.articles.find(params[:id])
|
49
|
+
@article.destroy
|
50
|
+
|
51
|
+
respond_with @article
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module ContentEngine
|
2
|
+
class PagesController < ContentEngineController
|
3
|
+
respond_to :html, :xml
|
4
|
+
|
5
|
+
# GET /pages
|
6
|
+
# GET /pages.xml
|
7
|
+
def index
|
8
|
+
@pages = @site.pages.order('created_at desc').all.paginate(:page => params[:page])
|
9
|
+
@rootpage = @site.pages.root
|
10
|
+
|
11
|
+
if request.xhr? and params[:parent_id]
|
12
|
+
@rootpage = @site.pages.find(params[:parent_id])
|
13
|
+
return render(:partial => 'treeview')
|
14
|
+
end
|
15
|
+
|
16
|
+
respond_with @pages
|
17
|
+
end
|
18
|
+
|
19
|
+
# GET /pages/1
|
20
|
+
# GET /pages/1.xml
|
21
|
+
def show
|
22
|
+
respond_with @page = @site.pages.find(params[:id])
|
23
|
+
end
|
24
|
+
|
25
|
+
def lookup
|
26
|
+
@page = @site.pages.find_by_url(params[:url])
|
27
|
+
|
28
|
+
render :template => 'content_engine/pages/show'
|
29
|
+
end
|
30
|
+
|
31
|
+
# GET /pages/new
|
32
|
+
# GET /pages/new.xml
|
33
|
+
def new
|
34
|
+
respond_with @page = @site.pages.new
|
35
|
+
end
|
36
|
+
|
37
|
+
# GET /pages/1/edit
|
38
|
+
def edit
|
39
|
+
respond_with @page = @site.pages.find(params[:id])
|
40
|
+
end
|
41
|
+
|
42
|
+
# POST /pages
|
43
|
+
# POST /pages.xml
|
44
|
+
def create
|
45
|
+
@page = @site.pages.new(params[:page])
|
46
|
+
flash[:notice] = "Page was successfully created." if @page.save
|
47
|
+
respond_with @page
|
48
|
+
end
|
49
|
+
|
50
|
+
# PUT /pages/1
|
51
|
+
# PUT /pages/1.xml
|
52
|
+
def update
|
53
|
+
@page = @site.pages.find(params[:id])
|
54
|
+
flash[:notice] = "Page was successfully updated." if @page.update_attributes(params[:page])
|
55
|
+
respond_with @page
|
56
|
+
end
|
57
|
+
|
58
|
+
# DELETE /pages/1
|
59
|
+
# DELETE /pages/1.xml
|
60
|
+
def destroy
|
61
|
+
@page = @site.pages.find(params[:id])
|
62
|
+
@page.destroy
|
63
|
+
|
64
|
+
respond_with @page
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
# # GET /pages/1/move?to=(up|down)
|
69
|
+
# def move
|
70
|
+
# @page = @site.pages.find(params[:id])
|
71
|
+
# @page.move_left
|
72
|
+
#
|
73
|
+
# redirect_to pages_path
|
74
|
+
# end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class ContentEngineController < ApplicationController
|
2
|
+
protect_from_forgery
|
3
|
+
before_filter :load_site
|
4
|
+
|
5
|
+
protected
|
6
|
+
def load_site
|
7
|
+
# Single site mode
|
8
|
+
if Site.count == 1
|
9
|
+
@site = Site.first
|
10
|
+
else
|
11
|
+
@site = Site.find_by_host(request.host)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class Article < Content
|
2
|
+
has_permalink :title
|
3
|
+
acts_as_taggable_on :tags
|
4
|
+
|
5
|
+
validates_presence_of :title
|
6
|
+
validates_presence_of :body
|
7
|
+
|
8
|
+
def excerpt
|
9
|
+
content = body[0, 300]
|
10
|
+
words = content.gsub(/<\/?[^>]+>/, "").split(' ')
|
11
|
+
words[0 .. 59].join(' ') + '...'
|
12
|
+
end
|
13
|
+
|
14
|
+
def url
|
15
|
+
"/articles/%04d/%02d/%02d/#{permalink}" % [created_at.year, created_at.month, created_at.day]
|
16
|
+
end
|
17
|
+
|
18
|
+
def next
|
19
|
+
site.articles.published.order('id').where("id > ?", id).first
|
20
|
+
end
|
21
|
+
|
22
|
+
def prev
|
23
|
+
site.articles.published.order('id').where("id < ?", id).first
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_param
|
27
|
+
"#{id}-#{permalink}"
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
class Content < ActiveRecord::Base
|
2
|
+
abstract_class = true
|
3
|
+
|
4
|
+
belongs_to :site
|
5
|
+
belongs_to :author, :class_name => 'User'
|
6
|
+
|
7
|
+
scope :recent, order("published_at DESC")
|
8
|
+
scope :published, lambda{
|
9
|
+
where("published_at is NOT null").where("published_at <= ?", Time.now).recent
|
10
|
+
}
|
11
|
+
scope :draft, where(:published_at => nil).recent
|
12
|
+
|
13
|
+
before_save :update_published_at
|
14
|
+
|
15
|
+
def body
|
16
|
+
self[:body]
|
17
|
+
end
|
18
|
+
|
19
|
+
def body_html
|
20
|
+
if self.body_source
|
21
|
+
markdown = RDiscount.new(self.body_source)
|
22
|
+
@body_html ||= markdown.to_html
|
23
|
+
end
|
24
|
+
end
|
25
|
+
alias_method :body_source, :body
|
26
|
+
alias_method :body, :body_html
|
27
|
+
|
28
|
+
|
29
|
+
def author_name
|
30
|
+
author.display_name if author
|
31
|
+
end
|
32
|
+
|
33
|
+
def status
|
34
|
+
published? ? 'published' : 'draft'
|
35
|
+
end
|
36
|
+
|
37
|
+
def status=(status)
|
38
|
+
if status == 'draft'
|
39
|
+
self[:published_at] = nil
|
40
|
+
else
|
41
|
+
self[:published_at] = Time.now unless published?
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def published=(flag)
|
46
|
+
@mark_published = flag
|
47
|
+
end
|
48
|
+
|
49
|
+
def published?
|
50
|
+
published_at != nil
|
51
|
+
end
|
52
|
+
|
53
|
+
def publish!
|
54
|
+
self.published = true
|
55
|
+
self.send(:update_published_at)
|
56
|
+
save
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
def update_published_at
|
61
|
+
self[:published_at] = Time.now if @mark_published and not published?
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
data/app/models/page.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
class Page < Content
|
2
|
+
belongs_to :parent, :class_name => 'Page'
|
3
|
+
has_many :children, :class_name => 'Page', :foreign_key => 'parent_id'
|
4
|
+
|
5
|
+
acts_as_taggable_on :tags
|
6
|
+
|
7
|
+
before_validation :ensure_hierarchy
|
8
|
+
has_permalink :title, :scope => :parent_id, :unless => :homepage?
|
9
|
+
|
10
|
+
validates_presence_of :title, :body
|
11
|
+
|
12
|
+
# Tree structure
|
13
|
+
scope :roots, where(:parent_id => nil)
|
14
|
+
|
15
|
+
def self.root
|
16
|
+
roots.first
|
17
|
+
end
|
18
|
+
|
19
|
+
def root?
|
20
|
+
self == Page.root || Page.count == 0 && new_record?
|
21
|
+
end
|
22
|
+
alias :homepage? :root?
|
23
|
+
|
24
|
+
def ancestors
|
25
|
+
node, nodes = self, []
|
26
|
+
nodes << node = node.parent while node.parent
|
27
|
+
nodes
|
28
|
+
end
|
29
|
+
|
30
|
+
def url
|
31
|
+
links = (ancestors.map(&:permalink) << permalink).delete_if(&:blank?)
|
32
|
+
|
33
|
+
"/#{links.join('/')}"
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
def ensure_hierarchy
|
38
|
+
self.parent = site.homepage if !parent_id && site && site.homepage
|
39
|
+
end
|
40
|
+
end
|
data/app/models/site.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
class Site < ActiveRecord::Base
|
2
|
+
belongs_to :owner, :class_name => 'User'
|
3
|
+
|
4
|
+
has_many :memberships, :dependent => :destroy
|
5
|
+
has_many :users, :through => :memberships
|
6
|
+
|
7
|
+
# has_many :tags, :dependent => :destroy
|
8
|
+
has_many :articles, :dependent => :destroy
|
9
|
+
has_many :pages, :dependent => :destroy do
|
10
|
+
def find_by_url(url = [])
|
11
|
+
url = url.split('/').delete_if(&:blank?) if url.is_a? String
|
12
|
+
|
13
|
+
page = where(:parent_id => nil).first
|
14
|
+
|
15
|
+
url.each do |part|
|
16
|
+
page = page.children.published.where(:permalink => part).first
|
17
|
+
end
|
18
|
+
|
19
|
+
page
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def homepage
|
24
|
+
pages.root
|
25
|
+
end
|
26
|
+
end
|
data/app/models/tag.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
class Tag < ActiveRecord::Base
|
2
|
+
|
3
|
+
attr_accessible :name
|
4
|
+
|
5
|
+
### ASSOCIATIONS:
|
6
|
+
|
7
|
+
has_many :taggings, :dependent => :destroy
|
8
|
+
|
9
|
+
### VALIDATIONS:
|
10
|
+
|
11
|
+
validates_presence_of :name
|
12
|
+
validates_uniqueness_of :name
|
13
|
+
|
14
|
+
### NAMED SCOPES:
|
15
|
+
|
16
|
+
scope :named, lambda { |name| { :conditions => ["name LIKE ?", name] } }
|
17
|
+
scope :named_any, lambda { |list| { :conditions => list.map { |tag| sanitize_sql(["name LIKE ?", tag.to_s]) }.join(" OR ") } }
|
18
|
+
scope :named_like, lambda { |name| { :conditions => ["name LIKE ?", "%#{name}%"] } }
|
19
|
+
scope :named_like_any, lambda { |list| { :conditions => list.map { |tag| sanitize_sql(["name LIKE ?", "%#{tag.to_s}%"]) }.join(" OR ") } }
|
20
|
+
|
21
|
+
### CLASS METHODS:
|
22
|
+
|
23
|
+
def self.find_or_create_with_like_by_name(name)
|
24
|
+
named_like(name).first || create(:name => name)
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.find_or_create_all_with_like_by_name(*list)
|
28
|
+
list = [list].flatten
|
29
|
+
|
30
|
+
return [] if list.empty?
|
31
|
+
|
32
|
+
existing_tags = Tag.named_any(list).all
|
33
|
+
new_tag_names = list.reject { |name| existing_tags.any? { |tag| tag.name.downcase == name.downcase } }
|
34
|
+
created_tags = new_tag_names.map { |name| Tag.create(:name => name) }
|
35
|
+
|
36
|
+
existing_tags + created_tags
|
37
|
+
end
|
38
|
+
|
39
|
+
### INSTANCE METHODS:
|
40
|
+
|
41
|
+
def ==(object)
|
42
|
+
super || (object.is_a?(Tag) && name == object.name)
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_s
|
46
|
+
name
|
47
|
+
end
|
48
|
+
|
49
|
+
def count
|
50
|
+
read_attribute(:count).to_i
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
data/app/models/user.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
3
|
+
<html>
|
4
|
+
<head>
|
5
|
+
<title><%= @site.title %> - Content Engine</title>
|
6
|
+
</head>
|
7
|
+
<body>
|
8
|
+
<div id="container">
|
9
|
+
<%- flash.each do |name, msg| -%>
|
10
|
+
<%= content_tag :div, msg, :id => "flash_#{name}" if msg.is_a?(String) %>
|
11
|
+
<%- end -%>
|
12
|
+
|
13
|
+
<%= yield %>
|
14
|
+
</div>
|
15
|
+
</body>
|
16
|
+
</html>
|
@@ -0,0 +1 @@
|
|
1
|
+
require File.expand_path("../../content_engine", __FILE__)
|