gluttonberg-blog 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +3 -0
  4. data/Rakefile +38 -0
  5. data/app/assets/javascripts/blog/application.js +15 -0
  6. data/app/assets/stylesheets/blog/application.css +13 -0
  7. data/app/controllers/gluttonberg/admin/blog/application_controller.rb +6 -0
  8. data/app/controllers/gluttonberg/admin/blog/articles_controller.rb +168 -0
  9. data/app/controllers/gluttonberg/admin/blog/blogs_controller.rb +95 -0
  10. data/app/controllers/gluttonberg/admin/blog/comments_controller.rb +117 -0
  11. data/app/controllers/gluttonberg/public/blog/articles_controller.rb +88 -0
  12. data/app/controllers/gluttonberg/public/blog/blogs_controller.rb +47 -0
  13. data/app/controllers/gluttonberg/public/blog/comments_controller.rb +54 -0
  14. data/app/helpers/gluttonberg/blog/application_helper.rb +6 -0
  15. data/app/mailers/blog_notifier.rb +26 -0
  16. data/app/models/gluttonberg/blog/article.rb +120 -0
  17. data/app/models/gluttonberg/blog/comment.rb +152 -0
  18. data/app/models/gluttonberg/blog/comment_subscription.rb +31 -0
  19. data/app/models/gluttonberg/blog/weblog.rb +25 -0
  20. data/app/views/blog_notifier/comment_notification.html.haml +17 -0
  21. data/app/views/blog_notifier/comment_notification_for_admin.html.haml +19 -0
  22. data/app/views/gluttonberg/admin/blog/articles/_form.html.haml +106 -0
  23. data/app/views/gluttonberg/admin/blog/articles/edit.html.haml +12 -0
  24. data/app/views/gluttonberg/admin/blog/articles/import.html.haml +36 -0
  25. data/app/views/gluttonberg/admin/blog/articles/index.html.haml +82 -0
  26. data/app/views/gluttonberg/admin/blog/articles/new.html.haml +11 -0
  27. data/app/views/gluttonberg/admin/blog/blogs/_form.html.haml +53 -0
  28. data/app/views/gluttonberg/admin/blog/blogs/edit.html.haml +10 -0
  29. data/app/views/gluttonberg/admin/blog/blogs/index.html.haml +35 -0
  30. data/app/views/gluttonberg/admin/blog/blogs/new.html.haml +10 -0
  31. data/app/views/gluttonberg/admin/blog/comments/index.html.haml +66 -0
  32. data/app/views/gluttonberg/public/blog/articles/index.rss.builder +21 -0
  33. data/app/views/gluttonberg/public/blog/blogs/show.rss.builder +21 -0
  34. data/app/views/layouts/blog/application.html.erb +14 -0
  35. data/config/routes.rb +53 -0
  36. data/lib/generators/gluttonberg/blog/blog_generator.rb +42 -0
  37. data/lib/generators/gluttonberg/blog/templates/articles_index.html.haml +18 -0
  38. data/lib/generators/gluttonberg/blog/templates/articles_show.html.haml +63 -0
  39. data/lib/generators/gluttonberg/blog/templates/articles_tag.html.haml +25 -0
  40. data/lib/generators/gluttonberg/blog/templates/blog_migration.rb +94 -0
  41. data/lib/generators/gluttonberg/blog/templates/blogs_index.html.haml +15 -0
  42. data/lib/generators/gluttonberg/blog/templates/blogs_show.html.haml +26 -0
  43. data/lib/gluttonberg/blog.rb +9 -0
  44. data/lib/gluttonberg/blog/engine.rb +22 -0
  45. data/lib/gluttonberg/blog/tasks/blog_tasks.rake +12 -0
  46. data/lib/gluttonberg/blog/version.rb +5 -0
  47. data/spec/dummy/README.rdoc +261 -0
  48. data/spec/dummy/Rakefile +7 -0
  49. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  50. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  51. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  52. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  53. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  54. data/spec/dummy/config.ru +4 -0
  55. data/spec/dummy/config/application.rb +59 -0
  56. data/spec/dummy/config/boot.rb +10 -0
  57. data/spec/dummy/config/database.yml +8 -0
  58. data/spec/dummy/config/environment.rb +5 -0
  59. data/spec/dummy/config/environments/development.rb +37 -0
  60. data/spec/dummy/config/environments/production.rb +67 -0
  61. data/spec/dummy/config/environments/test.rb +37 -0
  62. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  63. data/spec/dummy/config/initializers/inflections.rb +15 -0
  64. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  65. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  66. data/spec/dummy/config/initializers/session_store.rb +8 -0
  67. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  68. data/spec/dummy/config/locales/en.yml +5 -0
  69. data/spec/dummy/config/routes.rb +3 -0
  70. data/spec/dummy/db/schema.rb +476 -0
  71. data/spec/dummy/public/404.html +26 -0
  72. data/spec/dummy/public/422.html +26 -0
  73. data/spec/dummy/public/500.html +25 -0
  74. data/spec/dummy/public/favicon.ico +0 -0
  75. data/spec/dummy/script/rails +6 -0
  76. data/spec/fixtures/assets/gb_banner.jpg +0 -0
  77. data/spec/fixtures/assets/gb_logo.png +0 -0
  78. data/spec/fixtures/assets/high_res_photo.jpg +0 -0
  79. data/spec/fixtures/assets/untitled +0 -0
  80. data/spec/fixtures/members.csv +5 -0
  81. data/spec/fixtures/staff_profiles.csv +4 -0
  82. data/spec/helpers/page_info_spec.rb +213 -0
  83. data/spec/mailers/blog_notifier_spec.rb +127 -0
  84. data/spec/models/article_spec.rb +213 -0
  85. data/spec/spec_helper.rb +67 -0
  86. metadata +203 -0
