effective_posts 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/MIT-LICENSE +20 -0
- data/README.md +7 -0
- data/Rakefile +24 -0
- data/app/assets/javascripts/effective/snippets/read_more_divider.js.coffee +22 -0
- data/app/assets/javascripts/effective_posts.js +0 -0
- data/app/assets/stylesheets/effective_posts.scss +0 -0
- data/app/controllers/admin/posts_controller.rb +91 -0
- data/app/controllers/effective/posts_controller.rb +51 -0
- data/app/helpers/effective_kaminari_helper.rb +16 -0
- data/app/helpers/effective_posts_helper.rb +42 -0
- data/app/models/effective/access_denied.rb +17 -0
- data/app/models/effective/datatables/posts.rb +21 -0
- data/app/models/effective/post.rb +39 -0
- data/app/models/effective/snippets/read_more_divider.rb +9 -0
- data/app/views/admin/posts/_actions.html.haml +9 -0
- data/app/views/admin/posts/_form.html.haml +27 -0
- data/app/views/admin/posts/edit.html.haml +2 -0
- data/app/views/admin/posts/index.html.haml +10 -0
- data/app/views/admin/posts/new.html.haml +2 -0
- data/app/views/effective/posts/_post.html.haml +9 -0
- data/app/views/effective/posts/_spacer.html.haml +0 -0
- data/app/views/effective/posts/index.html.haml +4 -0
- data/app/views/effective/posts/show.html.haml +12 -0
- data/app/views/effective/snippets/_read_more_divider.html.haml +9 -0
- data/app/views/kaminari/_first_page.html.haml +2 -0
- data/app/views/kaminari/_gap.html.haml +2 -0
- data/app/views/kaminari/_last_page.html.haml +2 -0
- data/app/views/kaminari/_next_page.html.haml +2 -0
- data/app/views/kaminari/_page.html.haml +6 -0
- data/app/views/kaminari/_paginator.html.haml +11 -0
- data/app/views/kaminari/_prev_page.html.haml +2 -0
- data/config/routes.rb +24 -0
- data/db/migrate/01_create_effective_posts.rb.erb +26 -0
- data/lib/effective_posts.rb +28 -0
- data/lib/effective_posts/engine.rb +18 -0
- data/lib/effective_posts/version.rb +3 -0
- data/lib/generators/effective_posts/install_generator.rb +33 -0
- data/lib/generators/templates/README +1 -0
- data/lib/generators/templates/effective_posts.rb +53 -0
- data/spec/effective_pages_spec.rb +7 -0
- data/spec/spec_helper.rb +43 -0
- data/spec/support/factories.rb +15 -0
- metadata +201 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 100e7584144d920e1e8995378769739f0e384c3c
|
|
4
|
+
data.tar.gz: 7add52b82afb4b69dc3bfd0953e2b0a842b2bacb
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 868c82a3b6305bfe6dde3e1d1b98fbfe1384aeadee15ce0c2b5e928e053f0ec61a1fe69f5d55dc1a29ecebe63248325ed44df29d810bcbe89d2c77c38002526f
|
|
7
|
+
data.tar.gz: 30f629262ee514f2ca20fbe46ae628637ee5117278dfc1f11ca024c40ed36f8f406dfe7cd239af424f16e765adf3bfdc4c3652fb1a4d0f42986d4fee9922ab77
|
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright 2015 Code and Effect Inc.
|
|
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
data/Rakefile
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
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
|
+
|
|
8
|
+
# Our tasks
|
|
9
|
+
load 'lib/tasks/effective_posts_tasks.rake'
|
|
10
|
+
|
|
11
|
+
# Testing tasks
|
|
12
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
|
13
|
+
load 'rails/tasks/engine.rake'
|
|
14
|
+
|
|
15
|
+
require "bundler/vendored_thor"
|
|
16
|
+
Bundler::GemHelper.install_tasks
|
|
17
|
+
|
|
18
|
+
require 'rspec/core'
|
|
19
|
+
require 'rspec/core/rake_task'
|
|
20
|
+
|
|
21
|
+
desc "Run all specs in spec directory (excluding plugin specs)"
|
|
22
|
+
RSpec::Core::RakeTask.new(:spec => 'app:db:test:prepare')
|
|
23
|
+
|
|
24
|
+
task :default => :spec
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
CKEDITOR.dialog.add 'read_more_divider', (editor) -> # Must match the class name of the snippet
|
|
2
|
+
title: 'Read more divider',
|
|
3
|
+
minWidth: 200,
|
|
4
|
+
minHeight: 100,
|
|
5
|
+
contents: [
|
|
6
|
+
{
|
|
7
|
+
id: 'read_more_info', # Just an html id, doesn't really matter what is here
|
|
8
|
+
elements: [
|
|
9
|
+
{
|
|
10
|
+
id: 'throwaway'
|
|
11
|
+
type: 'html',
|
|
12
|
+
html: 'Insert a read more divider to separate excerpt content from the full content.',
|
|
13
|
+
setup: (widget) -> this.setValue(widget.data.throwaway)
|
|
14
|
+
commit: (widget) -> widget.setData('throwaway', 'throwaway')
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
type: 'html',
|
|
18
|
+
html: 'Anything above the read more divider will be treated as excerpt content<br>and everything below the divider will also be included in the full content.'
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
}
|
|
22
|
+
]
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
module Admin
|
|
2
|
+
class PostsController < ApplicationController
|
|
3
|
+
before_filter :authenticate_user! if respond_to?(:authenticate_user!) # This is devise, ensure we're logged in.
|
|
4
|
+
|
|
5
|
+
layout (EffectivePosts.layout.kind_of?(Hash) ? EffectivePosts.layout[:admin] : EffectivePosts.layout)
|
|
6
|
+
|
|
7
|
+
def index
|
|
8
|
+
@page_title = 'Posts'
|
|
9
|
+
EffectivePosts.authorized?(self, :index, Effective::Post)
|
|
10
|
+
|
|
11
|
+
@datatable = Effective::Datatables::Posts.new() if defined?(EffectiveDatatables)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def new
|
|
15
|
+
@post = Effective::Post.new(:published_at => Time.zone.now)
|
|
16
|
+
@page_title = 'New Post'
|
|
17
|
+
|
|
18
|
+
EffectivePosts.authorized?(self, :new, @post)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def create
|
|
22
|
+
@post = Effective::Post.new(post_params)
|
|
23
|
+
@post.user = current_user if defined?(current_user)
|
|
24
|
+
|
|
25
|
+
@page_title = 'New Post'
|
|
26
|
+
|
|
27
|
+
EffectivePosts.authorized?(self, :create, @post)
|
|
28
|
+
|
|
29
|
+
if @post.save
|
|
30
|
+
if params[:commit] == 'Save and Edit Content' && defined?(EffectiveRegions)
|
|
31
|
+
redirect_to effective_regions.edit_path(effective_posts.post_path(@post), :exit => effective_posts.edit_admin_post_path(@post))
|
|
32
|
+
else
|
|
33
|
+
flash[:success] = 'Successfully created post'
|
|
34
|
+
redirect_to effective_posts.edit_admin_post_path(@post)
|
|
35
|
+
end
|
|
36
|
+
else
|
|
37
|
+
flash.now[:danger] = 'Unable to create post'
|
|
38
|
+
render :action => :new
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def edit
|
|
43
|
+
@post = Effective::Post.find(params[:id])
|
|
44
|
+
@page_title = 'Edit Post'
|
|
45
|
+
|
|
46
|
+
EffectivePosts.authorized?(self, :edit, @post)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def update
|
|
50
|
+
@post = Effective::Post.find(params[:id])
|
|
51
|
+
@page_title = 'Edit Post'
|
|
52
|
+
|
|
53
|
+
EffectivePosts.authorized?(self, :update, @post)
|
|
54
|
+
|
|
55
|
+
if @post.update_attributes(post_params)
|
|
56
|
+
if params[:commit] == 'Save and Edit Content' && defined?(EffectiveRegions)
|
|
57
|
+
redirect_to effective_regions.edit_path(effective_posts.post_path(@post))
|
|
58
|
+
else
|
|
59
|
+
flash[:success] = 'Successfully updated post'
|
|
60
|
+
redirect_to effective_posts.edit_admin_post_path(@post)
|
|
61
|
+
end
|
|
62
|
+
else
|
|
63
|
+
flash.now[:danger] = 'Unable to update post'
|
|
64
|
+
render :action => :edit
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def destroy
|
|
69
|
+
@post = Effective::Post.find(params[:id])
|
|
70
|
+
|
|
71
|
+
EffectivePosts.authorized?(self, :destroy, @post)
|
|
72
|
+
|
|
73
|
+
if @post.destroy
|
|
74
|
+
flash[:success] = 'Successfully deleted post'
|
|
75
|
+
else
|
|
76
|
+
flash[:danger] = 'Unable to delete post'
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
redirect_to effective_posts.admin_posts_path
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
private
|
|
83
|
+
|
|
84
|
+
def post_params
|
|
85
|
+
params.require(:effective_post).permit(
|
|
86
|
+
:title, :draft, :category, :published_at, :roles => []
|
|
87
|
+
)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
end
|
|
91
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module Effective
|
|
2
|
+
class PostsController < ApplicationController
|
|
3
|
+
layout (EffectivePosts.layout.kind_of?(Hash) ? EffectivePosts.layout[:posts] : EffectivePosts.layout)
|
|
4
|
+
|
|
5
|
+
after_action :monkey_patch_for_kaminari, :only => [:index]
|
|
6
|
+
|
|
7
|
+
def index
|
|
8
|
+
@posts = (Rails::VERSION::MAJOR > 3 ? Effective::Post.all : Effective::Post.scoped)
|
|
9
|
+
|
|
10
|
+
if defined?(EffectiveRoles) && (current_user.respond_to?(:roles) rescue false)
|
|
11
|
+
@posts = @posts.for_role(current_user.roles)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
@posts = @posts.includes(:regions)
|
|
15
|
+
@posts = @posts.with_category(params[:category]) if params[:category]
|
|
16
|
+
@posts = @posts.published
|
|
17
|
+
|
|
18
|
+
@posts = @posts.order("#{EffectivePosts.posts_table_name}.published_at DESC")
|
|
19
|
+
@posts = @posts.page(params[:page]).per(EffectivePosts.per_page)
|
|
20
|
+
|
|
21
|
+
EffectivePosts.authorized?(self, :index, Effective::Post)
|
|
22
|
+
|
|
23
|
+
@page_title = (params[:category] || 'Posts').titleize
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def show
|
|
27
|
+
@posts = (Rails::VERSION::MAJOR > 3 ? Effective::Post.all : Effective::Post.scoped)
|
|
28
|
+
|
|
29
|
+
if defined?(EffectiveRoles) && (current_user.respond_to?(:roles) rescue false)
|
|
30
|
+
@posts = @posts.for_role(current_user.roles)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
@posts = @posts.includes(:regions)
|
|
34
|
+
@posts = @posts.with_category(params[:category]) if params[:category]
|
|
35
|
+
@posts = @posts.published if params[:edit].to_s != 'true'
|
|
36
|
+
|
|
37
|
+
@post = @posts.find(params[:id])
|
|
38
|
+
|
|
39
|
+
EffectivePosts.authorized?(self, :show, @post)
|
|
40
|
+
|
|
41
|
+
@page_title = @post.title
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
def monkey_patch_for_kaminari
|
|
47
|
+
@template = @template.tap { |template| template.extend(EffectiveKaminariHelper) }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# This extends the @template.url_for method to work with Kaminari
|
|
2
|
+
# It is only extended on the posts#index method, for minimal pollution
|
|
3
|
+
|
|
4
|
+
module EffectiveKaminariHelper
|
|
5
|
+
def url_for(params)
|
|
6
|
+
if params.kind_of?(Hash) && params[:controller] == 'effective/posts' && params[:action] == 'index'
|
|
7
|
+
params.delete(:page) if params[:page].blank?
|
|
8
|
+
params.delete(:category) if EffectivePosts.use_category_routes
|
|
9
|
+
params = params.except(:action, :controller, :only_path)
|
|
10
|
+
|
|
11
|
+
request.path.to_s + (params.present? ? '?' : '') + params.to_param
|
|
12
|
+
else
|
|
13
|
+
super
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
module EffectivePostsHelper
|
|
2
|
+
def render_post(post)
|
|
3
|
+
render(:partial => 'effective/posts/post', :locals => {:post => post})
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def post_meta(post)
|
|
7
|
+
[
|
|
8
|
+
"Published",
|
|
9
|
+
"on #{post.published_at.strftime("%d-%b-%Y %l:%M %p")}",
|
|
10
|
+
("to #{link_to_post_category(post.category)}" if Array(EffectivePosts.categories).length > 0),
|
|
11
|
+
("by #{post.user.to_s.presence || 'Unknown'}" if EffectivePosts.post_meta_author)
|
|
12
|
+
].compact.join(' ').html_safe
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def post_excerpt(post, options = {})
|
|
16
|
+
content = effective_region(post, :content) { "<p>Default content</p>".html_safe }
|
|
17
|
+
|
|
18
|
+
index = content.index(Effective::Snippets::ReadMoreDivider::TOKEN)
|
|
19
|
+
|
|
20
|
+
if index.present? # We have to return the excerpt and add a Read more... link
|
|
21
|
+
content[0...index].html_safe +
|
|
22
|
+
content_tag(:p, :class => 'post-read-more') do
|
|
23
|
+
link_to((options.delete(:label) || 'Read more...'), effective_post_path(post), options)
|
|
24
|
+
end
|
|
25
|
+
else
|
|
26
|
+
content
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def link_to_post_category(category, options = {})
|
|
31
|
+
category = category.to_s.downcase
|
|
32
|
+
|
|
33
|
+
href = EffectivePosts.use_category_routes ? "/#{category}" : effective_posts.posts_path(:category => category.to_s)
|
|
34
|
+
link_to(category.to_s.titleize, href, options)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def effective_post_path(post)
|
|
38
|
+
category = post.category.to_s.downcase
|
|
39
|
+
EffectivePosts.use_category_routes ? "/#{category}/#{post.to_param}" : effective_posts.post_path(post, :category => category.to_s)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
unless defined?(Effective::AccessDenied)
|
|
2
|
+
module Effective
|
|
3
|
+
class AccessDenied < StandardError
|
|
4
|
+
attr_reader :action, :subject
|
|
5
|
+
|
|
6
|
+
def initialize(message = nil, action = nil, subject = nil)
|
|
7
|
+
@message = message
|
|
8
|
+
@action = action
|
|
9
|
+
@subject = subject
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def to_s
|
|
13
|
+
@message || I18n.t(:'unauthorized.default', :default => 'Access Denied')
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
if defined?(EffectiveDatatables)
|
|
2
|
+
module Effective
|
|
3
|
+
module Datatables
|
|
4
|
+
class Posts < Effective::Datatable
|
|
5
|
+
table_column :id
|
|
6
|
+
|
|
7
|
+
table_column :title
|
|
8
|
+
table_column :category, :filter => {:type => :select, :values => EffectivePosts.categories }
|
|
9
|
+
|
|
10
|
+
table_column :draft
|
|
11
|
+
table_column :published_at
|
|
12
|
+
|
|
13
|
+
table_column :actions, :sortable => false, :filter => false, :partial => '/admin/posts/actions'
|
|
14
|
+
|
|
15
|
+
def collection
|
|
16
|
+
Effective::Post.all
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module Effective
|
|
2
|
+
class Post < ActiveRecord::Base
|
|
3
|
+
acts_as_role_restricted if defined?(EffectiveRoles)
|
|
4
|
+
acts_as_regionable if defined?(EffectiveRegions)
|
|
5
|
+
|
|
6
|
+
self.table_name = EffectivePosts.posts_table_name.to_s
|
|
7
|
+
|
|
8
|
+
belongs_to :user
|
|
9
|
+
|
|
10
|
+
structure do
|
|
11
|
+
title :string, :validates => [:presence]
|
|
12
|
+
category :string, :validates => [:presence]
|
|
13
|
+
|
|
14
|
+
published_at :datetime, :validates => [:presence]
|
|
15
|
+
|
|
16
|
+
draft :boolean, :default => false
|
|
17
|
+
|
|
18
|
+
tags :text
|
|
19
|
+
|
|
20
|
+
roles_mask :integer, :default => 0
|
|
21
|
+
|
|
22
|
+
timestamps
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
scope :drafts, -> { where(:draft => true) }
|
|
26
|
+
scope :published, -> { where(:draft => false).where("#{EffectivePosts.posts_table_name}.published_at < ?", Time.zone.now) }
|
|
27
|
+
scope :with_category, proc { |category| where(:category => category.to_s.downcase) }
|
|
28
|
+
|
|
29
|
+
def to_param
|
|
30
|
+
"#{id}-#{title.parameterize}"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
%span.actions
|
|
2
|
+
= link_to 'Visit', effective_post_path(post), :target => '_blank'
|
|
3
|
+
= '-'
|
|
4
|
+
- if defined?(EffectiveRegions)
|
|
5
|
+
= link_to 'Edit Content', '/edit' + effective_posts.post_path(post), 'data-no-turbolink' => true
|
|
6
|
+
= '-'
|
|
7
|
+
= link_to 'Edit', effective_posts.edit_admin_post_path(post.id)
|
|
8
|
+
= '-'
|
|
9
|
+
= link_to 'Delete', effective_posts.admin_post_path(post.id), :data => {:method => :delete, :confirm => "Are you sure? This post will be made unavailable."}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
= simple_form_for(post, (EffectivePosts.simple_form_options || {}).merge(:url => (post.persisted? ? effective_posts.admin_post_path(post.id) : effective_posts.admin_posts_path))) do |f|
|
|
2
|
+
= f.input :title, :hint => "Give this post a title"
|
|
3
|
+
|
|
4
|
+
- if Array(EffectivePosts.categories).length > 0
|
|
5
|
+
= f.input :category, :collection => EffectivePosts.categories, :as => :select, :include_blank => false
|
|
6
|
+
- else
|
|
7
|
+
= f.input :category, :as => :hidden, :input_html => {:value => 'posts'}
|
|
8
|
+
|
|
9
|
+
%h4 Publish
|
|
10
|
+
= f.input :draft, :hint => "Save this post as a draft. It will not be accessible on the website."
|
|
11
|
+
|
|
12
|
+
- if defined?(EffectiveFormInputs)
|
|
13
|
+
= f.input :published_at, :as => :effective_date_time_picker, :hint => "Set this to a future date to schedule a post to appear in the future."
|
|
14
|
+
- else
|
|
15
|
+
= f.input :published_at, :hint => "Set this to a future date to schedule a post to appear in the future."
|
|
16
|
+
|
|
17
|
+
- if defined?(EffectiveRoles) and f.object.respond_to?(:roles)
|
|
18
|
+
= f.input :roles, :collection => EffectiveRoles.roles_collection(f.object), :as => :check_boxes, :hint => '* leave blank for a regular public post that anyone can view'
|
|
19
|
+
|
|
20
|
+
.form-group
|
|
21
|
+
.col-xs-12
|
|
22
|
+
.form-group
|
|
23
|
+
.pull-right
|
|
24
|
+
= f.button :submit, 'Save'
|
|
25
|
+
- if defined?(EffectiveRegions)
|
|
26
|
+
= f.button :submit, 'Save and Edit Content'
|
|
27
|
+
= link_to 'Cancel', effective_posts.admin_posts_path
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
%h2= @page_title
|
|
2
|
+
|
|
3
|
+
- if @datatable.nil?
|
|
4
|
+
%p Please install #{link_to 'effective_datatables', 'https://github.com/code-and-effect/effective_datatables'} to view this page
|
|
5
|
+
- elsif @datatable.collection.length == 0
|
|
6
|
+
%p There are no posts
|
|
7
|
+
- else
|
|
8
|
+
= render_datatable @datatable
|
|
9
|
+
|
|
10
|
+
%p= link_to 'New Post', effective_posts.new_admin_post_path, :class => 'btn btn-primary'
|
|
File without changes
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
- if effectively_editting?
|
|
2
|
+
%p.show-block-adjust{:style => 'border-top: 2px dashed black; text-align: center;', :title => 'anything above this line will be treated as excerpt content'}
|
|
3
|
+
%span{:style => 'background: #ddd; display: inline-block; padding: 0px 6px 4px 6px; border-radius: 0px 0px 10px 10px;'}
|
|
4
|
+
Read more...
|
|
5
|
+
- else
|
|
6
|
+
= Effective::Snippets::ReadMoreDivider::TOKEN.html_safe
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
= paginator.render do
|
|
2
|
+
%ul.pagination
|
|
3
|
+
= first_page_tag unless current_page.first?
|
|
4
|
+
= prev_page_tag unless current_page.first?
|
|
5
|
+
- each_page do |page|
|
|
6
|
+
- if page.left_outer? || page.right_outer? || page.inside_window?
|
|
7
|
+
= page_tag page
|
|
8
|
+
- elsif !page.was_truncated?
|
|
9
|
+
= gap_tag
|
|
10
|
+
= next_page_tag unless current_page.last?
|
|
11
|
+
= last_page_tag unless current_page.last?
|
data/config/routes.rb
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
EffectivePosts::Engine.routes.draw do
|
|
2
|
+
namespace :admin do
|
|
3
|
+
resources :posts, :except => [:show]
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
scope :module => 'effective' do
|
|
7
|
+
resources :posts, :only => [:index, :show]
|
|
8
|
+
|
|
9
|
+
if EffectivePosts.use_category_routes
|
|
10
|
+
EffectivePosts.categories.each do |category|
|
|
11
|
+
match "#{category}", :to => 'posts#index', :via => [:get], :defaults => {:category => category.to_s }
|
|
12
|
+
match "#{category}/:id", :to => 'posts#show', :via => [:get], :defaults => {:category => category.to_s }
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Automatically mount the engine as an append
|
|
20
|
+
Rails.application.routes.append do
|
|
21
|
+
unless Rails.application.routes.routes.find { |r| r.name == 'effective_posts' }
|
|
22
|
+
mount EffectivePosts::Engine => '/', :as => 'effective_posts'
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
class CreateEffectivePosts < ActiveRecord::Migration
|
|
2
|
+
def self.up
|
|
3
|
+
create_table <%= @posts_table_name %> do |t|
|
|
4
|
+
t.integer :user_id
|
|
5
|
+
|
|
6
|
+
t.string :title
|
|
7
|
+
t.string :category
|
|
8
|
+
|
|
9
|
+
t.boolean :draft, :default => false
|
|
10
|
+
|
|
11
|
+
t.text :tags
|
|
12
|
+
|
|
13
|
+
t.integer :roles_mask, :default => 0
|
|
14
|
+
|
|
15
|
+
t.datetime :published_at
|
|
16
|
+
|
|
17
|
+
t.datetime :updated_at
|
|
18
|
+
t.datetime :created_at
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.down
|
|
23
|
+
drop_table <%= @posts_table_name %>
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require 'kaminari'
|
|
2
|
+
require 'migrant' # Required for rspec to run properly
|
|
3
|
+
require "effective_posts/engine"
|
|
4
|
+
|
|
5
|
+
module EffectivePosts
|
|
6
|
+
mattr_accessor :posts_table_name
|
|
7
|
+
|
|
8
|
+
mattr_accessor :authorization_method
|
|
9
|
+
mattr_accessor :simple_form_options
|
|
10
|
+
mattr_accessor :layout
|
|
11
|
+
|
|
12
|
+
mattr_accessor :categories
|
|
13
|
+
mattr_accessor :use_category_routes
|
|
14
|
+
|
|
15
|
+
mattr_accessor :per_page
|
|
16
|
+
mattr_accessor :post_meta_author
|
|
17
|
+
|
|
18
|
+
def self.setup
|
|
19
|
+
yield self
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.authorized?(controller, action, resource)
|
|
23
|
+
if authorization_method.respond_to?(:call) || authorization_method.kind_of?(Symbol)
|
|
24
|
+
raise Effective::AccessDenied.new() unless (controller || self).instance_exec(controller, action, resource, &authorization_method)
|
|
25
|
+
end
|
|
26
|
+
true
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module EffectivePosts
|
|
2
|
+
class Engine < ::Rails::Engine
|
|
3
|
+
engine_name 'effective_posts'
|
|
4
|
+
|
|
5
|
+
# Include Helpers to base application
|
|
6
|
+
initializer 'effective_posts.action_controller' do |app|
|
|
7
|
+
ActiveSupport.on_load :action_controller do
|
|
8
|
+
helper EffectivePostsHelper
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Set up our default configuration options.
|
|
13
|
+
initializer "effective_posts.defaults", :before => :load_config_initializers do |app|
|
|
14
|
+
# Set up our defaults, as per our initializer template
|
|
15
|
+
eval File.read("#{config.root}/lib/generators/templates/effective_posts.rb")
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module EffectivePosts
|
|
2
|
+
module Generators
|
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
|
4
|
+
include Rails::Generators::Migration
|
|
5
|
+
|
|
6
|
+
desc "Creates an EffectivePosts initializer in your application."
|
|
7
|
+
|
|
8
|
+
source_root File.expand_path("../../templates", __FILE__)
|
|
9
|
+
|
|
10
|
+
def self.next_migration_number(dirname)
|
|
11
|
+
if not ActiveRecord::Base.timestamped_migrations
|
|
12
|
+
Time.new.utc.strftime("%Y%m%d%H%M%S")
|
|
13
|
+
else
|
|
14
|
+
"%.3d" % (current_migration_number(dirname) + 1)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def copy_initializer
|
|
19
|
+
template "effective_posts.rb", "config/initializers/effective_posts.rb"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def create_migration_file
|
|
23
|
+
@posts_table_name = ':' + EffectivePosts.posts_table_name.to_s
|
|
24
|
+
|
|
25
|
+
migration_template '../../../db/migrate/01_create_effective_posts.rb.erb', 'db/migrate/create_effective_posts.rb'
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def show_readme
|
|
29
|
+
readme "README" if behavior == :invoke
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Thanks for using EffectivePosts
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# EffectivePosts Rails Engine
|
|
2
|
+
|
|
3
|
+
EffectivePosts.setup do |config|
|
|
4
|
+
config.posts_table_name = :posts
|
|
5
|
+
|
|
6
|
+
# Every post must belong to one or more category
|
|
7
|
+
# Only add to the end of this array. Never prepend categories.
|
|
8
|
+
# Don't include :posts
|
|
9
|
+
config.categories = [:blog, :news]
|
|
10
|
+
|
|
11
|
+
# Create top level routes for each category
|
|
12
|
+
# Should each of the above categories have a top level route created for it
|
|
13
|
+
# For example:
|
|
14
|
+
# Visiting /blog will display all posts created with the :blog category
|
|
15
|
+
# Visiting /news will display all posts created with the :news category
|
|
16
|
+
#
|
|
17
|
+
# Regardless of this setting, posts will always be available via /posts?category=blog
|
|
18
|
+
config.use_category_routes = true
|
|
19
|
+
|
|
20
|
+
# Number of posts displayed per page (Kaminari)
|
|
21
|
+
config.per_page = 10
|
|
22
|
+
|
|
23
|
+
# Post Meta behaviour
|
|
24
|
+
# Should the author be displayed in the post meta?
|
|
25
|
+
# The author is the user that created the Effective::Post object
|
|
26
|
+
config.post_meta_author = true
|
|
27
|
+
|
|
28
|
+
# Use CanCan: authorize!(action, resource)
|
|
29
|
+
# Use effective_roles: resource.roles_match_with?(current_user)
|
|
30
|
+
config.authorization_method = Proc.new { |controller, action, resource| true }
|
|
31
|
+
|
|
32
|
+
# Layout Settings
|
|
33
|
+
# Configure the Layout per controller, or all at once
|
|
34
|
+
config.layout = {
|
|
35
|
+
:pages => 'application',
|
|
36
|
+
:admin => 'application'
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
# SimpleForm Options
|
|
40
|
+
# This Hash of options will be passed into any simple_form_for() calls
|
|
41
|
+
config.simple_form_options = {}
|
|
42
|
+
|
|
43
|
+
# config.simple_form_options = {
|
|
44
|
+
# :html => {:class => 'form-horizontal'},
|
|
45
|
+
# :wrapper => :horizontal_form,
|
|
46
|
+
# :wrapper_mappings => {
|
|
47
|
+
# :boolean => :horizontal_boolean,
|
|
48
|
+
# :check_boxes => :horizontal_radio_and_checkboxes,
|
|
49
|
+
# :radio_buttons => :horizontal_radio_and_checkboxes
|
|
50
|
+
# }
|
|
51
|
+
# }
|
|
52
|
+
|
|
53
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
ENV["RAILS_ENV"] ||= 'test'
|
|
2
|
+
|
|
3
|
+
require File.expand_path("../dummy/config/environment", __FILE__)
|
|
4
|
+
|
|
5
|
+
require 'rspec/rails'
|
|
6
|
+
require 'rspec/autorun'
|
|
7
|
+
require 'capybara/rspec'
|
|
8
|
+
require 'capybara/poltergeist'
|
|
9
|
+
require 'factory_girl_rails'
|
|
10
|
+
require 'haml'
|
|
11
|
+
|
|
12
|
+
# Requires supporting ruby files with custom matchers and macros, etc,
|
|
13
|
+
# in spec/support/ and its subdirectories.
|
|
14
|
+
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f }
|
|
15
|
+
|
|
16
|
+
RSpec.configure do |config|
|
|
17
|
+
config.fixture_path = "#{::Rails.root}/spec/fixtures"
|
|
18
|
+
|
|
19
|
+
config.include Capybara::DSL
|
|
20
|
+
|
|
21
|
+
Capybara.current_driver = :poltergeist
|
|
22
|
+
Capybara.javascript_driver = :poltergeist
|
|
23
|
+
Capybara.default_wait_time = 5
|
|
24
|
+
|
|
25
|
+
Rails.logger.level = 4 # Output only minimal stuff to test.log
|
|
26
|
+
|
|
27
|
+
config.use_transactional_fixtures = true # Make this false to once again use DatabaseCleaner
|
|
28
|
+
config.infer_base_class_for_anonymous_controllers = false
|
|
29
|
+
config.order = 'random'
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class ActiveRecord::Base
|
|
33
|
+
mattr_accessor :shared_connection
|
|
34
|
+
@@shared_connection = nil
|
|
35
|
+
|
|
36
|
+
def self.connection
|
|
37
|
+
@@shared_connection || retrieve_connection
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Forces all threads to share the same connection. This works on
|
|
42
|
+
# Capybara because it starts the web server in a thread.
|
|
43
|
+
ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'factory_girl'
|
|
2
|
+
|
|
3
|
+
FactoryGirl.define do
|
|
4
|
+
factory :post, :class => Effective::Post do
|
|
5
|
+
sequence(:title) { |n| "Title #{n}" }
|
|
6
|
+
sequence(:slug) { |n| "title-#{n}" }
|
|
7
|
+
|
|
8
|
+
meta_description 'meta description'
|
|
9
|
+
draft false
|
|
10
|
+
|
|
11
|
+
template 'example'
|
|
12
|
+
layout 'application'
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
metadata
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: effective_posts
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: '0.1'
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Code and Effect
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2015-01-28 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: rails
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: 3.2.0
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: 3.2.0
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: haml
|
|
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: sass-rails
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0'
|
|
48
|
+
type: :runtime
|
|
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: kaminari
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '0'
|
|
62
|
+
type: :runtime
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '0'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: migrant
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - ">="
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '0'
|
|
76
|
+
type: :runtime
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - ">="
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '0'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: simple_form
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - ">="
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '0'
|
|
90
|
+
type: :runtime
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - ">="
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '0'
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: effective_ckeditor
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - ">="
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: 1.1.0
|
|
104
|
+
type: :runtime
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - ">="
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: 1.1.0
|
|
111
|
+
- !ruby/object:Gem::Dependency
|
|
112
|
+
name: effective_regions
|
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
|
114
|
+
requirements:
|
|
115
|
+
- - ">="
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: 1.2.0
|
|
118
|
+
type: :runtime
|
|
119
|
+
prerelease: false
|
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
+
requirements:
|
|
122
|
+
- - ">="
|
|
123
|
+
- !ruby/object:Gem::Version
|
|
124
|
+
version: 1.2.0
|
|
125
|
+
description: CRUD Posts with intention to work with EffectiveRegions. WIP.
|
|
126
|
+
email:
|
|
127
|
+
- info@codeandeffect.com
|
|
128
|
+
executables: []
|
|
129
|
+
extensions: []
|
|
130
|
+
extra_rdoc_files: []
|
|
131
|
+
files:
|
|
132
|
+
- MIT-LICENSE
|
|
133
|
+
- README.md
|
|
134
|
+
- Rakefile
|
|
135
|
+
- app/assets/javascripts/effective/snippets/read_more_divider.js.coffee
|
|
136
|
+
- app/assets/javascripts/effective_posts.js
|
|
137
|
+
- app/assets/stylesheets/effective_posts.scss
|
|
138
|
+
- app/controllers/admin/posts_controller.rb
|
|
139
|
+
- app/controllers/effective/posts_controller.rb
|
|
140
|
+
- app/helpers/effective_kaminari_helper.rb
|
|
141
|
+
- app/helpers/effective_posts_helper.rb
|
|
142
|
+
- app/models/effective/access_denied.rb
|
|
143
|
+
- app/models/effective/datatables/posts.rb
|
|
144
|
+
- app/models/effective/post.rb
|
|
145
|
+
- app/models/effective/snippets/read_more_divider.rb
|
|
146
|
+
- app/views/admin/posts/_actions.html.haml
|
|
147
|
+
- app/views/admin/posts/_form.html.haml
|
|
148
|
+
- app/views/admin/posts/edit.html.haml
|
|
149
|
+
- app/views/admin/posts/index.html.haml
|
|
150
|
+
- app/views/admin/posts/new.html.haml
|
|
151
|
+
- app/views/effective/posts/_post.html.haml
|
|
152
|
+
- app/views/effective/posts/_spacer.html.haml
|
|
153
|
+
- app/views/effective/posts/index.html.haml
|
|
154
|
+
- app/views/effective/posts/show.html.haml
|
|
155
|
+
- app/views/effective/snippets/_read_more_divider.html.haml
|
|
156
|
+
- app/views/kaminari/_first_page.html.haml
|
|
157
|
+
- app/views/kaminari/_gap.html.haml
|
|
158
|
+
- app/views/kaminari/_last_page.html.haml
|
|
159
|
+
- app/views/kaminari/_next_page.html.haml
|
|
160
|
+
- app/views/kaminari/_page.html.haml
|
|
161
|
+
- app/views/kaminari/_paginator.html.haml
|
|
162
|
+
- app/views/kaminari/_prev_page.html.haml
|
|
163
|
+
- config/routes.rb
|
|
164
|
+
- db/migrate/01_create_effective_posts.rb.erb
|
|
165
|
+
- lib/effective_posts.rb
|
|
166
|
+
- lib/effective_posts/engine.rb
|
|
167
|
+
- lib/effective_posts/version.rb
|
|
168
|
+
- lib/generators/effective_posts/install_generator.rb
|
|
169
|
+
- lib/generators/templates/README
|
|
170
|
+
- lib/generators/templates/effective_posts.rb
|
|
171
|
+
- spec/effective_pages_spec.rb
|
|
172
|
+
- spec/spec_helper.rb
|
|
173
|
+
- spec/support/factories.rb
|
|
174
|
+
homepage: https://github.com/code-and-effect/effective_posts
|
|
175
|
+
licenses:
|
|
176
|
+
- MIT
|
|
177
|
+
metadata: {}
|
|
178
|
+
post_install_message:
|
|
179
|
+
rdoc_options: []
|
|
180
|
+
require_paths:
|
|
181
|
+
- lib
|
|
182
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
183
|
+
requirements:
|
|
184
|
+
- - ">="
|
|
185
|
+
- !ruby/object:Gem::Version
|
|
186
|
+
version: '0'
|
|
187
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
188
|
+
requirements:
|
|
189
|
+
- - ">="
|
|
190
|
+
- !ruby/object:Gem::Version
|
|
191
|
+
version: '0'
|
|
192
|
+
requirements: []
|
|
193
|
+
rubyforge_project:
|
|
194
|
+
rubygems_version: 2.4.3
|
|
195
|
+
signing_key:
|
|
196
|
+
specification_version: 4
|
|
197
|
+
summary: CRUD Posts with intention to work with EffectiveRegions. WIP.
|
|
198
|
+
test_files:
|
|
199
|
+
- spec/effective_pages_spec.rb
|
|
200
|
+
- spec/spec_helper.rb
|
|
201
|
+
- spec/support/factories.rb
|