exposition 0.0.3.pre.alpha

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 (165) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/Rakefile +25 -0
  4. data/app/assets/images/exposition/twitter.svg +10 -0
  5. data/app/assets/javascripts/exposition/admin/application.js +3 -0
  6. data/app/assets/stylesheets/exposition/_breakpoints.scss +5 -0
  7. data/app/assets/stylesheets/exposition/_code.scss +83 -0
  8. data/app/assets/stylesheets/exposition/_footer.scss +9 -0
  9. data/app/assets/stylesheets/exposition/_header.scss +62 -0
  10. data/app/assets/stylesheets/exposition/_layout.scss +28 -0
  11. data/app/assets/stylesheets/exposition/_mixins.scss +4 -0
  12. data/app/assets/stylesheets/exposition/_normalize.scss +427 -0
  13. data/app/assets/stylesheets/exposition/_pagination.scss +18 -0
  14. data/app/assets/stylesheets/exposition/_posts.scss +96 -0
  15. data/app/assets/stylesheets/exposition/_tags.scss +12 -0
  16. data/app/assets/stylesheets/exposition/_variables.scss +16 -0
  17. data/app/assets/stylesheets/exposition/admin/_layout.scss +58 -0
  18. data/app/assets/stylesheets/exposition/admin/_mixins.scss +3 -0
  19. data/app/assets/stylesheets/exposition/admin/_notifications.scss +46 -0
  20. data/app/assets/stylesheets/exposition/admin/_pagination.scss +12 -0
  21. data/app/assets/stylesheets/exposition/admin/_posts.scss +7 -0
  22. data/app/assets/stylesheets/exposition/admin/application.scss +9 -0
  23. data/app/assets/stylesheets/exposition/admin/base/_base.scss +15 -0
  24. data/app/assets/stylesheets/exposition/admin/base/_buttons.scss +31 -0
  25. data/app/assets/stylesheets/exposition/admin/base/_forms.scss +78 -0
  26. data/app/assets/stylesheets/exposition/admin/base/_grid-settings.scss +14 -0
  27. data/app/assets/stylesheets/exposition/admin/base/_lists.scss +31 -0
  28. data/app/assets/stylesheets/exposition/admin/base/_tables.scss +25 -0
  29. data/app/assets/stylesheets/exposition/admin/base/_typography.scss +55 -0
  30. data/app/assets/stylesheets/exposition/admin/base/_variables.scss +35 -0
  31. data/app/assets/stylesheets/exposition/admin/normalize.scss +427 -0
  32. data/app/assets/stylesheets/exposition/application.scss +17 -0
  33. data/app/controllers/exposition/admin/admin_controller.rb +5 -0
  34. data/app/controllers/exposition/admin/posts_controller.rb +5 -0
  35. data/app/controllers/exposition/admin/sessions_controller.rb +31 -0
  36. data/app/controllers/exposition/admin/tags_controller.rb +5 -0
  37. data/app/controllers/exposition/application_controller.rb +8 -0
  38. data/app/controllers/exposition/posts_controller.rb +5 -0
  39. data/app/controllers/exposition/tags_controller.rb +5 -0
  40. data/app/helpers/exposition/admin/flashes_helper.rb +7 -0
  41. data/app/helpers/exposition/admin/sessions_helper.rb +20 -0
  42. data/app/helpers/exposition/markdown_helper.rb +21 -0
  43. data/app/models/categorical/tag.rb +6 -0
  44. data/app/models/exposition/encryptor.rb +10 -0
  45. data/app/models/exposition/post.rb +5 -0
  46. data/app/models/exposition/user.rb +5 -0
  47. data/app/views/exposition/admin/images/index.html.haml +12 -0
  48. data/app/views/exposition/admin/images/new.html.haml +0 -0
  49. data/app/views/exposition/admin/posts/_error_handler.html.haml +8 -0
  50. data/app/views/exposition/admin/posts/_form_fields.html.haml +23 -0
  51. data/app/views/exposition/admin/posts/edit.html.haml +5 -0
  52. data/app/views/exposition/admin/posts/index.html.haml +23 -0
  53. data/app/views/exposition/admin/posts/new.html.haml +7 -0
  54. data/app/views/exposition/admin/posts/update.html.haml +2 -0
  55. data/app/views/exposition/admin/sessions/new.html.haml +10 -0
  56. data/app/views/exposition/admin/tags/_error_handler.html.haml +8 -0
  57. data/app/views/exposition/admin/tags/edit.html.haml +10 -0
  58. data/app/views/exposition/admin/tags/index.html.haml +18 -0
  59. data/app/views/exposition/admin/tags/new.html.haml +10 -0
  60. data/app/views/exposition/posts/_post.html.haml +8 -0
  61. data/app/views/exposition/posts/_tags.html.haml +6 -0
  62. data/app/views/exposition/posts/index.html.haml +8 -0
  63. data/app/views/exposition/posts/show.html.haml +5 -0
  64. data/app/views/exposition/tags/show.html.haml +6 -0
  65. data/app/views/layouts/exposition/admin.html.haml +22 -0
  66. data/app/views/layouts/exposition/application.html.haml +20 -0
  67. data/config/locales/en.yml +37 -0
  68. data/config/routes.rb +14 -0
  69. data/db/migrate/20160106220615_create_exposition_posters.rb +12 -0
  70. data/db/migrate/20160112194424_add_author_id_to_posts.rb +5 -0
  71. data/db/migrate/20160112200248_create_exposition_users.rb +14 -0
  72. data/db/migrate/20160112202302_add_slug_to_expositon_posts.rb +7 -0
  73. data/db/migrate/20160112204019_add_categorial_tags.rb +17 -0
  74. data/db/migrate/20160225203524_add_summary_to_posts.rb +5 -0
  75. data/db/migrate/20160226035733_convert_published_at_to_datetime.rb +9 -0
  76. data/lib/exposition.rb +19 -0
  77. data/lib/exposition/concerns/controllers/admin/admin_controller.rb +39 -0
  78. data/lib/exposition/concerns/controllers/admin/posts_controller.rb +70 -0
  79. data/lib/exposition/concerns/controllers/admin/tags_controller.rb +63 -0
  80. data/lib/exposition/concerns/controllers/posts_controller.rb +19 -0
  81. data/lib/exposition/concerns/controllers/tags_controller.rb +31 -0
  82. data/lib/exposition/concerns/models/post.rb +52 -0
  83. data/lib/exposition/concerns/models/user.rb +43 -0
  84. data/lib/exposition/engine.rb +14 -0
  85. data/lib/exposition/setup.rb +15 -0
  86. data/lib/exposition/version.rb +3 -0
  87. data/lib/tasks/exposition_tasks.rake +4 -0
  88. data/lib/tasks/setup.rb +17 -0
  89. data/spec/controllers/exposition/admin/admin_controller_spec.rb +88 -0
  90. data/spec/controllers/exposition/admin/posts_controller_spec.rb +153 -0
  91. data/spec/controllers/exposition/admin/sessions_controller_spec.rb +46 -0
  92. data/spec/controllers/exposition/admin/tags_controller_spec.rb +106 -0
  93. data/spec/controllers/exposition/posts_controller_spec.rb +43 -0
  94. data/spec/controllers/exposition/tags_controller_spec.rb +40 -0
  95. data/spec/dummy/Gemfile +5 -0
  96. data/spec/dummy/Gemfile.lock +173 -0
  97. data/spec/dummy/README.rdoc +28 -0
  98. data/spec/dummy/Rakefile +6 -0
  99. data/spec/dummy/Thorfile +1 -0
  100. data/spec/dummy/app/assets/javascripts/application.js +1 -0
  101. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  102. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  103. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  104. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  105. data/spec/dummy/bin/bundle +3 -0
  106. data/spec/dummy/bin/rails +9 -0
  107. data/spec/dummy/bin/rake +9 -0
  108. data/spec/dummy/bin/setup +29 -0
  109. data/spec/dummy/bin/spring +15 -0
  110. data/spec/dummy/bin/thor +16 -0
  111. data/spec/dummy/config.ru +4 -0
  112. data/spec/dummy/config/application.rb +26 -0
  113. data/spec/dummy/config/boot.rb +3 -0
  114. data/spec/dummy/config/database.yml +12 -0
  115. data/spec/dummy/config/environment.rb +5 -0
  116. data/spec/dummy/config/environments/development.rb +41 -0
  117. data/spec/dummy/config/environments/production.rb +79 -0
  118. data/spec/dummy/config/environments/test.rb +42 -0
  119. data/spec/dummy/config/initializers/assets.rb +11 -0
  120. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  121. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  122. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  123. data/spec/dummy/config/initializers/inflections.rb +16 -0
  124. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  125. data/spec/dummy/config/initializers/session_store.rb +3 -0
  126. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  127. data/spec/dummy/config/locales/en.yml +23 -0
  128. data/spec/dummy/config/routes.rb +3 -0
  129. data/spec/dummy/config/secrets.yml +22 -0
  130. data/spec/dummy/db/schema.rb +62 -0
  131. data/spec/dummy/db/seeds.rb +22 -0
  132. data/spec/dummy/public/404.html +67 -0
  133. data/spec/dummy/public/422.html +67 -0
  134. data/spec/dummy/public/500.html +66 -0
  135. data/spec/dummy/public/favicon.ico +0 -0
  136. data/spec/dummy/public/robots.txt +5 -0
  137. data/spec/factories/categorical/tags.rb +5 -0
  138. data/spec/factories/posts.rb +8 -0
  139. data/spec/factories/taggings.rb +7 -0
  140. data/spec/factories/users.rb +7 -0
  141. data/spec/features/admin/post_management_spec.rb +95 -0
  142. data/spec/features/admin/session_management_spec.rb +40 -0
  143. data/spec/features/admin/tags_management_spec.rb +59 -0
  144. data/spec/features/posts_index_spec.rb +28 -0
  145. data/spec/features/viewing_a_post_spec.rb +21 -0
  146. data/spec/features/viewing_posts_by_tag_spec.rb +17 -0
  147. data/spec/helpers/admin/flashes_helper_spec.rb +29 -0
  148. data/spec/helpers/admin/sessions_helper_spec.rb +56 -0
  149. data/spec/helpers/markdown_helper_spec.rb +10 -0
  150. data/spec/models/categorical/tag_spec.rb +35 -0
  151. data/spec/models/exposition/post_spec.rb +123 -0
  152. data/spec/models/exposition/user_spec.rb +15 -0
  153. data/spec/rails_helper.rb +47 -0
  154. data/spec/spec_helper.rb +11 -0
  155. data/spec/support/controllers.rb +6 -0
  156. data/spec/support/controllers/pagination.rb +17 -0
  157. data/spec/support/controllers/session_management.rb +20 -0
  158. data/spec/support/features.rb +6 -0
  159. data/spec/support/features/pagination.rb +22 -0
  160. data/spec/support/features/session_management.rb +17 -0
  161. data/spec/support/models.rb +5 -0
  162. data/spec/support/models/sluggable.rb +11 -0
  163. data/spec/tasks/setup_spec.rb +32 -0
  164. data/spec/views/admin/posts/index.html.haml_spec.rb +16 -0
  165. metadata +619 -0
