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.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +7 -0
  4. data/Rakefile +24 -0
  5. data/app/assets/javascripts/effective/snippets/read_more_divider.js.coffee +22 -0
  6. data/app/assets/javascripts/effective_posts.js +0 -0
  7. data/app/assets/stylesheets/effective_posts.scss +0 -0
  8. data/app/controllers/admin/posts_controller.rb +91 -0
  9. data/app/controllers/effective/posts_controller.rb +51 -0
  10. data/app/helpers/effective_kaminari_helper.rb +16 -0
  11. data/app/helpers/effective_posts_helper.rb +42 -0
  12. data/app/models/effective/access_denied.rb +17 -0
  13. data/app/models/effective/datatables/posts.rb +21 -0
  14. data/app/models/effective/post.rb +39 -0
  15. data/app/models/effective/snippets/read_more_divider.rb +9 -0
  16. data/app/views/admin/posts/_actions.html.haml +9 -0
  17. data/app/views/admin/posts/_form.html.haml +27 -0
  18. data/app/views/admin/posts/edit.html.haml +2 -0
  19. data/app/views/admin/posts/index.html.haml +10 -0
  20. data/app/views/admin/posts/new.html.haml +2 -0
  21. data/app/views/effective/posts/_post.html.haml +9 -0
  22. data/app/views/effective/posts/_spacer.html.haml +0 -0
  23. data/app/views/effective/posts/index.html.haml +4 -0
  24. data/app/views/effective/posts/show.html.haml +12 -0
  25. data/app/views/effective/snippets/_read_more_divider.html.haml +9 -0
  26. data/app/views/kaminari/_first_page.html.haml +2 -0
  27. data/app/views/kaminari/_gap.html.haml +2 -0
  28. data/app/views/kaminari/_last_page.html.haml +2 -0
  29. data/app/views/kaminari/_next_page.html.haml +2 -0
  30. data/app/views/kaminari/_page.html.haml +6 -0
  31. data/app/views/kaminari/_paginator.html.haml +11 -0
  32. data/app/views/kaminari/_prev_page.html.haml +2 -0
  33. data/config/routes.rb +24 -0
  34. data/db/migrate/01_create_effective_posts.rb.erb +26 -0
  35. data/lib/effective_posts.rb +28 -0
  36. data/lib/effective_posts/engine.rb +18 -0
  37. data/lib/effective_posts/version.rb +3 -0
  38. data/lib/generators/effective_posts/install_generator.rb +33 -0
  39. data/lib/generators/templates/README +1 -0
  40. data/lib/generators/templates/effective_posts.rb +53 -0
  41. data/spec/effective_pages_spec.rb +7 -0
  42. data/spec/spec_helper.rb +43 -0
  43. data/spec/support/factories.rb +15 -0
  44. 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
@@ -0,0 +1,7 @@
1
+ # Effective Posts
2
+
3
+ WIP Gem
4
+
5
+ ## TODO
6
+
7
+ Write a README
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
+ module Effective
2
+ module Snippets
3
+ class ReadMoreDivider < Snippet
4
+ TOKEN = "<div style='display: none;'>READ_MORE_DIVIDER</div>"
5
+
6
+ attribute :throwaway, String
7
+ end
8
+ end
9
+ end
@@ -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,2 @@
1
+ %h2= @page_title
2
+ = render :partial => 'form', :as => :post, :object => @post
@@ -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'
@@ -0,0 +1,2 @@
1
+ %h2= @page_title
2
+ = render :partial => 'form', :as => :post, :object => @post
@@ -0,0 +1,9 @@
1
+ .effective-post
2
+ %h2.post-title
3
+ %a{:href => effective_post_path(post)}
4
+ = simple_effective_region post, :title do
5
+ = post.title
6
+
7
+ %p.post-meta= post_meta(post)
8
+
9
+ .post-content.post-excerpt= post_excerpt(post)
File without changes
@@ -0,0 +1,4 @@
1
+ .effective-posts
2
+ = render :partial => @posts, :spacer_template => 'spacer'
3
+
4
+ %nav= paginate @posts
@@ -0,0 +1,12 @@
1
+ .effective-post
2
+ %h2.post-title
3
+ %a{:href => effective_post_path(@post)}
4
+ = simple_effective_region @post, :title do
5
+ = @post.title
6
+
7
+ %p.post-meta= post_meta(@post)
8
+
9
+ .post-content
10
+ = effective_region @post, :content do
11
+ %p Default content
12
+
@@ -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,2 @@
1
+ %li
2
+ = link_to_unless current_page.first?, raw(t 'views.pagination.first'), url, :remote => remote
@@ -0,0 +1,2 @@
1
+ %li.disabled
2
+ = content_tag :a, raw(t 'views.pagination.truncate')
@@ -0,0 +1,2 @@
1
+ %li
2
+ = link_to_unless current_page.last?, raw(t 'views.pagination.last'), url, {:remote => remote}
@@ -0,0 +1,2 @@
1
+ %li
2
+ = link_to_unless current_page.last?, raw(t 'views.pagination.next'), url, :rel => 'next', :remote => remote
@@ -0,0 +1,6 @@
1
+ - if page.current?
2
+ %li.active
3
+ = content_tag :a, page, remote: remote, rel: (page.next? ? 'next' : (page.prev? ? 'prev' : nil))
4
+ - else
5
+ %li
6
+ = link_to page, url, remote: remote, rel: (page.next? ? 'next' : (page.prev? ? 'prev' : nil))
@@ -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?
@@ -0,0 +1,2 @@
1
+ %li
2
+ = link_to_unless current_page.first?, raw(t 'views.pagination.previous'), url, :rel => 'prev', :remote => remote
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,3 @@
1
+ module EffectivePosts
2
+ VERSION = "0.1"
3
+ 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
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe EffectivePosts do
4
+ it 'should be a module' do
5
+ assert_kind_of Module, EffectivePosts
6
+ end
7
+ end
@@ -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