nocms-pages 0.0.1
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.
- checksums.yaml +7 -0
- data/LICENSE +674 -0
- data/README.md +4 -0
- data/Rakefile +21 -0
- data/app/assets/stylesheets/pages/application.css +13 -0
- data/app/controllers/no_cms/pages/application_controller.rb +6 -0
- data/app/controllers/no_cms/pages/pages_controller.rb +12 -0
- data/app/helpers/no_cms/pages/application_helper.rb +6 -0
- data/app/models/no_cms/pages/block.rb +146 -0
- data/app/models/no_cms/pages/concerns/translation_scopes.rb +16 -0
- data/app/models/no_cms/pages/page.rb +37 -0
- data/app/views/layouts/nocms/pages/application.html.erb +14 -0
- data/app/views/no_cms/pages/blocks/_default.html.erb +8 -0
- data/app/views/no_cms/pages/pages/show.html.erb +6 -0
- data/config/locales/en.yml +18 -0
- data/config/routes.rb +6 -0
- data/db/migrate/20140226123742_create_no_cms_pages.rb +14 -0
- data/db/migrate/20140227100626_create_no_cms_blocks.rb +16 -0
- data/db/migrate/20140227143723_add_fields_info_to_no_cms_block.rb +5 -0
- data/db/migrate/20140228112643_add_slug_to_no_cms_page.rb +5 -0
- data/db/migrate/20140303092727_add_awesome_nested_set_to_no_cms_pages.rb +8 -0
- data/db/migrate/20140303100908_add_path_to_no_cms_page.rb +5 -0
- data/db/migrate/20140303123845_add_poisition_to_no_cms_block.rb +5 -0
- data/db/migrate/20140303145615_add_template_to_no_cms_page.rb +5 -0
- data/db/migrate/20140313171000_add_draft_to_block.rb +5 -0
- data/db/migrate/20140314110439_add_draft_to_pages.rb +5 -0
- data/lib/generators/nocms/pages_generator.rb +15 -0
- data/lib/generators/nocms/templates/config/initializers/nocms/pages.rb +25 -0
- data/lib/nocms/pages/configuration.rb +18 -0
- data/lib/nocms/pages/engine.rb +10 -0
- data/lib/nocms/pages/routes/page_found_constraint.rb +9 -0
- data/lib/nocms/pages/routes.rb +1 -0
- data/lib/nocms/pages/version.rb +5 -0
- data/lib/nocms_pages.rb +8 -0
- data/lib/tasks/pages_tasks.rake +4 -0
- metadata +153 -0
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'Pages'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.rdoc')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
Bundler::GemHelper.install_tasks
|
21
|
+
|
@@ -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,12 @@
|
|
1
|
+
require_dependency "no_cms/pages/application_controller"
|
2
|
+
|
3
|
+
module NoCms::Pages
|
4
|
+
class PagesController < ApplicationController
|
5
|
+
def show
|
6
|
+
@page = Page.no_drafts.where(path: "/#{params[:path]}").first
|
7
|
+
raise ActionController::RoutingError.new('Not Found') if @page.nil?
|
8
|
+
|
9
|
+
render @page.template unless @page.template.blank?
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
module NoCms::Pages
|
2
|
+
class Block < ActiveRecord::Base
|
3
|
+
|
4
|
+
include Concerns::TranslationScopes
|
5
|
+
|
6
|
+
scope :drafts, ->() { where_with_locale(draft: true) }
|
7
|
+
scope :no_drafts, ->() { where_with_locale(draft: false) }
|
8
|
+
|
9
|
+
belongs_to :page
|
10
|
+
|
11
|
+
attr_reader :cached_objects
|
12
|
+
|
13
|
+
translates :layout, :fields_info, :draft
|
14
|
+
|
15
|
+
class Translation
|
16
|
+
serialize :fields_info, Hash
|
17
|
+
end
|
18
|
+
|
19
|
+
after_initialize :set_blank_fields
|
20
|
+
after_create :set_default_position
|
21
|
+
before_save :save_related_objects
|
22
|
+
|
23
|
+
validates :fields_info, presence: { allow_blank: true }
|
24
|
+
validates :page, :layout, presence: true
|
25
|
+
|
26
|
+
def layout_config
|
27
|
+
NoCms::Pages.block_layouts.stringify_keys[layout]
|
28
|
+
end
|
29
|
+
|
30
|
+
def template
|
31
|
+
layout_config[:template] if layout_config
|
32
|
+
end
|
33
|
+
|
34
|
+
def has_field? field
|
35
|
+
# We have the field if...
|
36
|
+
!layout_config.nil? && # We have a layout configuration AND
|
37
|
+
(
|
38
|
+
!layout_config[:fields].symbolize_keys[field.to_sym].nil? || # We have this field OR
|
39
|
+
!layout_config[:fields].symbolize_keys[field.to_s.gsub(/\_id$/, '').to_sym].nil? # we remove the final _id and then we have the field
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
def field_type field
|
44
|
+
return nil unless has_field?(field)
|
45
|
+
layout_config[:fields].symbolize_keys[field.to_sym]
|
46
|
+
end
|
47
|
+
|
48
|
+
def read_field field
|
49
|
+
return nil unless has_field?(field)
|
50
|
+
|
51
|
+
value = fields_info[field.to_sym] || # first, we get the value
|
52
|
+
@cached_objects[field.to_sym] # or we get it from the cached objects
|
53
|
+
|
54
|
+
# If value is still nil, but the field exists we must get the object from the database
|
55
|
+
if value.nil?
|
56
|
+
field_id = fields_info["#{field}_id".to_sym]
|
57
|
+
value = @cached_objects[field.to_sym] = field_type(field).find(field_id) unless field_id.nil?
|
58
|
+
end
|
59
|
+
|
60
|
+
value
|
61
|
+
end
|
62
|
+
|
63
|
+
def write_field field, value
|
64
|
+
return nil unless has_field?(field)
|
65
|
+
field_type = field_type field
|
66
|
+
# If field type is a model then we update the cached object
|
67
|
+
if field_type.is_a?(Class) && field_type < ActiveRecord::Base
|
68
|
+
# First, we initialize the object if we don't read the object (it loads it into the cached objects)
|
69
|
+
@cached_objects[field.to_sym] = field_type.new if read_field(field).nil?
|
70
|
+
# Then, assign attributes
|
71
|
+
@cached_objects[field.to_sym].assign_attributes value
|
72
|
+
else # If it's a model then a new object or update the previous one
|
73
|
+
self.fields_info = fields_info.merge field.to_sym => value # when updating through an object (i.e. the page updates through nested attributes) fields_info[field.to_sym] = value doesn't work. Kudos to Rubo for this fix
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# In this missing method we check wether we're asking for one field
|
78
|
+
# in which case we will read or write ir
|
79
|
+
def method_missing(m, *args, &block)
|
80
|
+
# We get the name of the field stripping out the '=' for writers
|
81
|
+
field = m.to_s
|
82
|
+
write_accessor = field.ends_with? '='
|
83
|
+
field.gsub!(/\=$/, '')
|
84
|
+
|
85
|
+
# If this field actually exists, then we write it or read it.
|
86
|
+
if has_field?(field)
|
87
|
+
write_accessor ?
|
88
|
+
write_field(field, args.first) :
|
89
|
+
read_field(field.to_sym)
|
90
|
+
else
|
91
|
+
super
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# When we are assigning attributes (this method is called in new, create...)
|
96
|
+
# we must split those fields from our current layout and those who are not
|
97
|
+
# (they must be attributes).
|
98
|
+
# Attributes are processed the usual way and fields are written later
|
99
|
+
def assign_attributes new_attributes
|
100
|
+
fields = []
|
101
|
+
|
102
|
+
set_blank_fields
|
103
|
+
|
104
|
+
# We get the layout
|
105
|
+
new_layout = new_attributes[:layout] || new_attributes['layout']
|
106
|
+
self.layout = new_layout unless new_layout.nil?
|
107
|
+
|
108
|
+
# And now separate fields and attributes
|
109
|
+
fields = new_attributes.select{|k, _| has_field? k }.symbolize_keys
|
110
|
+
new_attributes.reject!{|k, _| has_field? k }
|
111
|
+
|
112
|
+
super(new_attributes)
|
113
|
+
|
114
|
+
Rails.logger.info "Writing #{fields.inspect} to #{self.layout} block"
|
115
|
+
|
116
|
+
fields.each do |field_name, value|
|
117
|
+
self.write_field field_name, value
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def reload
|
122
|
+
@cached_objects = {}
|
123
|
+
super
|
124
|
+
end
|
125
|
+
|
126
|
+
private
|
127
|
+
|
128
|
+
def set_blank_fields
|
129
|
+
self.fields_info ||= {}
|
130
|
+
@cached_objects ||= {}
|
131
|
+
end
|
132
|
+
|
133
|
+
def set_default_position
|
134
|
+
self.update_attribute :position, ((page.blocks.pluck(:position).compact.max || 0) + 1) if self.position.blank?
|
135
|
+
end
|
136
|
+
|
137
|
+
def save_related_objects
|
138
|
+
cached_objects.each do |field, object|
|
139
|
+
if object.is_a?(ActiveRecord::Base) && object.changed?
|
140
|
+
object.save!
|
141
|
+
fields_info["#{field}_id".to_sym] = object.id
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module NoCms
|
2
|
+
module Pages
|
3
|
+
module Concerns
|
4
|
+
module TranslationScopes
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
scope :where_with_locale, ->(where_params, locale = ::I18n.locale) {
|
9
|
+
with_translations(locale).where(self::Translation.table_name => where_params)
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module NoCms::Pages
|
2
|
+
class Page < ActiveRecord::Base
|
3
|
+
|
4
|
+
include Concerns::TranslationScopes
|
5
|
+
|
6
|
+
scope :drafts, ->() { where_with_locale(draft: true) }
|
7
|
+
scope :no_drafts, ->() { where_with_locale(draft: false) }
|
8
|
+
|
9
|
+
acts_as_nested_set
|
10
|
+
|
11
|
+
has_many :blocks, inverse_of: :page, class_name: 'NoCms::Pages::Block'
|
12
|
+
accepts_nested_attributes_for :blocks, allow_destroy: true
|
13
|
+
|
14
|
+
translates :title, :body, :slug, :path, :draft
|
15
|
+
|
16
|
+
validates :title, :body, presence: true
|
17
|
+
validates :slug, presence: { allow_blank: true }
|
18
|
+
|
19
|
+
before_validation :set_slug_and_path
|
20
|
+
after_move :rebuild_path
|
21
|
+
|
22
|
+
def set_slug_and_path
|
23
|
+
self.slug = title.parameterize if slug.nil? && !title.nil?
|
24
|
+
self.rebuild_path if path.nil?
|
25
|
+
end
|
26
|
+
|
27
|
+
def rebuild_path
|
28
|
+
self.update_attribute :path, "#{ancestors.map(&:path).join}/#{slug}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.templates
|
32
|
+
Dir[Rails.root.join('app', 'views', 'no_cms', 'pages', 'pages', '*.html.erb').to_s]. # We get all page templates
|
33
|
+
map { |f| File.basename(f, '.html.erb') }.uniq.sort # And get their names
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Pages</title>
|
5
|
+
<%= stylesheet_link_tag "pages/application", media: "all" %>
|
6
|
+
<%= javascript_include_tag "pages/application" %>
|
7
|
+
<%= csrf_meta_tags %>
|
8
|
+
</head>
|
9
|
+
<body>
|
10
|
+
|
11
|
+
<%= yield %>
|
12
|
+
|
13
|
+
</body>
|
14
|
+
</html>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
en:
|
2
|
+
activerecord:
|
3
|
+
models:
|
4
|
+
no_cms/pages/page: Page
|
5
|
+
no_cms/pages/block: Content Block
|
6
|
+
attributes:
|
7
|
+
no_cms/pages/page:
|
8
|
+
title: Title
|
9
|
+
body: Body
|
10
|
+
no_cms/pages/block:
|
11
|
+
layout: Layout
|
12
|
+
title: Title
|
13
|
+
body: Body
|
14
|
+
no_cms:
|
15
|
+
pages:
|
16
|
+
blocks:
|
17
|
+
layouts:
|
18
|
+
default: Default layout
|
data/config/routes.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
class CreateNoCmsPages < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :no_cms_pages_pages do |t|
|
4
|
+
t.timestamps
|
5
|
+
end
|
6
|
+
|
7
|
+
create_table :no_cms_pages_page_translations do |t|
|
8
|
+
t.belongs_to :no_cms_pages_page, index: true
|
9
|
+
t.string :locale
|
10
|
+
t.string :title
|
11
|
+
t.string :body
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class CreateNoCmsBlocks < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :no_cms_pages_blocks do |t|
|
4
|
+
t.belongs_to :page, index: true
|
5
|
+
|
6
|
+
t.timestamps
|
7
|
+
end
|
8
|
+
|
9
|
+
create_table :no_cms_pages_block_translations do |t|
|
10
|
+
t.belongs_to :no_cms_pages_block, index: true
|
11
|
+
t.string :locale
|
12
|
+
t.string :layout
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
class AddAwesomeNestedSetToNoCmsPages < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
add_column :no_cms_pages_pages, :parent_id, :integer
|
4
|
+
add_column :no_cms_pages_pages, :lft, :integer
|
5
|
+
add_column :no_cms_pages_pages, :rgt, :integer
|
6
|
+
add_column :no_cms_pages_pages, :depth, :integer
|
7
|
+
end
|
8
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module NoCms
|
2
|
+
class PagesGenerator < Rails::Generators::Base
|
3
|
+
|
4
|
+
source_root File.expand_path("../templates/", __FILE__)
|
5
|
+
|
6
|
+
def generate_nocms_pages_initializer
|
7
|
+
template "config/initializers/nocms/pages.rb", File.join(destination_root, "config", "initializers", "nocms", "pages.rb")
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.namespace
|
11
|
+
"nocms:pages"
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
NoCms::Pages.configure do |config|
|
2
|
+
|
3
|
+
# In this section we configure block layouts. It's just an array of layouts, each consisting on a hash.
|
4
|
+
# Each layout has a template and a list of fields with a type.
|
5
|
+
# E.g: config.block_layouts = {
|
6
|
+
# 'title-long_text' => {
|
7
|
+
# template: 'title-long_text',
|
8
|
+
# fields: {
|
9
|
+
# title: :string,
|
10
|
+
# long_text: :text
|
11
|
+
# }
|
12
|
+
# },
|
13
|
+
# 'title-3_columns_text' => {
|
14
|
+
# template: 'title-3_columns_text',
|
15
|
+
# fields: {
|
16
|
+
# title: :string,
|
17
|
+
# column_1: :text,
|
18
|
+
# column_2: :text,
|
19
|
+
# column_3: :text
|
20
|
+
# }
|
21
|
+
# }
|
22
|
+
# }
|
23
|
+
# config.block_layouts = {}
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module NoCms
|
2
|
+
module Pages
|
3
|
+
include ActiveSupport::Configurable
|
4
|
+
|
5
|
+
config_accessor :block_layouts
|
6
|
+
|
7
|
+
self.block_layouts = {
|
8
|
+
'default' => {
|
9
|
+
template: 'default',
|
10
|
+
fields: {
|
11
|
+
title: :string,
|
12
|
+
body: :text
|
13
|
+
}
|
14
|
+
}
|
15
|
+
}
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module NoCms::Pages::Routes
|
2
|
+
class PageFoundConstraint
|
3
|
+
|
4
|
+
# A filter URL must NOT have a qualification as the first of its path filters
|
5
|
+
def self.matches?(request)
|
6
|
+
@page = NoCms::Pages::Page.no_drafts.where(path: "/#{request.params[:path]}").exists?
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'nocms/pages/routes/page_found_constraint'
|
data/lib/nocms_pages.rb
ADDED