younker-blog 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. data/.gitignore +5 -0
  2. data/Gemfile +1 -0
  3. data/Gemfile.lock +10 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.rdoc +27 -0
  6. data/Rakefile +39 -0
  7. data/app/assets/stylesheets/scaffold.css +56 -0
  8. data/app/controllers/blog/application_controller.rb +29 -0
  9. data/app/controllers/blog/blogs_controller.rb +115 -0
  10. data/app/controllers/blog/contexts_controller.rb +78 -0
  11. data/app/controllers/blog/sluggables_controller.rb +15 -0
  12. data/app/helpers/blog/application_helper.rb +4 -0
  13. data/app/helpers/blog/blogs_helper.rb +26 -0
  14. data/app/helpers/blog/contexts_helper.rb +4 -0
  15. data/app/helpers/blog/sluggables_helper.rb +4 -0
  16. data/app/models/blog/blog.rb +29 -0
  17. data/app/models/blog/context.rb +41 -0
  18. data/app/models/blog/photo.rb +15 -0
  19. data/app/views/blog/blogs/_archive.haml +1 -0
  20. data/app/views/blog/blogs/_blog.haml +13 -0
  21. data/app/views/blog/blogs/_form.haml +7 -0
  22. data/app/views/blog/blogs/_form_elements.haml +58 -0
  23. data/app/views/blog/blogs/edit.haml +3 -0
  24. data/app/views/blog/blogs/index.haml +31 -0
  25. data/app/views/blog/blogs/new.haml +3 -0
  26. data/app/views/blog/blogs/show.haml +29 -0
  27. data/app/views/blog/contexts/_form.html.haml +24 -0
  28. data/app/views/blog/contexts/create.html.haml +8 -0
  29. data/app/views/blog/contexts/edit.html.haml +7 -0
  30. data/app/views/blog/contexts/index.html.haml +30 -0
  31. data/app/views/blog/contexts/new.html.haml +6 -0
  32. data/app/views/blog/contexts/show.html.haml +39 -0
  33. data/app/views/layouts/blog/application.html.erb +14 -0
  34. data/app/views/shared/_user_notice.haml +6 -0
  35. data/blog.gemspec +43 -0
  36. data/config/blog.yml +9 -0
  37. data/config/initializers/blog_pagination_list_link_renderer.rb +21 -0
  38. data/config/initializers/blog_setup.rb +2 -0
  39. data/config/initializers/date_format.rb +1 -0
  40. data/config/routes.rb +11 -0
  41. data/db/migrate/20110627224424_create_blog_blogs.rb +32 -0
  42. data/db/seeds.rb +8 -0
  43. data/lib/blog.rb +4 -0
  44. data/lib/blog/engine.rb +5 -0
  45. data/lib/blog/version.rb +3 -0
  46. data/lib/tasks/blog_tasks.rake +4 -0
  47. data/script/rails +6 -0
  48. data/test/blog_test.rb +7 -0
  49. data/test/dummy/Rakefile +7 -0
  50. data/test/dummy/app/assets/images/blog/1/large/july4th-smaller.jpg +0 -0
  51. data/test/dummy/app/assets/images/blog/1/medium/july4th-smaller.jpg +0 -0
  52. data/test/dummy/app/assets/images/blog/1/original/july4th-smaller.jpg +0 -0
  53. data/test/dummy/app/assets/images/blog/1/small/july4th-smaller.jpg +0 -0
  54. data/test/dummy/app/assets/javascripts/application.js +10 -0
  55. data/test/dummy/app/assets/shared/blog/1/large/july4th-smaller.jpg +0 -0
  56. data/test/dummy/app/assets/shared/blog/1/medium/july4th-smaller.jpg +0 -0
  57. data/test/dummy/app/assets/shared/blog/1/original/july4th-smaller.jpg +0 -0
  58. data/test/dummy/app/assets/shared/blog/1/small/july4th-smaller.jpg +0 -0
  59. data/test/dummy/app/assets/stylesheets/application.css +7 -0
  60. data/test/dummy/app/controllers/application_controller.rb +4 -0
  61. data/test/dummy/app/helpers/application_helper.rb +2 -0
  62. data/test/dummy/app/mailers/.gitkeep +0 -0
  63. data/test/dummy/app/models/.gitkeep +0 -0
  64. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  65. data/test/dummy/config.ru +4 -0
  66. data/test/dummy/config/application.rb +42 -0
  67. data/test/dummy/config/boot.rb +10 -0
  68. data/test/dummy/config/database.yml +39 -0
  69. data/test/dummy/config/environment.rb +5 -0
  70. data/test/dummy/config/environments/development.rb +27 -0
  71. data/test/dummy/config/environments/production.rb +51 -0
  72. data/test/dummy/config/environments/test.rb +39 -0
  73. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  74. data/test/dummy/config/initializers/inflections.rb +10 -0
  75. data/test/dummy/config/initializers/mime_types.rb +5 -0
  76. data/test/dummy/config/initializers/secret_token.rb +7 -0
  77. data/test/dummy/config/initializers/session_store.rb +8 -0
  78. data/test/dummy/config/initializers/wrap_parameters.rb +12 -0
  79. data/test/dummy/config/locales/en.yml +5 -0
  80. data/test/dummy/config/routes.rb +26 -0
  81. data/test/dummy/db/development.sqlite3 +0 -0
  82. data/test/dummy/db/schema.rb +44 -0
  83. data/test/dummy/lib/assets/.gitkeep +0 -0
  84. data/test/dummy/log/.gitkeep +0 -0
  85. data/test/dummy/log/development.log +9412 -0
  86. data/test/dummy/public/404.html +26 -0
  87. data/test/dummy/public/422.html +26 -0
  88. data/test/dummy/public/500.html +26 -0
  89. data/test/dummy/public/favicon.ico +0 -0
  90. data/test/dummy/script/rails +6 -0
  91. data/test/fixtures/blog/blogs.yml +11 -0
  92. data/test/functional/blog/blogs_controller_test.rb +9 -0
  93. data/test/functional/blog/contexts_controller_test.rb +36 -0
  94. data/test/functional/blog/sluggables_controller_test.rb +9 -0
  95. data/test/integration/navigation_test.rb +10 -0
  96. data/test/test_helper.rb +10 -0
  97. data/test/unit/blog/blog_test.rb +9 -0
  98. data/test/unit/helpers/blog/blogs_helper_test.rb +6 -0
  99. data/test/unit/helpers/blog/contexts_helper_test.rb +6 -0
  100. data/test/unit/helpers/blog/sluggables_helper_test.rb +6 -0
  101. data/vendor/assets/javascripts/blog/application.js +3 -0
  102. data/vendor/assets/javascripts/blog/blogs.js +2 -0
  103. data/vendor/assets/javascripts/blog/contexts.js +2 -0
  104. data/vendor/assets/javascripts/blog/helpers.js +5 -0
  105. data/vendor/assets/javascripts/blog/sluggables.js +28 -0
  106. data/vendor/assets/stylesheets/blog/_form.scss +26 -0
  107. data/vendor/assets/stylesheets/blog/application.css +7 -0
  108. data/vendor/assets/stylesheets/blog/blog.css +15 -0
  109. data/vendor/assets/stylesheets/blog/contexts.css +4 -0
  110. data/vendor/assets/stylesheets/blog/scss/blogs.css +60 -0
  111. data/vendor/assets/stylesheets/blog/scss/blogs.scss +100 -0
  112. data/vendor/assets/stylesheets/blog/sluggables.css +4 -0
  113. metadata +344 -0
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ .bundle
2
+ db/*.sqlite3
3
+ log/*.log
4
+ tmp/
5
+ .sass-cache
data/Gemfile ADDED
@@ -0,0 +1 @@
1
+ source "http://rubygems.org"
data/Gemfile.lock ADDED
@@ -0,0 +1,10 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ younker-string-extensions (0.0.2)
5
+
6
+ PLATFORMS
7
+ ruby
8
+
9
+ DEPENDENCIES
10
+ younker-string-extensions (~> 0.0.2)
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2011 YOURNAME
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.rdoc ADDED
@@ -0,0 +1,27 @@
1
+ # http://rdoc.sourceforge.net/doc/
2
+ = Blog
3
+
4
+ This is an engine meant to be mounted inside a client app giving it a blogging type application.
5
+
6
+ = Blog Contexts
7
+
8
+ I found that many of my sites had a /blog, /news and other such sections. The functionality was identical but the
9
+ context was different. Thus, each of these "blogs" has a context and routes that go with them to allow this sort of
10
+ differentiation.
11
+
12
+ = Required method (client app)
13
+
14
+ * current_user() that responds to id -- needed for blog creation/edits so we do not pass user_id in params (small security thing)
15
+ * blog_user_can?(:action, :object) -- based off of cancan model
16
+
17
+
18
+ = Instructions for Use
19
+
20
+ * Run migrations: do this using rake app:blog:install:migrations
21
+ * instal paperclip & inherited_resources gems
22
+ * may have to prepend 'main_app' to route helpers in main application. ie. sign_up_path => main_app.sign_up_path
23
+ * New context:
24
+
25
+ = Development
26
+
27
+ * sass --watch app/assets/stylesheets/blog/
data/Rakefile ADDED
@@ -0,0 +1,39 @@
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
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'Blog'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+ APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
24
+ load 'rails/tasks/engine.rake'
25
+
26
+
27
+ Bundler::GemHelper.install_tasks
28
+
29
+ require 'rake/testtask'
30
+
31
+ Rake::TestTask.new(:test) do |t|
32
+ t.libs << 'lib'
33
+ t.libs << 'test'
34
+ t.pattern = 'test/**/*_test.rb'
35
+ t.verbose = false
36
+ end
37
+
38
+
39
+ task :default => :test
@@ -0,0 +1,56 @@
1
+ body { background-color: #fff; color: #333; }
2
+
3
+ body, p, ol, ul, td {
4
+ font-family: verdana, arial, helvetica, sans-serif;
5
+ font-size: 13px;
6
+ line-height: 18px;
7
+ }
8
+
9
+ pre {
10
+ background-color: #eee;
11
+ padding: 10px;
12
+ font-size: 11px;
13
+ }
14
+
15
+ a { color: #000; }
16
+ a:visited { color: #666; }
17
+ a:hover { color: #fff; background-color:#000; }
18
+
19
+ div.field, div.actions {
20
+ margin-bottom: 10px;
21
+ }
22
+
23
+ #notice {
24
+ color: green;
25
+ }
26
+
27
+ .field_with_errors {
28
+ padding: 2px;
29
+ background-color: red;
30
+ display: table;
31
+ }
32
+
33
+ #error_explanation {
34
+ width: 450px;
35
+ border: 2px solid red;
36
+ padding: 7px;
37
+ padding-bottom: 0;
38
+ margin-bottom: 20px;
39
+ background-color: #f0f0f0;
40
+ }
41
+
42
+ #error_explanation h2 {
43
+ text-align: left;
44
+ font-weight: bold;
45
+ padding: 5px 5px 5px 15px;
46
+ font-size: 12px;
47
+ margin: -7px;
48
+ margin-bottom: 0px;
49
+ background-color: #c00;
50
+ color: #fff;
51
+ }
52
+
53
+ #error_explanation ul li {
54
+ font-size: 12px;
55
+ list-style: square;
56
+ }
@@ -0,0 +1,29 @@
1
+ module Blog
2
+ # inherit from the mounting application's application_controller
3
+ class ApplicationController < ::ApplicationController
4
+
5
+ layout "application"
6
+
7
+ # We need construct_blog_path() for respond_to actions
8
+ include BlogsHelper
9
+
10
+ def can_manage_blogs
11
+ redirect_to main_app.root_url, :notice => 'You do not have permissions to view that page.' unless blog_user_can?(:manage, Blog)
12
+ end
13
+
14
+ def can_manage_contexts
15
+ redirect_to main_app.root_url, :notice => 'You do not have permissions to view that page.' unless blog_user_can?(:manage, Context)
16
+ end
17
+
18
+ # def log_exception(e)
19
+ # Rails.logger.fatal("#{e.class} (#{e.message}):\n" + clean_backtrace(e).join("\n "));
20
+ # end
21
+ #
22
+ # def clean_backtrace(e)
23
+ # if backtrace = e.backtrace
24
+ # backtrace.map { |line| line.sub Rails.root.to_s, '' }
25
+ # end
26
+ # end
27
+
28
+ end
29
+ end
@@ -0,0 +1,115 @@
1
+ module Blog
2
+ class BlogsController < ApplicationController
3
+
4
+ # before_filter :redirect_unless_admin, :except => [:index, :show]
5
+ before_filter :can_manage_blogs, :except => [:index, :show]
6
+ before_filter :setup_blog_context, :except => [:create]
7
+ before_filter :ensure_full_path, :only => [:index]
8
+ before_filter :find_blog, :only => [:show, :edit, :update, :destroy]
9
+
10
+ def index
11
+ if @context
12
+ @blogs = Blog.where("context_id = ?", @context.id).limit(10).order('created_at desc').paginate(:page => params[:page]).per_page(10)
13
+ @archive = Blog.where("context_id = ? and id not in (?)", @context, @blogs.collect{|b| b.id}).limit(10).order('created_at desc')
14
+ else
15
+ @blogs = Blog.all
16
+ end
17
+ end
18
+
19
+ def new
20
+ # If we are at /blogs/new the it will look for a 'blogs' blog context. Likely one does not exist so use the first
21
+ # created as a default
22
+ @context ||= Context.first
23
+ @context_options = Context.selections
24
+ @blog = Blog.new(:context => @context, :photo => Photo.new)
25
+
26
+ respond_to do |format|
27
+ format.html { render }
28
+ format.xml { render :xml => @blog }
29
+ end
30
+ end
31
+
32
+ def create
33
+ # No, we don't pass these in the form
34
+ params[:blog].merge!(:user_id => current_user.id)
35
+
36
+ @blog = Blog.new(params[:blog])
37
+
38
+ if @blog.save
39
+ redirect_to(construct_blog_path(@blog, :show), :notice => "#{@blog.title} was successfully created.")
40
+ else
41
+ @context_options = Context.selections
42
+ @context = @blog.context
43
+ render :action => :new
44
+ end
45
+ end
46
+
47
+ def show
48
+ raise ActiveRecord::RecordNotFound unless @blog.present?
49
+ @other_blogs = Blog.where("context_id = ? and id != ?", @context, @blog.id).limit(10).order('created_at desc')
50
+
51
+ respond_to do |format|
52
+ format.html # show.haml relative to controller calling it
53
+ format.xml { render :xml => @blog }
54
+ end
55
+ end
56
+
57
+
58
+ def update
59
+ respond_to do |format|
60
+ if @blog.update_attributes(params[:blog])
61
+ format.xml { render :xml => @blog, :status => :created, :location => @blog }
62
+
63
+ format.html do
64
+ redirect_to(construct_blog_path(@blog, :show), :notice => "#{@blog.title} was successfully updated.")
65
+ end
66
+ else
67
+ format.html { render :action => :edit }
68
+ format.xml { render :xml => @blog.errors, :status => :unprocessable_entity }
69
+ end
70
+ end
71
+ end
72
+
73
+ def destroy
74
+ title = @blog.title
75
+ @blog.destroy
76
+
77
+ respond_to do |format|
78
+ format.html { redirect_to construct_blog_path(@blog, :index), :notice => "'#{title}' was successfully removed" }
79
+ format.json { head :ok }
80
+ end
81
+ end
82
+
83
+
84
+ # ------------------------------------------------------------------------------------------------------------------
85
+ private
86
+
87
+ # Which blog content is this. Possibly trends, reasons to sell or guides
88
+ def setup_blog_context
89
+ begin
90
+ route = request.path_info.split('/').reject{|pi| pi.blank?}.first
91
+ @context = Context.context_for_route(route)
92
+
93
+ # Controls menu highlighting and arrow
94
+ # active_section(@context)
95
+ rescue => e
96
+ # most likely due to no context found, assume they want/need to create one
97
+ redirect_to new_context_path, :notice => e.to_s
98
+ end
99
+ end
100
+
101
+ # SEO touch: Index pages should always use the context's full route, everything else should use the terse route
102
+ def ensure_full_path
103
+ return if params[:page].present? && params[:page].to_i > 1
104
+
105
+ unless @context.route_match?(:full, request.path)
106
+ redirect_to "/#{@context.full_route}", :status => 301
107
+ end
108
+ end
109
+
110
+ def find_blog
111
+ @blog = Blog.find_by_title_for_url(params[:id]) || Blog.find_by_id(params[:id])
112
+ end
113
+
114
+ end
115
+ end
@@ -0,0 +1,78 @@
1
+ module Blog
2
+ class ContextsController < ApplicationController
3
+
4
+ before_filter :can_manage_contexts
5
+
6
+ def index
7
+ @contexts = Context.all
8
+
9
+ respond_to do |format|
10
+ format.html # index.html.erb
11
+ format.json { render :json => @contexts }
12
+ end
13
+ end
14
+
15
+ def show
16
+ @context = Context.find(params[:id])
17
+
18
+ respond_to do |format|
19
+ format.html # show.html.erb
20
+ format.json { render :json => @context }
21
+ end
22
+ end
23
+
24
+ def new
25
+ @context = Context.new
26
+ end
27
+
28
+
29
+ def edit
30
+ @context = Context.find(params[:id])
31
+ end
32
+
33
+
34
+ def create
35
+ @context = Context.new(params[:context])
36
+
37
+ respond_to do |format|
38
+ if @context.save
39
+ notice = "The '#{@context.context_type}' context was successfully created."
40
+ format.html { redirect_to @context, :notice => notice }
41
+ format.json { render :json => @context, :status => :created, :location => @context }
42
+ else
43
+ format.html { render :action => "new" }
44
+ format.json { render :json => @context.errors, :status => :unprocessable_entity }
45
+ end
46
+ end
47
+ end
48
+
49
+
50
+ def update
51
+ @context = Context.find(params[:id])
52
+
53
+ respond_to do |format|
54
+ if @context.update_attributes(params[:context])
55
+ notice = "The '#{@context.context_type}' context was successfully updated."
56
+ format.html { redirect_to context_path(@context), :notice => notice }
57
+ format.json { head :ok }
58
+ else
59
+ format.html { render :action => "edit" }
60
+ format.json { render :json => @context.errors, :status => :unprocessable_entity }
61
+ end
62
+ end
63
+ end
64
+
65
+ def destroy
66
+ context = Blog::Context.find_by_id(params[:id])
67
+ notice = "The '#{context.context_type}' context has been destroyed. Please remove the entries from you routes file"
68
+
69
+ context.destroy
70
+
71
+ respond_to do |format|
72
+ format.html { redirect_to contexts_path, :notice => notice }
73
+ format.json { head :ok }
74
+ end
75
+ end
76
+
77
+ end
78
+ end
@@ -0,0 +1,15 @@
1
+ module Blog
2
+ class SluggablesController < ApplicationController
3
+
4
+ def create
5
+
6
+ if params[:slug].present?
7
+ render :text => params[:slug].make_url_friendly
8
+ else
9
+ render :text => '', :status => 400
10
+ end
11
+
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,4 @@
1
+ module Blog
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,26 @@
1
+ module Blog
2
+ module BlogsHelper
3
+
4
+ def allowable_html
5
+ %w(br p a b ul li)
6
+ end
7
+
8
+ def construct_blog_path(blog_obj, action='index', context=nil, full_path=false)
9
+ context = blog_obj.context if context.nil?
10
+ full_route = context.full_route.underscore
11
+
12
+ rel_path = case action.to_s.intern
13
+ when :index then "/#{context.full_route}"
14
+ when :create then "/#{context.terse_route}" #main_app.send("#{full_route}_index_path")
15
+ when :new, :edit then main_app.send("#{action.to_s}_#{full_route.singularize}_path")
16
+ when :show, :update, :delete then main_app.send("#{full_route.singularize}_path", blog_obj.title_for_url)
17
+ end
18
+
19
+ full_path ? "#{root_url}#{rel_path.gsub(/^\//,'')}" : rel_path
20
+ end
21
+
22
+ def posted_by_on(blog)
23
+ "Posted by #{blog.user.email} on <time datetime='#{blog.created_at}'>#{blog.created_at.to_s(:created_at)}</time>".html_safe
24
+ end
25
+ end
26
+ end