action_page 0.1.0
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 +20 -0
- data/README.md +118 -0
- data/Rakefile +32 -0
- data/app/assets/config/action_page_manifest.js +1 -0
- data/app/assets/stylesheets/action_page/application.css +15 -0
- data/app/controllers/action_page/base_controller.rb +36 -0
- data/app/helpers/action_page/application_helper.rb +7 -0
- data/app/jobs/action_page/application_job.rb +4 -0
- data/app/mailers/action_page/application_mailer.rb +6 -0
- data/app/models/action_page/application_record.rb +5 -0
- data/app/models/action_page/base.rb +45 -0
- data/app/views/layouts/action_page/application.html.erb +15 -0
- data/config/environment.rb +0 -0
- data/config/routes.rb +2 -0
- data/lib/action_page.rb +5 -0
- data/lib/action_page/engine.rb +15 -0
- data/lib/action_page/template_handler.rb +34 -0
- data/lib/action_page/version.rb +3 -0
- data/lib/tasks/action_page_tasks.rake +4 -0
- metadata +118 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8c102ef0c54f16662928586b6340c1b0b7cacb12e4625ef3eff8afa630c3105a
|
4
|
+
data.tar.gz: 1dca2f2a761119fdaaf2fbf7e06e40c384699abaa13958b55ba35cd23dab5a13
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d688f8f9f18170f56ea3363f2273509a76ea8a8ba3f7c10f351f5a0686c6efffe5016ab8da19209b769ad71e4d73e818791a6dd08829e347211f416c752b2379
|
7
|
+
data.tar.gz: 4d08ae5cd821e1fd3902d4eadffd32a0b2dd6042bcec9ce9fe78b98de7bd972a819ad060be62c770430d2d24a9daafa8439b7ee44bf5de56a5d1a16ff8c1a97c
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2020 Caleb Hearth
|
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,118 @@
|
|
1
|
+
# ActionPage
|
2
|
+
|
3
|
+
ActionPage provides a Rails template handler for views ending in .yaml or .yml
|
4
|
+
which contain "frontmatter" that is valid YAML contained between two sets of
|
5
|
+
`---`, such as:
|
6
|
+
|
7
|
+
---
|
8
|
+
author: Caleb Hearth
|
9
|
+
website: https://calebhearth.com
|
10
|
+
likes:
|
11
|
+
- Dogs
|
12
|
+
- Frontmatter
|
13
|
+
- Rails
|
14
|
+
dislikes:
|
15
|
+
- Beets
|
16
|
+
---
|
17
|
+
|
18
|
+
This frontmatter is parsed and made available as getter methods in a model you
|
19
|
+
define per "collection" of views. This collection might be "posts" or "talks"
|
20
|
+
and conceptually it can be considered similarly to an ActiveRecord::Base
|
21
|
+
subclass, but with the view file as the data source rather than a database.
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
A simple use case would be to import blog posts into Rails from a Jekyll site.
|
26
|
+
The code to do that might look like the below. Note that the semantics are very
|
27
|
+
familiar to anyone who's used Rails applications for similar purposes.
|
28
|
+
|
29
|
+
### app/models/post.rb
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
class Post < ActionPost::Base
|
33
|
+
end
|
34
|
+
```
|
35
|
+
|
36
|
+
`ActionPost::Base` provides class-level "all" and "find(slug)" methods which
|
37
|
+
list all pages and finds the first page matching the slug. It also extracts all
|
38
|
+
frontmatter and provides it as getter methods such as `post.title`.
|
39
|
+
|
40
|
+
### app/controllers/posts_controller.rb
|
41
|
+
|
42
|
+
A controller is required, but there is no need to define the default actions.
|
43
|
+
Default index and show actions are provided that list all posts (all files in
|
44
|
+
app/views/posts with a .yaml or .yml extension) and finds posts based on their
|
45
|
+
"slug" which is the filename without any extensions.
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
class PostsController < ActionPage::BaseController
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
52
|
+
The ActionPost::Base subclass is inferred to be the singular of the Controller's
|
53
|
+
class name without "Controller", so `PostsController` would render `Post`
|
54
|
+
objects and look for views in `app/views/posts`. The class-level `renders_page`
|
55
|
+
method overrides this:
|
56
|
+
|
57
|
+
```
|
58
|
+
class PostsController < ActionPage::BaseController
|
59
|
+
renders_page :blog_post # BlogPost objects / app/views/blog_posts views.
|
60
|
+
end
|
61
|
+
```
|
62
|
+
|
63
|
+
### config/routes.rb
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
resources :posts, only: %i(index show)
|
67
|
+
```
|
68
|
+
|
69
|
+
### app/views/posts/my-first-post.md.yaml
|
70
|
+
|
71
|
+
This original Jekyll file would be called `_posts/2020-05-30-my-first-post.md`
|
72
|
+
and would not have a date field in the frontmatter. That would need to be
|
73
|
+
migrated manually or scripted. Date extraction from filename is not a feature of
|
74
|
+
ActionPage.
|
75
|
+
|
76
|
+
```markdown
|
77
|
+
|
78
|
+
---
|
79
|
+
title: My First Post
|
80
|
+
date: 2020-05-30
|
81
|
+
---
|
82
|
+
|
83
|
+
Look at all the things I'm not doing!
|
84
|
+
```
|
85
|
+
|
86
|
+
### app/views/posts/show.html.erb
|
87
|
+
|
88
|
+
```erb
|
89
|
+
<h1><%= @page.title %></h1>
|
90
|
+
<aside><%= time_tag @post.date %></aside>
|
91
|
+
<%= page_content @page %>
|
92
|
+
```
|
93
|
+
|
94
|
+
### app/views/posts/index.html.erb
|
95
|
+
|
96
|
+
```erb
|
97
|
+
<h1>My Posts</h1>
|
98
|
+
<ul><% @posts.each do |post| %>
|
99
|
+
<li><%= link_to @post.title, post_path(@post) %></li>
|
100
|
+
<% end %></ul>
|
101
|
+
```
|
102
|
+
|
103
|
+
## Installation
|
104
|
+
Add this line to your application's Gemfile:
|
105
|
+
|
106
|
+
```ruby
|
107
|
+
gem 'action_page'
|
108
|
+
```
|
109
|
+
|
110
|
+
And then execute:
|
111
|
+
```bash
|
112
|
+
$ bundle
|
113
|
+
```
|
114
|
+
|
115
|
+
Or install it yourself as:
|
116
|
+
```bash
|
117
|
+
$ gem install action_page
|
118
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
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 = 'ActionPage'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.md')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
|
18
|
+
load 'rails/tasks/engine.rake'
|
19
|
+
|
20
|
+
load 'rails/tasks/statistics.rake'
|
21
|
+
|
22
|
+
require 'bundler/gem_tasks'
|
23
|
+
|
24
|
+
require 'rake/testtask'
|
25
|
+
|
26
|
+
Rake::TestTask.new(:test) do |t|
|
27
|
+
t.libs << 'test'
|
28
|
+
t.pattern = 'test/**/*_test.rb'
|
29
|
+
t.verbose = false
|
30
|
+
end
|
31
|
+
|
32
|
+
task default: :test
|
@@ -0,0 +1 @@
|
|
1
|
+
//= link_directory ../stylesheets/action_page .css
|
@@ -0,0 +1,15 @@
|
|
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 any plugin's vendor/assets/stylesheets directory 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 bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
11
|
+
* It is generally better to create a new file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module ActionPage
|
2
|
+
class BaseController < ::ApplicationController
|
3
|
+
cattr_reader :page_class
|
4
|
+
helper ActionPage::ApplicationHelper
|
5
|
+
|
6
|
+
def self.renders_page(page)
|
7
|
+
@@page_class = page
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.page_class
|
11
|
+
@@page_class ||= begin
|
12
|
+
page_class = name.sub(/Controller\z/, '')
|
13
|
+
page_class.singularize.constantize
|
14
|
+
rescue NameError
|
15
|
+
raise #ActionPage::MissingPageClass.new(page: page_class)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(*args)
|
20
|
+
super
|
21
|
+
append_view_path("app/views/#{self.class.page_class.view_key}")
|
22
|
+
end
|
23
|
+
|
24
|
+
def index
|
25
|
+
@pages = page_class.all
|
26
|
+
end
|
27
|
+
|
28
|
+
def show
|
29
|
+
@page = page_class.find(params[:id])
|
30
|
+
if @page.nil?
|
31
|
+
raise ActionController::RoutingError.new("Not Found")
|
32
|
+
end
|
33
|
+
render
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module ActionPage
|
2
|
+
class Base
|
3
|
+
extend ActiveModel::Naming
|
4
|
+
attr_reader :slug
|
5
|
+
|
6
|
+
def self.all
|
7
|
+
Dir[pages_directory]
|
8
|
+
.reject { %w(index show).include? File.basename(_1.split('.')[0]) }
|
9
|
+
.map { |f| new(f) }
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.find(slug)
|
13
|
+
all.find { _1.slug == slug }
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.pages_directory
|
17
|
+
Rails.root.join("app", "views", view_key, '*.yaml').freeze
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(filename)
|
21
|
+
@slug = File.basename(filename.split('.')[0])
|
22
|
+
@frontmatter = YAML.load(File.read(filename)).with_indifferent_access
|
23
|
+
end
|
24
|
+
|
25
|
+
# TODO: Define attribute methods to speed this up
|
26
|
+
def method_missing(m, *args, &block)
|
27
|
+
if value = @frontmatter[m]
|
28
|
+
return value
|
29
|
+
end
|
30
|
+
super
|
31
|
+
end
|
32
|
+
|
33
|
+
def respond_to_missing(m)
|
34
|
+
@frontmatter.key(m)
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_param
|
38
|
+
slug
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.view_key
|
42
|
+
model_name.route_key
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
File without changes
|
data/config/routes.rb
ADDED
data/lib/action_page.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
module ActionPage
|
2
|
+
class Engine < ::Rails::Engine
|
3
|
+
isolate_namespace ActionPage
|
4
|
+
initializer "actionpage.load" do
|
5
|
+
ActiveSupport.on_load :action_view do
|
6
|
+
ActionView::Template.register_template_handler(
|
7
|
+
# Accept all existing handlers with additional .yaml or .yml extension
|
8
|
+
*ActionView::Template.template_handler_extensions.flat_map { %W(#{_1}.yaml #{_1}.yml) },
|
9
|
+
:yml, :yaml,
|
10
|
+
ActionPage::TemplateHandler
|
11
|
+
)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module ActionPage
|
2
|
+
class TemplateHandler
|
3
|
+
def self.call(template, source)
|
4
|
+
new(template, source).call
|
5
|
+
end
|
6
|
+
|
7
|
+
def initialize(template, source)
|
8
|
+
@template = template
|
9
|
+
@source = source
|
10
|
+
end
|
11
|
+
|
12
|
+
def call
|
13
|
+
handler_for_template.call(@template, source_without_yaml)
|
14
|
+
end
|
15
|
+
|
16
|
+
def handler_for_template
|
17
|
+
ApplicationController.new.view_paths.paths.first
|
18
|
+
.extract_handler_and_format_and_variant(path_without_yaml)
|
19
|
+
.first
|
20
|
+
end
|
21
|
+
|
22
|
+
def source_without_yaml
|
23
|
+
@source.lines[last_line+1...].join
|
24
|
+
end
|
25
|
+
|
26
|
+
def path_without_yaml
|
27
|
+
@template.short_identifier.sub(/.ya?ml\z/, '')
|
28
|
+
end
|
29
|
+
|
30
|
+
def last_line
|
31
|
+
YAML.parse(@source).root.end_line
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
metadata
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: action_page
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Caleb Hearth
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-05-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: railties
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activesupport
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rails
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pg
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description:
|
70
|
+
email:
|
71
|
+
- caleb@calebhearth.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- LICENSE
|
77
|
+
- README.md
|
78
|
+
- Rakefile
|
79
|
+
- app/assets/config/action_page_manifest.js
|
80
|
+
- app/assets/stylesheets/action_page/application.css
|
81
|
+
- app/controllers/action_page/base_controller.rb
|
82
|
+
- app/helpers/action_page/application_helper.rb
|
83
|
+
- app/jobs/action_page/application_job.rb
|
84
|
+
- app/mailers/action_page/application_mailer.rb
|
85
|
+
- app/models/action_page/application_record.rb
|
86
|
+
- app/models/action_page/base.rb
|
87
|
+
- app/views/layouts/action_page/application.html.erb
|
88
|
+
- config/environment.rb
|
89
|
+
- config/routes.rb
|
90
|
+
- lib/action_page.rb
|
91
|
+
- lib/action_page/engine.rb
|
92
|
+
- lib/action_page/template_handler.rb
|
93
|
+
- lib/action_page/version.rb
|
94
|
+
- lib/tasks/action_page_tasks.rake
|
95
|
+
homepage: https://calebhearth.com
|
96
|
+
licenses:
|
97
|
+
- MIT
|
98
|
+
metadata: {}
|
99
|
+
post_install_message:
|
100
|
+
rdoc_options: []
|
101
|
+
require_paths:
|
102
|
+
- lib
|
103
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
108
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
requirements: []
|
114
|
+
rubygems_version: 3.1.2
|
115
|
+
signing_key:
|
116
|
+
specification_version: 4
|
117
|
+
summary: Semi-static pages with data in Rails.
|
118
|
+
test_files: []
|