data/config/routes.rb ADDED
@@ -0,0 +1,14 @@
1
+ Exposition::Engine.routes.draw do
2
+ namespace :admin do
3
+ resources :posts
4
+ resources :tags
5
+ get 'login' => 'sessions#new'
6
+ post 'login' => 'sessions#create'
7
+ delete 'logout' => 'sessions#destroy'
8
+ end
9
+
10
+ resources :posts, only: [:show]
11
+ resources :tags, only: [:show]
12
+
13
+ root to: 'posts#index'
14
+ end
@@ -0,0 +1,12 @@
1
+ class CreateExpositionPosters < ActiveRecord::Migration
2
+ def change
3
+ create_table :exposition_posts do |t|
4
+ t.string :title
5
+ t.text :body
6
+ t.boolean :published, null: false, default: false
7
+ t.date :published_at
8
+
9
+ t.timestamps null: false
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,5 @@
1
+ class AddAuthorIdToPosts < ActiveRecord::Migration
2
+ def change
3
+ add_column :exposition_posts, :author_id, :integer
4
+ end
5
+ end
@@ -0,0 +1,14 @@
1
+ class CreateExpositionUsers < ActiveRecord::Migration
2
+ def change
3
+ create_table :exposition_users do |t|
4
+ t.string :name
5
+ t.string :email
6
+ t.string :password_digest
7
+ t.string :remember_digest
8
+
9
+ t.timestamps null: false
10
+
11
+ t.index :email, unique: true
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,7 @@
1
+ class AddSlugToExpositonPosts < ActiveRecord::Migration
2
+ def change
3
+ add_column :exposition_posts, :slug, :string
4
+
5
+ add_index :exposition_posts, :slug, unique: true
6
+ end
7
+ end
@@ -0,0 +1,17 @@
1
+ class AddCategorialTags < ActiveRecord::Migration
2
+ def change
3
+ create_table :categorical_tags do |t|
4
+ t.string :label
5
+ t.string :slug
6
+
7
+ t.timestamps null: false
8
+
9
+ t.index :label, unique: true
10
+ t.index :slug, unique: true
11
+ end
12
+ create_table :categorical_taggings do |t|
13
+ t.references :taggable, polymorphic: true, index: true
14
+ t.integer :tag_id
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,5 @@
1
+ class AddSummaryToPosts < ActiveRecord::Migration
2
+ def change
3
+ add_column :exposition_posts, :summary, :text
4
+ end
5
+ end
@@ -0,0 +1,9 @@
1
+ class ConvertPublishedAtToDatetime < ActiveRecord::Migration
2
+ def up
3
+ change_column :exposition_posts, :published_at, :datetime
4
+ end
5
+
6
+ def down
7
+ change_column :exposition_posts, :published_at, :date
8
+ end
9
+ end
data/lib/exposition.rb ADDED
@@ -0,0 +1,19 @@
1
+ require "human_urls"
2
+ require "categorical"
3
+ require "kaminari"
4
+ require "haml"
5
+ require "bourbon"
6
+ require "neat"
7
+ require 'jquery-rails'
8
+ require "exposition/engine"
9
+ require "exposition/setup"
10
+ require "exposition/concerns/models/post"
11
+ require "exposition/concerns/models/user"
12
+ require "exposition/concerns/controllers/posts_controller"
13
+ require "exposition/concerns/controllers/tags_controller"
14
+ require "exposition/concerns/controllers/admin/posts_controller"
15
+ require "exposition/concerns/controllers/admin/admin_controller"
16
+ require "exposition/concerns/controllers/admin/tags_controller"
17
+
18
+ module Exposition
19
+ end
@@ -0,0 +1,39 @@
1
+ module Exposition
2
+ module Concerns
3
+ module Controller
4
+ module Admin
5
+ module AdminController
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ layout 'exposition/admin'
10
+
11
+ before_action :authorize
12
+ helper_method :current_user, :logged_in?
13
+ end
14
+
15
+ def authorize
16
+ raise ActionController::RoutingError.new('Not Found') unless logged_in?
17
+ end
18
+
19
+ def current_user
20
+ if (user_id = session[:user_id])
21
+ @current_user ||= User.find_by(id: user_id)
22
+ elsif (user_id = cookies.signed[:user_id])
23
+ user = User.find_by(id: user_id)
24
+ if user && user.authenticated?(cookies[:remember_token])
25
+ session[:user_id] = user.id
26
+ @current_user = user
27
+ end
28
+ end
29
+ end
30
+
31
+ def logged_in?
32
+ current_user.present?
33
+ end
34
+
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,70 @@
1
+ module Exposition
2
+ module Concerns
3
+ module Controller
4
+ module Admin
5
+ module PostsController
6
+ extend ActiveSupport::Concern
7
+ def index
8
+ @posts = Post.sorted_by_published_date.
9
+ page(params[:page]).
10
+ per(25)
11
+ end
12
+
13
+ def new
14
+ @post = Post.new
15
+ find_authors
16
+ find_tags
17
+ end
18
+
19
+ def create
20
+ @post = Post.new(post_params)
21
+ find_authors
22
+ find_tags
23
+ if @post.save
24
+ flash[:success] = "Post successfully created."
25
+ redirect_to admin_posts_path
26
+ else
27
+ render :new
28
+ end
29
+ end
30
+
31
+ def edit
32
+ find_post
33
+ find_authors
34
+ find_tags
35
+ end
36
+
37
+ def update
38
+ find_post
39
+ find_authors
40
+ find_tags
41
+ if @post.update(post_params)
42
+ flash[:success] = "Post was successfully updated."
43
+ redirect_to admin_posts_path
44
+ else
45
+ render action: 'edit'
46
+ end
47
+ end
48
+
49
+ private
50
+
51
+ def find_authors
52
+ @authors = User.all
53
+ end
54
+
55
+ def find_post
56
+ @post = Post.find_by_slug!(params[:id])
57
+ end
58
+
59
+ def find_tags
60
+ @tags = Categorical::Tag.all
61
+ end
62
+
63
+ def post_params
64
+ params.require(:post).permit(:id, :title, :body, :summary, :slug, :published, :author_id, tag_ids: [])
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,63 @@
1
+ module Exposition
2
+ module Concerns
3
+ module Controller
4
+ module Admin
5
+ module TagsController
6
+ extend ActiveSupport::Concern
7
+
8
+ def index
9
+ @tags = Categorical::Tag.page(params[:page]).per(25)
10
+ end
11
+
12
+ def new
13
+ @tag = Categorical::Tag.new
14
+ end
15
+
16
+ def create
17
+ @tag = Categorical::Tag.new(tag_params)
18
+ if @tag.save
19
+ flash[:success] = "Tag successfully created."
20
+ redirect_to admin_tags_path
21
+ else
22
+ render :new
23
+ end
24
+ end
25
+
26
+ def edit
27
+ find_tag
28
+ end
29
+
30
+ def update
31
+ find_tag
32
+ if @tag.update(tag_params)
33
+ flash[:success] = "Tag was successfully updated."
34
+ redirect_to admin_tags_path
35
+ else
36
+ render action: 'edit'
37
+ end
38
+ end
39
+
40
+ def destroy
41
+ find_tag
42
+ if @tag.destroy
43
+ redirect_to admin_tags_path,
44
+ notice: 'Tag was successfully destroyed.'
45
+ else
46
+ redirect_to admin_tags_path
47
+ end
48
+ end
49
+
50
+ private
51
+
52
+ def find_tag
53
+ @tag = Categorical::Tag.find_by_slug!(params[:id])
54
+ end
55
+
56
+ def tag_params
57
+ params.require(:tag).permit(:id, :label)
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,19 @@
1
+ module Exposition
2
+ module Concerns
3
+ module Controller
4
+ module PostsController
5
+ extend ActiveSupport::Concern
6
+
7
+ def index
8
+ @posts = Post.published.sorted_by_published_date.
9
+ page(params[:page]).
10
+ per(10)
11
+ end
12
+
13
+ def show
14
+ @post = Post.published.find_by_slug!(params[:id])
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,31 @@
1
+ module Exposition
2
+ module Concerns
3
+ module Controller
4
+ module TagsController
5
+ extend ActiveSupport::Concern
6
+
7
+ def show
8
+ @tag = Categorical::Tag.find_by_slug!(params[:id])
9
+ @taggables = @tag.
10
+ send(fetch_taggable_type).
11
+ published.
12
+ sorted_by_published_date.
13
+ page(params[:page]).
14
+ per(10)
15
+ end
16
+
17
+ private
18
+
19
+ def fetch_taggable_type
20
+ if params[:type]
21
+ taggable_type = params[:type]
22
+ return taggable_type.underscore.to_sym
23
+ else
24
+ return "Exposition::Post"
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+
@@ -0,0 +1,52 @@
1
+ module Exposition
2
+ module Concerns
3
+ module Models
4
+ module Post
5
+ extend ActiveSupport::Concern
6
+ include HumanUrls::Sluggable
7
+ include Categorical::Taggable
8
+
9
+ included do
10
+ belongs_to :author, class_name: 'User'
11
+
12
+ validates_presence_of :title, :body, :author
13
+ validates_length_of :title, maximum: 244
14
+
15
+ before_save :set_published_at_date
16
+
17
+ sluggify :slug, generated_from: :title
18
+ end
19
+
20
+ class_methods do
21
+ def published
22
+ where(published: true)
23
+ end
24
+
25
+ def sorted_by_published_date
26
+ order(published_at: :desc)
27
+ end
28
+ end
29
+
30
+ def css_classes
31
+ if published?
32
+ return "published"
33
+ else
34
+ return "not-published"
35
+ end
36
+ end
37
+
38
+ def summary
39
+ read_attribute(:summary) || body
40
+ end
41
+
42
+ private
43
+
44
+ def set_published_at_date
45
+ if published_changed?(from: false, to: true)
46
+ self.published_at = Date.today
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,43 @@
1
+ module Exposition
2
+ module Concerns
3
+ module Models
4
+ module User
5
+ extend ActiveSupport::Concern
6
+ VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
7
+
8
+ included do
9
+ attr_accessor :remember_token
10
+
11
+ validates_presence_of :name, :email
12
+ validates_length_of :name, maximum: 50
13
+ validates_length_of :email, maximum: 244
14
+ validates_length_of :password, minimum: 6
15
+ validates_uniqueness_of :email, case_sensitive: false
16
+ validates_format_of :email, with: VALID_EMAIL_REGEX
17
+
18
+ has_secure_password
19
+ end
20
+
21
+ class_methods do
22
+ end
23
+
24
+ # Returns true if the given token matches the digest.
25
+ def authenticated?(remember_token)
26
+ BCrypt::Password.new(remember_digest).is_password?(remember_token)
27
+ end
28
+
29
+ # Remembers a user in the database for use in persistent sessions.
30
+ def set_encrypted_remember_token!
31
+ self.remember_token = generate_new_token
32
+ update_attribute(:remember_digest, Encryptor.encrypt(remember_token))
33
+ end
34
+
35
+ private
36
+
37
+ def generate_new_token
38
+ SecureRandom.urlsafe_base64
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end