@@ -0,0 +1,88 @@
1
+ module Gluttonberg
2
+ module Public
3
+ module Blog
4
+ class ArticlesController < Gluttonberg::Public::BaseController
5
+ before_filter :find_blog, :only => [:index, :show, :preview]
6
+
7
+ def index
8
+ @articles = @blog.articles.published.includes(:localizations)
9
+ respond_to do |format|
10
+ format.html
11
+ format.rss { render :layout => false }
12
+ end
13
+ end
14
+
15
+ def show
16
+ find_article
17
+ return if redirect_if_previous_path
18
+ load_correct_version_and_localization
19
+
20
+ @comments = @article.comments.where(:approved => true)
21
+ @comment = Gluttonberg::Blog::Comment.new(:subscribe_to_comments => true)
22
+ respond_to do |format|
23
+ format.html
24
+ end
25
+ end
26
+
27
+ def tag
28
+ @articles = Gluttonberg::Blog::Article.tagged_with(params[:tag]).includes(:blog).published
29
+ @tags = Gluttonberg::Blog::Article.published.tag_counts_on(:tag)
30
+ respond_to do |format|
31
+ format.html
32
+ end
33
+ end
34
+
35
+ def unsubscribe
36
+ @subscription = Gluttonberg::Blog::CommentSubscription.where(:reference_hash => params[:reference]).first
37
+ unless @subscription.blank?
38
+ @subscription.destroy
39
+ flash[:notice] = "You are successfully unsubscribe from comments of \"#{@subscription.article.title}\""
40
+ redirect_to blog_article_path(:blog_id => @subscription.article.blog.slug, :id => @subscription.article.slug)
41
+ else
42
+ raise ActiveRecord::RecordNotFound.new
43
+ end
44
+ end
45
+
46
+ private
47
+ def find_blog
48
+ @blog = Gluttonberg::Blog::Weblog.where(:slug => params[:blog_id]).includes([:articles]).first
49
+ if @blog.blank?
50
+ @blog = Gluttonberg::Blog::Weblog.published.where(:previous_slug => params[:blog_id]).first
51
+ end
52
+ @blog = nil if @blog && current_user.blank? && !@blog.published?
53
+ raise ActiveRecord::RecordNotFound.new if @blog.blank?
54
+ end
55
+
56
+ def find_article
57
+ @article = Gluttonberg::Blog::Article.where(:slug => params[:id], :blog_id => @blog.id).first
58
+ find_article_by_previous_path
59
+ @article = nil if @article && current_user.blank? && !@article.published?
60
+ raise ActiveRecord::RecordNotFound.new if @article.blank?
61
+ end
62
+
63
+ def find_article_by_previous_path
64
+ if @article.blank?
65
+ @article = Gluttonberg::Blog::Article.published.where(:previous_slug => params[:id], :blog_id => @blog.id).first
66
+ end
67
+ end
68
+
69
+ def redirect_if_previous_path
70
+ if @blog.previous_slug == params[:blog_id] || @article.previous_slug == params[:id]
71
+ redirect_to blog_article_path(:blog_id => @blog.slug , :id => params[:id]) , :status => 301
72
+ true
73
+ else
74
+ false
75
+ end
76
+ end
77
+
78
+ def load_correct_version_and_localization
79
+ @article.load_localization(env['GLUTTONBERG.LOCALE'])
80
+ if current_user && params[:preview].to_s == "true"
81
+ Gluttonberg::AutoSave.load_version(@article.current_localization)
82
+ end
83
+ end
84
+
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,47 @@
1
+ module Gluttonberg
2
+ module Public
3
+ module Blog
4
+ class BlogsController < Gluttonberg::Public::BaseController
5
+
6
+ def index
7
+ @blogs = Gluttonberg::Blog::Weblog.published.all
8
+ if @blogs.blank?
9
+ redirect_to "/"
10
+ elsif @blogs.length == 1
11
+ if Gluttonberg.localized?
12
+ redirect_to blog_path(current_localization_slug , @blogs.first.slug)
13
+ else
14
+ redirect_to blog_path(:id =>@blogs.first.slug)
15
+ end
16
+ end
17
+ end
18
+
19
+ def show
20
+ @blog = Gluttonberg::Blog::Weblog.published.where(:slug => params[:id]).includes(:articles).first
21
+ return if find_by_previous_path
22
+ raise ActiveRecord::RecordNotFound.new if @blog.blank?
23
+ @articles = @blog.articles.published.order("published_at DESC").includes(:localizations).paginate(:page => params[:page], :per_page => Gluttonberg::Setting.get_setting("number_of_per_page_items"))
24
+ @tags = Gluttonberg::Blog::Article.published.tag_counts_on(:tag)
25
+ respond_to do |format|
26
+ format.html
27
+ format.rss { render :layout => false }
28
+ end
29
+ end
30
+
31
+ private
32
+ def find_by_previous_path
33
+ if @blog.blank?
34
+ @blog = Gluttonberg::Blog::Weblog.published.where(:previous_slug => params[:id]).first
35
+
36
+ unless @blog.blank?
37
+ redirect_to blog_path(:id => @blog.slug) , :status => 301
38
+ return true
39
+ end
40
+ end
41
+ false
42
+ end
43
+
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,54 @@
1
+ module Gluttonberg
2
+ module Public
3
+ module Blog
4
+ class CommentsController < Gluttonberg::Public::BaseController
5
+ def create
6
+ find_blog_and_article
7
+ prepare_comment
8
+
9
+ if @comment.save
10
+ send_notification
11
+ adjust_subscription
12
+ else
13
+ end
14
+ if Gluttonberg.localized?
15
+ redirect_to blog_article_path(current_localization_slug , @blog.slug, @article.slug)
16
+ else
17
+ redirect_to blog_article_path(:blog_id => @blog.slug, :id => @article.slug)
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def send_notification
24
+ if Setting.get_setting("comment_notification") == "Yes" || @blog.moderation_required == true
25
+ User.all_super_admin_and_admins.each do |user|
26
+ BlogNotifier.comment_notification_for_admin(user , @article , @comment).deliver
27
+ end
28
+ end
29
+ end
30
+
31
+ def find_blog_and_article
32
+ @blog = Gluttonberg::Blog::Weblog.where(:slug => params[:blog_id]).first
33
+ @article = Gluttonberg::Blog::Article.where(:slug => params[:article_id], :blog_id => @blog.id).first
34
+ end
35
+
36
+ def prepare_comment
37
+ @comment = @article.comments.new(params[:comment])
38
+ @comment.blog_slug = params[:blog_id]
39
+ @comment.author_id = current_member.id if current_member
40
+ end
41
+
42
+ def adjust_subscription
43
+ @subscription = Gluttonberg::Blog::CommentSubscription.where(:article_id => @article.id , :author_email => @comment.writer_email).first
44
+ if @comment.subscribe_to_comments == "1" && @subscription.blank?
45
+ @subscription = Gluttonberg::Blog::CommentSubscription.create( {:article_id => @article.id , :author_email => @comment.writer_email , :author_name => @comment.writer_name } )
46
+ elsif (@comment.subscribe_to_comments.blank? || @comment.subscribe_to_comments == "0") && !@subscription.blank?
47
+ #unsubscribe
48
+ @subscription.destroy
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,6 @@
1
+ module Gluttonberg
2
+ module Blog
3
+ module ApplicationHelper
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,26 @@
1
+ class BlogNotifier < Gluttonberg::BaseNotifier
2
+ def comment_notification(subscriber , article , comment,current_localization_slug = "")
3
+ setup_from
4
+ @subscriber = subscriber
5
+ @article = article
6
+ @comment = comment
7
+ @website_title = Gluttonberg::Setting.get_setting("title")
8
+ @article_url = blog_article_url(current_localization_slug, article.blog.slug, article.slug)
9
+ @unsubscribe_url = unsubscribe_article_comments_url(@subscriber.reference_hash)
10
+
11
+ mail(:to => @subscriber.author_email, :subject => "Re: [#{@website_title}] #{@article.title}")
12
+ end
13
+
14
+ def comment_notification_for_admin(admin , article , comment)
15
+ setup_email
16
+ @admin = admin
17
+ @article = article
18
+ @blog = @article.blog
19
+ @comment = comment
20
+ @website_title = Gluttonberg::Setting.get_setting("title")
21
+ @article_url = blog_article_url(:blog_id => article.blog.slug, :id => article.slug)
22
+
23
+ mail(:to => @admin.email, :subject => "Re: [#{@website_title}] #{@article.title}")
24
+ end
25
+
26
+ end
@@ -0,0 +1,120 @@
1
+ module Gluttonberg
2
+ module Blog
3
+ class Article < ActiveRecord::Base
4
+ self.table_name = "gb_articles"
5
+ include Content::SlugManagement
6
+ include Content::Publishable
7
+ include Content::Localization
8
+ MixinManager.load_mixins(self)
9
+
10
+ belongs_to :blog, :foreign_key => 'blog_id', :class_name => "Gluttonberg::Blog::Weblog"
11
+ belongs_to :author, :class_name => "User"
12
+ belongs_to :user #created by
13
+ has_many :comments, :as => :commentable, :dependent => :destroy
14
+ has_many :localizations, :class_name => "Gluttonberg::ArticleLocalization" , :foreign_key => :article_id , :dependent => :destroy
15
+
16
+ acts_as_taggable_on :article_category , :tag
17
+ attr_accessor :name
18
+ delegate :title , :body , :excerpt , :featured_image_id , :featured_image , :to => :current_localization
19
+ attr_accessible :user_id, :blog_id, :author_id, :slug, :article_category_list, :tag_list, :disable_comments, :state, :published_at, :name
20
+ attr_accessible :user, :blog, :author
21
+ validates_presence_of :user_id, :author_id, :blog_id
22
+ delegate :version, :loaded_version, :to => :current_localization
23
+
24
+ if ActiveRecord::Base.connection.table_exists?('gb_article_localizations')
25
+ is_localized(:parent_key => :article_id) do
26
+ self.table_name = "gb_article_localizations"
27
+ belongs_to :article , :class_name => "Gluttonberg::Blog::Article"
28
+ belongs_to :locale
29
+
30
+ belongs_to :fb_icon , :class_name => "Gluttonberg::Asset" , :foreign_key => "fb_icon_id"
31
+ belongs_to :featured_image , :foreign_key => :featured_image_id , :class_name => "Gluttonberg::Asset"
32
+
33
+ is_versioned :non_versioned_columns => ['state' , 'disable_comments' , 'published_at' , 'article_id' , 'locale_id']
34
+
35
+ validates_presence_of :title
36
+ attr_accessible :article, :locale_id, :title, :featured_image_id, :excerpt, :body, :seo_title, :seo_keywords, :seo_description, :fb_icon_id, :article_id
37
+ delegate :state, :_publish_status, :state_changed?, :to => :article, :allow_nil => true
38
+
39
+ clean_html [:excerpt , :body]
40
+
41
+ def name
42
+ title
43
+ end
44
+
45
+ def slug
46
+ self.article.slug
47
+ end
48
+ end #is_localized
49
+ end
50
+
51
+ import_export_csv([:id, :slug, :title, :seo_title, :seo_description, :seo_keywords, :state], [:excerpt, :body])
52
+
53
+ def commenting_disabled?
54
+ !disable_comments.blank? && disable_comments
55
+ end
56
+
57
+ def moderation_required
58
+ if self.blog.blank?
59
+ true
60
+ else
61
+ self.blog.moderation_required
62
+ end
63
+ end
64
+
65
+ def current_localization
66
+ if @current_localization.blank?
67
+ load_default_localizations
68
+ end
69
+ @current_localization
70
+ end
71
+
72
+ # Load the matching localization as specified in the options
73
+ def load_localization(locale = nil)
74
+ if locale.blank? || locale.id.blank?
75
+ @current_localization = load_default_localizations
76
+ else
77
+ @current_localization = localizations.find_all{|l| l.locale_id == locale.id}.first
78
+ end
79
+ @current_localization
80
+ end
81
+
82
+ def load_default_localizations
83
+ @current_localization = localizations.find_all{ |l| l.locale_id == Locale.first_default.id }.first
84
+ end
85
+
86
+ def create_localizations(params)
87
+ Locale.all.each do |locale|
88
+ article_localization = localizations.new(params.merge({
89
+ :locale_id => locale.id
90
+ })
91
+ )
92
+ article_localization.current_user_id = self.user_id
93
+ article_localization.save
94
+ end
95
+ end
96
+
97
+ def duplicate
98
+ ActiveRecord::Base.transaction do
99
+ duplicated_article = self.dup
100
+ duplicated_article.state = "draft"
101
+ duplicated_article.created_at = Time.now
102
+ duplicated_article.published_at = nil
103
+
104
+ if duplicated_article.save
105
+ self.localizations.each do |loc|
106
+ dup_loc = loc.dup
107
+ dup_loc.article_id = duplicated_article.id
108
+ dup_loc.created_at = Time.now
109
+ dup_loc.save
110
+ end
111
+ duplicated_article
112
+ else
113
+ nil
114
+ end
115
+ end
116
+ end
117
+
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,152 @@
1
+ module Gluttonberg
2
+ module Blog
3
+ class Comment < ActiveRecord::Base
4
+ self.table_name = "gb_comments"
5
+ MixinManager.load_mixins(self)
6
+ attr_accessible :body , :author_name , :author_email , :author_website , :subscribe_to_comments , :blog_slug
7
+
8
+ belongs_to :commentable, :polymorphic => true, :counter_cache => true
9
+ belongs_to :author, :class_name => "Gluttonberg::Member"
10
+
11
+ before_save :init_moderation
12
+ before_validation :spam_detection
13
+ after_save :send_notifications_if_needed
14
+
15
+ validates_presence_of :body
16
+
17
+ scope :all_approved, lambda { where("approved = ? AND ( spam = ? OR spam IS NULL)",true , false)}
18
+ scope :all_pending, lambda { where("moderation_required = ? AND ( spam = ? OR spam IS NULL)",true , false)}
19
+ scope :all_rejected, lambda { where("moderation_required = ? AND approved = ? AND ( spam = ? OR spam IS NULL)",false , false , false)}
20
+ scope :all_spam, lambda { where(:spam => true)}
21
+
22
+ attr_accessor :subscribe_to_comments , :blog_slug
23
+ attr_accessible :body , :author_name , :author_email , :author_website , :commentable_id , :commentable_type , :author_id
24
+ attr_accessible :user, :author, :commentable
25
+ alias_attribute :user_id, :author_id
26
+
27
+ can_be_flagged
28
+
29
+ clean_html [:body]
30
+
31
+ def moderate(params)
32
+ if params == "approve"
33
+ self.moderation_required = false
34
+ self.approved = true
35
+ self.spam = false
36
+ self.save
37
+ elsif params == "disapprove"
38
+ self.moderation_required = false
39
+ self.approved = false
40
+ self.save
41
+ else
42
+ #error
43
+ end
44
+ end
45
+
46
+ # these are helper methods for comment.
47
+ def writer_email
48
+ if self.author_email
49
+ self.author_email
50
+ elsif author
51
+ author.email
52
+ end
53
+ end
54
+
55
+ def writer_name
56
+ if self.author_name
57
+ self.author_name
58
+ elsif author
59
+ author.full_name
60
+ end
61
+ end
62
+
63
+ def approved=(val)
64
+ @approve_updated = !self.moderation_required && val && self.notification_sent_at.blank? #just got approved
65
+ write_attribute(:approved, val)
66
+ end
67
+
68
+ def self.spam_detection_for_all
69
+ self.all_pending.each do |c|
70
+ c.send("spam_detection")
71
+ c.save(:validate => false)
72
+ end
73
+ end
74
+
75
+ def black_list_author
76
+ author_string = _concat("", self.author_name)
77
+ author_string = _concat(author_string, self.author_email)
78
+ author_string = _concat(author_string, self.author_website)
79
+ unless author_string.blank?
80
+ gb_blacklist_settings = Gluttonberg::Setting.get_setting("comment_blacklist")
81
+ gb_blacklist_settings = _concat(gb_blacklist_settings, author_string)
82
+ Gluttonberg::Setting.update_settings("comment_blacklist" => gb_blacklist_settings)
83
+ Comment.spam_detection_for_all
84
+ end
85
+ end
86
+
87
+ protected
88
+ def init_moderation
89
+ if self.commentable.respond_to?(:moderation_required)
90
+ if self.commentable.moderation_required == false
91
+ self.approved = true
92
+ write_attribute(:moderation_required, false)
93
+ end
94
+ end
95
+ true
96
+ end
97
+
98
+ def send_notifications_if_needed
99
+ if @approve_updated == true
100
+ @approve_updated = false
101
+ CommentSubscription.notify_subscribers_of(self.commentable , self)
102
+ end
103
+ end
104
+
105
+ def spam_detection
106
+ unless self.body.blank?
107
+ dspam = Gluttonberg::Content::Despamilator.new(self.body)
108
+ self.spam = (dspam.score >= 1.0)
109
+ self.spam_score = dspam.score
110
+ self.check_author_details_for_spam
111
+ else
112
+ self.spam = true
113
+ self.spam_score = 1.0
114
+ end
115
+ end
116
+
117
+ def self._blank?(str)
118
+ str.blank? || str == "NULL" || str.length < 3
119
+ end
120
+
121
+ def _blank?(str)
122
+ self.class._blank?(str)
123
+ end
124
+
125
+ def self._concat(str1, str2)
126
+ unless _blank?(str2)
127
+ str1 = str1.blank? ? str2 : "#{str1}, #{str2}"
128
+ end
129
+ str1
130
+ end
131
+
132
+ def _concat(str1, str2)
133
+ self.class._concat(str1, str2)
134
+ end
135
+
136
+
137
+ def check_author_details_for_spam
138
+ unless self.spam
139
+ naughty_word_parser = Gluttonberg::Content::DespamilatorFilter::NaughtyWords.new
140
+ [:author_email, :author_name, :author_website].each do |field|
141
+ val = self.send(field)
142
+ if !val.blank? && naughty_word_parser.local_parse(val) >= 1.0
143
+ self.spam = true
144
+ break
145
+ end
146
+ end
147
+ end
148
+ end
149
+
150
+ end
151
+ end
152
+ end