xhive 1.0.0.pre
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/MIT-LICENSE +20 -0
- data/README.md +223 -0
- data/Rakefile +40 -0
- data/app/assets/javascripts/xhive/application.js +15 -0
- data/app/assets/javascripts/xhive/loader.js.coffee +22 -0
- data/app/assets/javascripts/xhive/pages.js +2 -0
- data/app/assets/stylesheets/xhive/application.css +13 -0
- data/app/assets/stylesheets/xhive/pages.css +4 -0
- data/app/controllers/xhive/application_controller.rb +5 -0
- data/app/controllers/xhive/pages_controller.rb +24 -0
- data/app/controllers/xhive/stylesheets_controller.rb +16 -0
- data/app/controllers/xhive/widgets_controller.rb +16 -0
- data/app/helpers/xhive/application_helper.rb +39 -0
- data/app/models/xhive/anonymous_user.rb +6 -0
- data/app/models/xhive/mapper.rb +19 -0
- data/app/models/xhive/page.rb +19 -0
- data/app/models/xhive/site.rb +14 -0
- data/app/models/xhive/stylesheet.rb +29 -0
- data/app/presenters/xhive/base_presenter.rb +31 -0
- data/app/presenters/xhive/page_presenter.rb +23 -0
- data/app/presenters/xhive/stylesheet_presenter.rb +31 -0
- data/app/presenters/xhive/user_presenter.rb +8 -0
- data/app/views/layouts/xhive/application.html.erb +15 -0
- data/app/views/xhive/pages/show.html.erb +2 -0
- data/config/routes.rb +13 -0
- data/db/migrate/20121012191751_create_xhive_sites.rb +10 -0
- data/db/migrate/20121012193105_create_xhive_pages.rb +14 -0
- data/db/migrate/20121013235227_add_home_page_to_xhive_sites.rb +5 -0
- data/db/migrate/20121013235306_add_site_to_xhive_pages.rb +6 -0
- data/db/migrate/20121016224054_create_xhive_stylesheets.rb +13 -0
- data/db/migrate/20121016224326_add_slug_index_to_pages.rb +5 -0
- data/db/migrate/20121019185702_create_xhive_mappers.rb +13 -0
- data/lib/tasks/xhive_tasks.rake +4 -0
- data/lib/xhive/base_tag.rb +89 -0
- data/lib/xhive/controller.rb +24 -0
- data/lib/xhive/engine.rb +24 -0
- data/lib/xhive/hashy.rb +42 -0
- data/lib/xhive/presentable.rb +28 -0
- data/lib/xhive/router/base.rb +61 -0
- data/lib/xhive/router/cells.rb +36 -0
- data/lib/xhive/router/error.rb +14 -0
- data/lib/xhive/router/route.rb +77 -0
- data/lib/xhive/router.rb +10 -0
- data/lib/xhive/tag_factory.rb +21 -0
- data/lib/xhive/version.rb +3 -0
- data/lib/xhive/widgify.rb +53 -0
- data/lib/xhive.rb +12 -0
- metadata +271 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2012 YOURNAME
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,223 @@
|
|
1
|
+
XHIVE
|
2
|
+
======
|
3
|
+
|
4
|
+
xhive is a gem built for turning your Rails application into an AJAXified CMS.
|
5
|
+
|
6
|
+
# How it works
|
7
|
+
|
8
|
+
xhive converts your controller actions or [cells](https://github.com/apotonick/cells) into AJAX widgets.
|
9
|
+
|
10
|
+
It leverages the power of [Liquid](http://liquidmarkup.org/) creating a custom Liquid::Tag for every
|
11
|
+
widget, so it can be called from within any HTML template.
|
12
|
+
|
13
|
+
xhive also gives you the foundation of a CMS providing the following models:
|
14
|
+
|
15
|
+
* Site
|
16
|
+
* Page
|
17
|
+
* Stylesheet
|
18
|
+
* Image
|
19
|
+
|
20
|
+
Using this models along with the xhive widgets you will be able to build a fully functional CMS.
|
21
|
+
|
22
|
+
# Installation
|
23
|
+
|
24
|
+
Add xhive to your Gemfile
|
25
|
+
|
26
|
+
`gem 'xhive'`
|
27
|
+
|
28
|
+
Run bundle install
|
29
|
+
|
30
|
+
`bundle install`
|
31
|
+
|
32
|
+
Run xhive migrations
|
33
|
+
|
34
|
+
```
|
35
|
+
rake xhive:install:migrations
|
36
|
+
rake db:migrate
|
37
|
+
```
|
38
|
+
|
39
|
+
Include the custom stylesheets in your head tag.
|
40
|
+
|
41
|
+
`<%= include_custom_stylesheets %>`
|
42
|
+
|
43
|
+
Include the widgets loader just before your \<\\body\> tag.
|
44
|
+
|
45
|
+
`<%= initialize_widgets_loader %>`
|
46
|
+
|
47
|
+
# Usage
|
48
|
+
|
49
|
+
## Widgify
|
50
|
+
|
51
|
+
### Turning your controller actions into widgets
|
52
|
+
|
53
|
+
Let's say you have a Posts controller and you want to access the show action as a widget.
|
54
|
+
|
55
|
+
```
|
56
|
+
app/controller/posts_controller.rb
|
57
|
+
|
58
|
+
class PostsController < ApplicationController
|
59
|
+
def show
|
60
|
+
@post = Post.find(params[:id])
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
app/views/posts/show.html.erb
|
65
|
+
|
66
|
+
<h1><%= @post.title %></h1>
|
67
|
+
|
68
|
+
<p><%= @post.body %></p>
|
69
|
+
|
70
|
+
config/routes.rb
|
71
|
+
|
72
|
+
resources :posts, :only => [:show]
|
73
|
+
|
74
|
+
```
|
75
|
+
Just tell xhive to *widgify* your action:
|
76
|
+
|
77
|
+
```
|
78
|
+
class PostsController < ApplicationController
|
79
|
+
widgify :show
|
80
|
+
|
81
|
+
def show
|
82
|
+
@post = Post.find(params[:id])
|
83
|
+
end
|
84
|
+
end
|
85
|
+
```
|
86
|
+
And that's it. You will now be able to insert the content of any post from within an HTML template using:
|
87
|
+
|
88
|
+
{% posts_show id:1234 %}
|
89
|
+
|
90
|
+
This tag will make the browser insert the post content asynchronously into the HTML document.
|
91
|
+
|
92
|
+
xhive will also enforce the tag to include the :id parameter.
|
93
|
+
|
94
|
+
### Using [cells](https://github.com/apotonick/cells) as reusable widgets
|
95
|
+
|
96
|
+
Let's use the same example to illustrate the use of cells with xhive.
|
97
|
+
|
98
|
+
We have a Posts cell and we want to use the show method as an AJAX widget.
|
99
|
+
|
100
|
+
```
|
101
|
+
app/cells/posts_cell.rb
|
102
|
+
|
103
|
+
class PostsCell < Cell::Rails
|
104
|
+
def show(params)
|
105
|
+
@post = params[:id]
|
106
|
+
render
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
app/cells/posts/show.html.erb
|
111
|
+
|
112
|
+
<div class='post'>
|
113
|
+
<h1><%= @post.title %></h1>
|
114
|
+
|
115
|
+
<p><%= @post.body %></p>
|
116
|
+
</div>
|
117
|
+
|
118
|
+
```
|
119
|
+
In this case, we need to tell xhive how we are mounting our widgets routes:
|
120
|
+
|
121
|
+
```
|
122
|
+
config/initializers/xhive.rb
|
123
|
+
|
124
|
+
Xhive::Router::Cells.draw do |router|
|
125
|
+
router.mount 'posts/:id', :to => 'posts#show'
|
126
|
+
end
|
127
|
+
```
|
128
|
+
|
129
|
+
And that's it. You will now be able to insert the content of any post from within an HTML template using:
|
130
|
+
|
131
|
+
{% posts_show id:1234 %}
|
132
|
+
|
133
|
+
This tag will make the browser insert the post content asynchronously into the HTML document.
|
134
|
+
|
135
|
+
xhive will also enforce the tag to include the :id parameter.
|
136
|
+
|
137
|
+
## CMS features
|
138
|
+
|
139
|
+
Ok, I can include my cells and controller actions as widgets, but... how?
|
140
|
+
|
141
|
+
xhive provides you with some basic CMS infrastructure.
|
142
|
+
|
143
|
+
### Creating your first dynamic page
|
144
|
+
|
145
|
+
To be able to use your widgets, you have to follow the following steps:
|
146
|
+
|
147
|
+
Create a Site
|
148
|
+
|
149
|
+
```
|
150
|
+
site = Xhive::Site.create(:name => 'My awesome blog', :domain => 'localhost')
|
151
|
+
```
|
152
|
+
|
153
|
+
Create a Page
|
154
|
+
|
155
|
+
```
|
156
|
+
page = Xhive::Page.create(:name => 'home',
|
157
|
+
:title => 'My blog page',
|
158
|
+
:content => '<h1>Home</h1><p>{% posts_show id:1 %}</p>',
|
159
|
+
:site => site)
|
160
|
+
```
|
161
|
+
|
162
|
+
Start the server
|
163
|
+
|
164
|
+
Now you can access the page on http://localhost:3000/pages/home.
|
165
|
+
|
166
|
+
This should display the post with id: 1 inside the home page.
|
167
|
+
|
168
|
+
### Adding pages to your own custom data
|
169
|
+
|
170
|
+
You can also use the xhive pages from within you own data.
|
171
|
+
|
172
|
+
xhive provides the Xhive::Mapper to wire up your resources to xhive pages.
|
173
|
+
|
174
|
+
Create a new page to display all the posts
|
175
|
+
|
176
|
+
```
|
177
|
+
posts_page = Xhive::Page.create(:name => 'posts',
|
178
|
+
:title => 'Blog Posts',
|
179
|
+
:content => '{% for post in posts %}{% posts_show id:post.id %}{% endfor %}',
|
180
|
+
:site => site)
|
181
|
+
```
|
182
|
+
|
183
|
+
Create a new stylesheet to display your posts:
|
184
|
+
|
185
|
+
```
|
186
|
+
stylesheet = Xhive::Stylesheet.create(:name => 'Posts',
|
187
|
+
:content => '.post {
|
188
|
+
h1 { font-size: 20px; color: blue; }
|
189
|
+
p { font-size: 12px; color: #000; }
|
190
|
+
}',
|
191
|
+
:site => site)
|
192
|
+
```
|
193
|
+
|
194
|
+
Create a new mapper record for the posts resources
|
195
|
+
|
196
|
+
```
|
197
|
+
mapper = Xhive::Mapper.create(:resource => 'Post', :action => 'index', :page => posts_page)
|
198
|
+
```
|
199
|
+
|
200
|
+
From your posts controller, render the posts page
|
201
|
+
|
202
|
+
```
|
203
|
+
class PostsController < ApplicationController
|
204
|
+
def index
|
205
|
+
@posts = Post.all.limit(10)
|
206
|
+
render_page_for 'Post', 'index', :posts => @posts
|
207
|
+
end
|
208
|
+
end
|
209
|
+
```
|
210
|
+
|
211
|
+
Using this feature you can let the designers implement the HTML/CSS to display the posts in your site without your intervention.
|
212
|
+
|
213
|
+
TODO
|
214
|
+
====
|
215
|
+
|
216
|
+
* Implement the Image model
|
217
|
+
* Remove as many dependencies as possible
|
218
|
+
* Improve test coverage
|
219
|
+
|
220
|
+
Disclaimer
|
221
|
+
==========
|
222
|
+
This is a work in progress and still a proof of concept. Use at your own risk :P.
|
223
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'rdoc/task'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rdoc/rdoc'
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
RDoc::Task = Rake::RDocTask
|
13
|
+
end
|
14
|
+
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
17
|
+
rdoc.title = 'Xhive'
|
18
|
+
rdoc.options << '--line-numbers'
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
|
24
|
+
load 'rails/tasks/engine.rake'
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
Bundler::GemHelper.install_tasks
|
29
|
+
|
30
|
+
require 'rake/testtask'
|
31
|
+
|
32
|
+
Rake::TestTask.new(:test) do |t|
|
33
|
+
t.libs << 'lib'
|
34
|
+
t.libs << 'test'
|
35
|
+
t.pattern = 'test/**/*_test.rb'
|
36
|
+
t.verbose = false
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
task :default => :test
|
@@ -0,0 +1,15 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
+
// listed below.
|
3
|
+
//
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
5
|
+
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
|
6
|
+
//
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
+
// the compiled file.
|
9
|
+
//
|
10
|
+
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
|
11
|
+
// GO AFTER THE REQUIRES BELOW.
|
12
|
+
//
|
13
|
+
//= require jquery
|
14
|
+
//= require jquery_ujs
|
15
|
+
//= require_tree .
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class @WidgetLoader
|
2
|
+
@load: ->
|
3
|
+
$widgets = []
|
4
|
+
|
5
|
+
$("[data-widget='true']").each((index) ->
|
6
|
+
$widget = $(this)
|
7
|
+
baseUrl = $widget.data('url')
|
8
|
+
args = $widget.data('params')
|
9
|
+
url = "#{baseUrl}?#{args}"
|
10
|
+
$widgets.push $.ajax({
|
11
|
+
url: url,
|
12
|
+
success: (data) ->
|
13
|
+
$widget.html(data)
|
14
|
+
$widget.attr('data-widget', 'false')
|
15
|
+
})
|
16
|
+
)
|
17
|
+
|
18
|
+
if $widgets.length > 0
|
19
|
+
$.when.apply(null, $widgets).then( ->
|
20
|
+
WidgetLoader.load()
|
21
|
+
)
|
22
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the top of the
|
9
|
+
* compiled file, but it's generally better to create a new file per style scope.
|
10
|
+
*
|
11
|
+
*= require_self
|
12
|
+
*= require_tree .
|
13
|
+
*/
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require_dependency "xhive/application_controller"
|
2
|
+
|
3
|
+
module Xhive
|
4
|
+
class PagesController < ApplicationController
|
5
|
+
extend Xhive::Widgify
|
6
|
+
|
7
|
+
widgify :widget
|
8
|
+
|
9
|
+
before_filter :load_page
|
10
|
+
|
11
|
+
def show
|
12
|
+
end
|
13
|
+
|
14
|
+
def widget
|
15
|
+
render :show
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def load_page
|
21
|
+
@page = current_site.pages.find(params[:id])
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require_dependency "xhive/application_controller"
|
2
|
+
|
3
|
+
module Xhive
|
4
|
+
class StylesheetsController < ApplicationController
|
5
|
+
respond_to :css
|
6
|
+
|
7
|
+
def index
|
8
|
+
render :text => StylesheetPresenter.all_compressed(Stylesheet.all)
|
9
|
+
end
|
10
|
+
|
11
|
+
def show
|
12
|
+
@style = Stylesheet.find(params[:id])
|
13
|
+
render :text => @style.presenter.compressed
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require_dependency "xhive/application_controller"
|
2
|
+
|
3
|
+
module Xhive
|
4
|
+
class WidgetsController < ApplicationController
|
5
|
+
def show
|
6
|
+
# Looks for a route matching the request path
|
7
|
+
route = Xhive::Router::Route.find(request.path)
|
8
|
+
# Gets the parameters from the request path and the query string
|
9
|
+
parameters = route.params_from(request.path).merge(params).with_indifferent_access
|
10
|
+
# Renders the corresponding cell#action
|
11
|
+
render :text => render_cell(route.klass.underscore.to_sym, route.action.to_sym, parameters), :status => 200
|
12
|
+
rescue => e
|
13
|
+
render :text => 'Not found', :status => 404
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Xhive
|
2
|
+
module ApplicationHelper
|
3
|
+
def initialize_widgets_loader
|
4
|
+
"<script type='text/javascript'>WidgetLoader.load()</script>".html_safe
|
5
|
+
end
|
6
|
+
|
7
|
+
def include_custom_stylesheets
|
8
|
+
"<link href='#{stylesheets_path}' media='all' rel='stylesheet' type='text/css'/>".html_safe
|
9
|
+
end
|
10
|
+
|
11
|
+
def render_page_for(resource, action, options={})
|
12
|
+
page = current_site.mappers.page_for(resource, action)
|
13
|
+
render :text => page.presenter.render_content(options)
|
14
|
+
end
|
15
|
+
|
16
|
+
def current_site
|
17
|
+
domain = request.host
|
18
|
+
@current_site ||= Site.where(:domain => domain).first || Site.first
|
19
|
+
fail "No Site defined. Please create a default Site." unless @current_site.present?
|
20
|
+
@current_site
|
21
|
+
end
|
22
|
+
|
23
|
+
# Private: Returns a safe user, e.i. a logged user or a guest user.
|
24
|
+
#
|
25
|
+
# This is just a placeholder and should be implemented in the host app.
|
26
|
+
#
|
27
|
+
# Example:
|
28
|
+
#
|
29
|
+
# def safe_user
|
30
|
+
# current_user || AnonymousUser.new
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# Returns: an anonymous user.
|
34
|
+
#
|
35
|
+
def safe_user
|
36
|
+
AnonymousUser.new
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Xhive
|
2
|
+
class Mapper < ActiveRecord::Base
|
3
|
+
attr_accessible :action, :page, :site, :resource
|
4
|
+
|
5
|
+
belongs_to :site
|
6
|
+
belongs_to :page
|
7
|
+
|
8
|
+
validates :resource, :presence => true
|
9
|
+
validates :action, :presence => true
|
10
|
+
validates :site, :presence => true
|
11
|
+
validates :page, :presence => true
|
12
|
+
|
13
|
+
def self.page_for(resource, action)
|
14
|
+
page = where(:resource => resource).where(:action => action).first.try(:page)
|
15
|
+
fail ActiveRecord::RecordNotFound unless page.present?
|
16
|
+
page
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'friendly_id'
|
2
|
+
|
3
|
+
module Xhive
|
4
|
+
class Page < ActiveRecord::Base
|
5
|
+
extend ::FriendlyId
|
6
|
+
friendly_id :name, use: :slugged
|
7
|
+
|
8
|
+
include Xhive::Presentable
|
9
|
+
|
10
|
+
attr_accessible :content, :meta_description, :meta_keywords, :name, :slug, :title, :site
|
11
|
+
|
12
|
+
belongs_to :site
|
13
|
+
|
14
|
+
validates :name, :presence => true, :uniqueness => { :scope => :site_id }
|
15
|
+
validates :title, :presence => true
|
16
|
+
validates :content, :presence => true
|
17
|
+
validates :site, :presence => true
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Xhive
|
2
|
+
class Site < ActiveRecord::Base
|
3
|
+
attr_accessible :domain, :name, :home_page
|
4
|
+
|
5
|
+
has_many :pages
|
6
|
+
has_many :mappers
|
7
|
+
has_many :stylesheets
|
8
|
+
|
9
|
+
belongs_to :home_page, :class_name => 'Page'
|
10
|
+
|
11
|
+
validates :name, :presence => true
|
12
|
+
validates :domain, :presence => true
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'friendly_id'
|
2
|
+
require 'sass'
|
3
|
+
|
4
|
+
module Xhive
|
5
|
+
class Stylesheet < ActiveRecord::Base
|
6
|
+
extend ::FriendlyId
|
7
|
+
friendly_id :name, use: :slugged
|
8
|
+
|
9
|
+
include Xhive::Presentable
|
10
|
+
|
11
|
+
attr_accessible :content, :name, :slug, :site
|
12
|
+
|
13
|
+
belongs_to :site
|
14
|
+
|
15
|
+
validates :name, :presence => true, :uniqueness => { :scope => :site_id }
|
16
|
+
validates :content, :presence => true
|
17
|
+
validates :site, :presence => true
|
18
|
+
validate :css_syntax, :if => Proc.new { self.content.present? }
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def css_syntax
|
23
|
+
engine = Sass::Engine.new(content, :syntax => :scss)
|
24
|
+
engine.render
|
25
|
+
rescue Sass::SyntaxError => e
|
26
|
+
errors.add(:content, e.message)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Xhive
|
2
|
+
class BasePresenter
|
3
|
+
attr_reader :object
|
4
|
+
|
5
|
+
include ActionView::Helpers
|
6
|
+
include ActionView::Context
|
7
|
+
include Rails.application.routes.url_helpers
|
8
|
+
|
9
|
+
default_url_options[:host] = (Rails.application.config.action_mailer.default_url_options || {}).fetch(:host, 'localhost')
|
10
|
+
|
11
|
+
def initialize(object)
|
12
|
+
@object = object
|
13
|
+
end
|
14
|
+
|
15
|
+
def id
|
16
|
+
@object.id
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def controller
|
22
|
+
ApplicationController.current_controller
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.presents(name)
|
26
|
+
define_method(name) do
|
27
|
+
@object
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Xhive
|
2
|
+
class PagePresenter < Xhive::BasePresenter
|
3
|
+
presents :page
|
4
|
+
delegate :name, :title, :content, :meta_keywords, :meta_description, :to => :page
|
5
|
+
|
6
|
+
liquid_methods :name, :title, :content, :meta_keywords, :meta_description
|
7
|
+
|
8
|
+
def render_content(options={})
|
9
|
+
layout = ::Liquid::Template.parse("{{content}}").render({"content" => page.content})
|
10
|
+
text = ::Liquid::Template.parse(layout).render(
|
11
|
+
{'page' => self, 'user' => controller.safe_user.presenter}.merge(options.stringify_keys),
|
12
|
+
:registers => {:controller => controller}
|
13
|
+
)
|
14
|
+
result = text.html_safe
|
15
|
+
rescue => e
|
16
|
+
logger.debug "#{e.class.name}: #{e.message}"
|
17
|
+
logger.debug e.backtrace.join("/n")
|
18
|
+
result = ''
|
19
|
+
ensure
|
20
|
+
return result
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Xhive
|
2
|
+
class StylesheetPresenter < Xhive::BasePresenter
|
3
|
+
presents :stylesheet
|
4
|
+
delegate :name, :content, :to => :stylesheet
|
5
|
+
|
6
|
+
liquid_methods :name, :content, :compressed
|
7
|
+
|
8
|
+
def compressed
|
9
|
+
self.class.compress(stylesheet.content)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.all_compressed(stylesheets)
|
13
|
+
stylesheets.inject('') do |result, stylesheet|
|
14
|
+
result << compress(stylesheet.content)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
# Private: compress stylesheet content
|
21
|
+
#
|
22
|
+
# content - The string containing the stylesheet content
|
23
|
+
#
|
24
|
+
# Returns: the compressed CSS
|
25
|
+
#
|
26
|
+
def self.compress(content)
|
27
|
+
engine = Sass::Engine.new(content, :syntax => :scss, :style => :compressed)
|
28
|
+
engine.render
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title><%= @title || 'Xhive' %></title>
|
5
|
+
<%= stylesheet_link_tag "xhive/application", :media => "all" %>
|
6
|
+
<%= javascript_include_tag "xhive/application" %>
|
7
|
+
<%= javascript_include_tag "https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.min.js" %>
|
8
|
+
<%= include_custom_stylesheets %>
|
9
|
+
<%= csrf_meta_tags %>
|
10
|
+
</head>
|
11
|
+
<body>
|
12
|
+
<%= yield %>
|
13
|
+
<%= initialize_widgets_loader %>
|
14
|
+
</body>
|
15
|
+
</html>
|
data/config/routes.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Xhive::Engine.routes.draw do
|
2
|
+
resources :pages, :only => :show do
|
3
|
+
get 'widget', :on => :member
|
4
|
+
end
|
5
|
+
|
6
|
+
get 'stylesheets/custom.css', :to => 'stylesheets#index', :as => :stylesheets, :format => :css
|
7
|
+
|
8
|
+
resources :stylesheets, :only => :show, :format => :css
|
9
|
+
|
10
|
+
get 'widgets/*widget', :to => 'widgets#show'
|
11
|
+
|
12
|
+
root :to => 'pages#show'
|
13
|
+
end
|