publify_core 9.0.0.pre6 → 9.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 (176) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +44 -0
  3. data/README.md +9 -0
  4. data/app/controllers/admin/base_controller.rb +0 -6
  5. data/app/controllers/admin/content_controller.rb +34 -15
  6. data/app/controllers/admin/dashboard_controller.rb +4 -9
  7. data/app/controllers/admin/feedback_controller.rb +1 -0
  8. data/app/controllers/admin/notes_controller.rb +1 -1
  9. data/app/controllers/admin/pages_controller.rb +3 -7
  10. data/app/controllers/admin/sidebar_controller.rb +1 -0
  11. data/app/controllers/admin/tags_controller.rb +1 -0
  12. data/app/controllers/articles_controller.rb +50 -55
  13. data/app/controllers/comments_controller.rb +2 -3
  14. data/app/controllers/content_controller.rb +8 -17
  15. data/app/controllers/feedback_controller.rb +5 -39
  16. data/app/controllers/notes_controller.rb +1 -3
  17. data/app/controllers/setup_controller.rb +14 -18
  18. data/app/controllers/tags_controller.rb +13 -15
  19. data/app/controllers/theme_controller.rb +7 -5
  20. data/app/controllers/xml_controller.rb +11 -59
  21. data/app/helpers/authors_helper.rb +2 -2
  22. data/app/helpers/base_helper.rb +11 -4
  23. data/app/helpers/xml_helper.rb +2 -2
  24. data/app/jobs/application_job.rb +2 -0
  25. data/app/models/archives_sidebar.rb +8 -11
  26. data/app/models/article.rb +53 -72
  27. data/app/models/article/factory.rb +1 -1
  28. data/app/models/blog.rb +17 -40
  29. data/app/models/comment.rb +4 -3
  30. data/app/models/content.rb +18 -21
  31. data/app/models/content_base.rb +0 -5
  32. data/app/models/feedback.rb +76 -54
  33. data/app/models/meta_sidebar.rb +1 -0
  34. data/app/models/note.rb +7 -0
  35. data/app/models/page.rb +10 -5
  36. data/app/models/ping.rb +0 -113
  37. data/app/models/post_type.rb +1 -0
  38. data/app/models/redirect.rb +1 -1
  39. data/app/models/resource.rb +1 -19
  40. data/app/models/sidebar.rb +1 -1
  41. data/app/models/static_sidebar.rb +1 -0
  42. data/app/models/tag.rb +13 -9
  43. data/app/models/tag_sidebar.rb +4 -4
  44. data/app/models/trackback.rb +1 -8
  45. data/app/models/trigger.rb +1 -15
  46. data/app/models/user.rb +2 -9
  47. data/app/uploaders/resource_uploader.rb +33 -2
  48. data/app/views/accounts/confirm.html.erb +0 -1
  49. data/app/views/admin/content/_article_list.html.erb +1 -1
  50. data/app/views/admin/content/_form.html.erb +3 -7
  51. data/app/views/admin/pages/_form.html.erb +2 -2
  52. data/app/views/admin/seo/_general.html.erb +33 -28
  53. data/app/views/admin/seo/_permalinks.html.erb +2 -2
  54. data/app/views/admin/seo/_titles.html.erb +36 -36
  55. data/app/views/admin/settings/display.html.erb +20 -27
  56. data/app/views/admin/settings/feedback.html.erb +44 -51
  57. data/app/views/admin/settings/index.html.erb +14 -14
  58. data/app/views/admin/settings/write.html.erb +12 -30
  59. data/app/views/admin/tags/_index_and_form.html.erb +1 -1
  60. data/app/views/articles/_archives_article.html.erb +9 -0
  61. data/app/views/articles/_article.html.erb +8 -6
  62. data/app/views/articles/_article_collection.html.erb +1 -1
  63. data/app/views/articles/_article_excerpt.html.erb +10 -8
  64. data/app/views/articles/_article_links.html.erb +4 -2
  65. data/app/views/articles/_comment_list.html.erb +5 -5
  66. data/app/views/articles/_full_article_content.html.erb +4 -2
  67. data/app/views/articles/archives.html.erb +10 -20
  68. data/app/views/articles/feedback_atom_feed.atom.builder +5 -5
  69. data/app/views/articles/feedback_rss_feed.rss.builder +12 -13
  70. data/app/views/articles/index_atom_feed.atom.builder +3 -4
  71. data/app/views/articles/index_rss_feed.rss.builder +9 -10
  72. data/app/views/articles/read.html.erb +5 -31
  73. data/app/views/articles/search.html.erb +1 -1
  74. data/app/views/articles/trackback.xml.builder +1 -1
  75. data/app/views/authors/show.html.erb +11 -21
  76. data/app/views/authors/show_atom_feed.atom.builder +3 -4
  77. data/app/views/authors/show_rss_feed.rss.builder +9 -10
  78. data/app/views/comments/_comment.html.erb +17 -16
  79. data/app/views/feedback/index.atom.builder +7 -0
  80. data/app/views/feedback/index.rss.builder +19 -0
  81. data/app/views/notes/_note.html.erb +16 -15
  82. data/app/views/notes/index.html.erb +1 -1
  83. data/app/views/notification_mailer/_mail_footer.html.erb +0 -2
  84. data/app/views/notification_mailer/_mail_header.html.erb +2 -0
  85. data/app/views/notification_mailer/article.html.erb +4 -3
  86. data/app/views/notification_mailer/comment.html.erb +7 -6
  87. data/app/views/notification_mailer/notif_user.html.erb +3 -8
  88. data/app/views/setup/index.html.erb +4 -0
  89. data/app/views/shared/_atom_header.atom.builder +3 -3
  90. data/app/views/shared/_atom_item_article.atom.builder +26 -19
  91. data/app/views/shared/_atom_item_comment.atom.builder +3 -5
  92. data/app/views/shared/_atom_item_trackback.atom.builder +3 -4
  93. data/app/views/shared/_page_header.html.erb +1 -1
  94. data/app/views/shared/_rss_item_article.rss.builder +10 -15
  95. data/app/views/shared/_rss_item_comment.rss.builder +1 -2
  96. data/app/views/shared/_rss_item_trackback.rss.builder +1 -1
  97. data/app/views/tags/index.html.erb +2 -2
  98. data/app/views/xml/sitemap.googlesitemap.builder +7 -0
  99. data/config/initializers/mime_types.rb +0 -1
  100. data/config/locales/da.yml +8 -37
  101. data/config/locales/de.yml +7 -36
  102. data/config/locales/en.yml +7 -36
  103. data/config/locales/es-MX.yml +8 -37
  104. data/config/locales/fr.yml +7 -36
  105. data/config/locales/he.yml +4 -33
  106. data/config/locales/it.yml +7 -36
  107. data/config/locales/ja.yml +5 -34
  108. data/config/locales/lt.yml +7 -36
  109. data/config/locales/nb-NO.yml +7 -36
  110. data/config/locales/nl.yml +9 -38
  111. data/config/locales/pl.yml +8 -37
  112. data/config/locales/pt-BR.yml +8 -37
  113. data/config/locales/ro.yml +9 -38
  114. data/config/locales/ru.yml +7 -36
  115. data/config/locales/zh-CN.yml +6 -35
  116. data/config/locales/zh-TW.yml +7 -36
  117. data/config/routes.rb +6 -28
  118. data/db/migrate/113_initial_schema.rb +191 -191
  119. data/db/migrate/114_fixes_buggy_articles_and_notes.rb +6 -7
  120. data/db/migrate/115_drops_categories_for_tags.rb +3 -3
  121. data/db/migrate/20150207131657_add_missing_indexes.rb +1 -1
  122. data/db/migrate/20150807134129_simplify_redirect_relations.rb +1 -1
  123. data/db/migrate/20150808052637_add_blog_ids.rb +3 -5
  124. data/db/migrate/20150808191127_add_blog_id_to_redirects.rb +1 -1
  125. data/db/migrate/20150810094754_add_blog_id_to_tags.rb +1 -1
  126. data/db/migrate/20160108111120_add_devise_to_users.rb +3 -3
  127. data/db/migrate/20160108184201_move_last_connection_to_last_sign_in_at.rb +1 -1
  128. data/db/migrate/20160110094906_remove_profiles_rights.rb +1 -1
  129. data/db/migrate/20160605103918_replace_profile_id_with_string.rb +1 -3
  130. data/db/migrate/20160605154632_remove_profiles.rb +2 -2
  131. data/db/migrate/20160701061851_demand_blog_id_on_contents.rb +1 -1
  132. data/db/migrate/20160701062604_add_blog_id_to_resources.rb +1 -1
  133. data/db/migrate/20170528093024_move_resources_to_content.rb +5 -0
  134. data/db/migrate/20170528094923_move_tags_to_content.rb +6 -0
  135. data/db/migrate/20170528201606_remove_separate_published_flag.rb +5 -0
  136. data/db/migrate/20170605071626_remove_extra_state_columns_from_feedback.rb +6 -0
  137. data/db/migrate/20170702105201_remove_published_at_from_feedback.rb +5 -0
  138. data/db/seeds.rb +1 -1
  139. data/lib/publify_core.rb +0 -1
  140. data/lib/publify_core/version.rb +1 -1
  141. data/lib/publify_guid.rb +1 -1
  142. data/lib/publify_time.rb +2 -2
  143. data/lib/sidebar_field.rb +19 -12
  144. data/lib/transforms.rb +1 -0
  145. metadata +102 -66
  146. data/.gitignore +0 -13
  147. data/.rspec +0 -2
  148. data/.rubocop.yml +0 -84
  149. data/.rubocop_todo.yml +0 -148
  150. data/.travis.yml +0 -27
  151. data/Gemfile +0 -17
  152. data/README.rdoc +0 -3
  153. data/Rakefile +0 -35
  154. data/app/assets/stylesheets/publify_core/.keep +0 -0
  155. data/app/controllers/.keep +0 -0
  156. data/app/controllers/admin/migrations_controller.rb +0 -19
  157. data/app/controllers/concerns/.keep +0 -0
  158. data/app/controllers/trackbacks_controller.rb +0 -36
  159. data/app/helpers/.keep +0 -0
  160. data/app/mailers/.keep +0 -0
  161. data/app/models/.keep +0 -0
  162. data/app/models/article/states.rb +0 -179
  163. data/app/models/concerns/.keep +0 -0
  164. data/app/models/feedback/states.rb +0 -256
  165. data/app/services/migrator.rb +0 -25
  166. data/app/views/.keep +0 -0
  167. data/app/views/comments/index.html.erb +0 -1
  168. data/app/views/comments/index_atom_feed.atom.builder +0 -8
  169. data/app/views/comments/index_rss_feed.rss.builder +0 -20
  170. data/app/views/trackbacks/index_atom_feed.atom.builder +0 -7
  171. data/app/views/trackbacks/index_rss_feed.rss.builder +0 -20
  172. data/app/views/trackbacks/trackback.xml.builder +0 -4
  173. data/app/views/xml/feed.googlesitemap.builder +0 -7
  174. data/app/views/xml/rsd.rsd.builder +0 -8
  175. data/lib/stateful.rb +0 -106
  176. data/publify_core.gemspec +0 -54
@@ -1,16 +1,16 @@
1
- require_dependency 'spam_protection'
1
+ # frozen_string_literal: true
2
+
3
+ require 'aasm'
2
4
  require 'akismet'
3
5
 
4
6
  class Feedback < ActiveRecord::Base
5
7
  self.table_name = 'feedback'
6
8
 
7
9
  belongs_to :text_filter, optional: true
8
- belongs_to :article
10
+ belongs_to :article, touch: true
9
11
 
10
12
  include PublifyGuid
11
- include Stateful
12
13
  include ContentBase
13
- include States
14
14
 
15
15
  class ContentTextHelpers
16
16
  include ActionView::Helpers::UrlHelper
@@ -22,52 +22,69 @@ class Feedback < ActiveRecord::Base
22
22
  validates :article, presence: true
23
23
 
24
24
  before_create :create_guid, :article_allows_this_feedback
25
- before_save :correct_url, :before_save_handler
26
- after_save :post_trigger, :report_classification
27
- after_initialize :after_initialize_handler
25
+ before_save :correct_url, :classify_content
28
26
 
27
+ # TODO: Rename so it doesn't sound like only approved ham
29
28
  scope :ham, -> { where(state: %w(presumed_ham ham)) }
29
+
30
30
  scope :spam, -> { where(state: 'spam') }
31
- scope :published_since, ->(time) { ham.where('published_at > ?', time) }
31
+ scope :created_since, ->(time) { ham.where('created_at > ?', time) }
32
32
  scope :presumed_ham, -> { where(state: 'presumed_ham') }
33
33
  scope :presumed_spam, -> { where(state: 'presumed_spam') }
34
- scope :unapproved, -> { where(status_confirmed: false) }
34
+ scope :unapproved, -> { where(state: ['presumed_spam', 'presumed_ham']) }
35
35
 
36
- scope :published, -> { where(published: true) }
36
+ scope :published, -> { ham }
37
37
  scope :oldest_first, -> { order(:created_at) }
38
+ scope :newest_first, -> { order(created_at: :desc) }
38
39
 
39
- has_state(:state,
40
- valid_states: [:unclassified, :presumed_spam, :just_marked_as_spam, :spam, :just_presumed_ham, :presumed_ham, :just_marked_as_ham, :ham],
41
- handles: [:published?, :status_confirmed?, :just_published?,
42
- :mark_as_ham, :mark_as_spam, :confirm_classification,
43
- :withdraw,
44
- :before_save_handler, :after_initialize_handler,
45
- :send_notifications, :post_trigger, :report_classification])
40
+ include AASM
46
41
 
47
- def self.paginated(page, per_page)
48
- page(page).per(per_page)
49
- end
42
+ aasm column: :state do
43
+ state :unclassified, initial: true
44
+ state :presumed_ham
45
+ state :presumed_spam
46
+ state :spam, after_enter: [:send_notifications, :report_as_spam]
47
+ state :ham, after_enter: [:send_notifications, :report_as_ham]
50
48
 
51
- def self.comments
52
- Comment.where(published: true).order('created_at DESC')
53
- end
49
+ event :presume_ham do
50
+ transitions from: :unclassified, to: :ham, if: ->() { user_id.present? }
51
+ transitions from: :unclassified, to: :presumed_ham
52
+ end
54
53
 
55
- def self.trackbacks
56
- Trackback.where(published: true).order('created_at DESC')
57
- end
54
+ event :presume_spam do
55
+ transitions from: :unclassified, to: :presumed_spam
56
+ end
58
57
 
59
- def self.from(type, article_id = nil)
60
- if article_id.present?
61
- Article.find(article_id).send("published_#{type}")
62
- else
63
- send(type)
58
+ event :mark_as_ham do
59
+ transitions to: :ham
60
+ end
61
+
62
+ event :mark_as_spam do
63
+ transitions to: :spam
64
+ end
65
+
66
+ event :withdraw do
67
+ transitions from: [:presumed_ham, :ham], to: :spam
64
68
  end
65
69
  end
66
70
 
71
+ def self.paginated(page, per_page)
72
+ page(page).per(per_page)
73
+ end
74
+
67
75
  def parent
68
76
  article
69
77
  end
70
78
 
79
+ def classify_content
80
+ return unless unclassified?
81
+
82
+ case classify
83
+ when :ham then presume_ham
84
+ else presume_spam
85
+ end
86
+ end
87
+
71
88
  def permalink_url(_anchor = :ignored, only_path = false)
72
89
  article.permalink_url("#{self.class.to_s.downcase}-#{id}", only_path)
73
90
  end
@@ -140,25 +157,27 @@ class Feedback < ActiveRecord::Base
140
157
 
141
158
  def change_state!
142
159
  result = ''
143
- if state.spam? || state.presumed_spam?
144
- mark_as_ham
160
+ if spam? || presumed_spam?
161
+ mark_as_ham!
145
162
  result = 'ham'
146
163
  else
147
- mark_as_spam
164
+ mark_as_spam!
148
165
  result = 'spam'
149
166
  end
150
- save!
151
167
  result
152
168
  end
153
169
 
154
- def mark_as_ham!
155
- mark_as_ham
170
+ def confirm_classification!
171
+ confirm_classification
156
172
  save!
157
173
  end
158
174
 
159
- def mark_as_spam!
160
- mark_as_spam
161
- save!
175
+ def confirm_classification
176
+ if presumed_spam?
177
+ mark_as_spam
178
+ elsif presumed_ham?
179
+ mark_as_ham
180
+ end
162
181
  end
163
182
 
164
183
  def report_as_spam
@@ -183,36 +202,39 @@ class Feedback < ActiveRecord::Base
183
202
  end
184
203
  end
185
204
 
186
- def withdraw!
187
- withdraw
188
- save!
205
+ def feedback_not_closed
206
+ errors.add(:article_id, 'Comment are closed') if article.comments_closed?
189
207
  end
190
208
 
191
- def confirm_classification!
192
- confirm_classification
193
- save
209
+ def send_notifications
210
+ nil
194
211
  end
195
212
 
196
- def feedback_not_closed
197
- errors.add(:article_id, 'Comment are closed') if article.comments_closed?
213
+ def published?
214
+ ham? || presumed_ham?
215
+ end
216
+
217
+ def status_confirmed?
218
+ ham? || spam?
219
+ end
220
+
221
+ def spammy?
222
+ spam? || presumed_spam?
198
223
  end
199
224
 
200
225
  delegate :blog, to: :article
201
226
 
202
227
  private
203
228
 
204
- @@akismet = nil
205
-
206
229
  def akismet
207
- @@akismet = akismet_client if @@akismet.nil?
208
- @@akismet == false ? nil : @@akismet
230
+ @akismet ||= akismet_client
209
231
  end
210
232
 
211
233
  def akismet_client
212
- return false if blog.sp_akismet_key.blank?
234
+ return nil if blog.sp_akismet_key.blank?
213
235
  client = Akismet::Client.new(blog.sp_akismet_key, blog.base_url)
214
236
  begin
215
- return client.verify_key ? client : false
237
+ return client.verify_key ? client : nil
216
238
  rescue SocketError
217
239
  nil
218
240
  end
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+
2
3
  class MetaSidebar < Sidebar
3
4
  description "This widget just displays links to Publify main site, this blog's admin and RSS."
4
5
 
data/app/models/note.rb CHANGED
@@ -18,6 +18,9 @@ class Note < Content
18
18
  after_create :set_permalink, :shorten_url
19
19
  before_create :create_guid
20
20
 
21
+ scope :published, lambda {
22
+ where(state: 'published').where('published_at <= ?', Time.zone.now).order(default_order)
23
+ }
21
24
  default_scope { order('published_at DESC') }
22
25
 
23
26
  TWITTER_FTP_URL_LENGTH = 19
@@ -123,6 +126,10 @@ class Note < Content
123
126
  blog.shortener_url.sub(/^https?\:\/\//, '')
124
127
  end
125
128
 
129
+ def published?
130
+ state == 'published'
131
+ end
132
+
126
133
  private
127
134
 
128
135
  def too_long?(message)
data/app/models/page.rb CHANGED
@@ -17,11 +17,7 @@ class Page < Content
17
17
  content_fields :body
18
18
 
19
19
  def self.default_order
20
- 'name ASC'
21
- end
22
-
23
- def self.search_with(search_hash)
24
- super(search_hash).order('title ASC')
20
+ 'title ASC'
25
21
  end
26
22
 
27
23
  def permalink_url(anchor = nil, only_path = false)
@@ -33,4 +29,13 @@ class Page < Content
33
29
  only_path: only_path
34
30
  )
35
31
  end
32
+
33
+ def publish!
34
+ self.state = 'published'
35
+ save!
36
+ end
37
+
38
+ def published?
39
+ state == 'published'
40
+ end
36
41
  end
data/app/models/ping.rb CHANGED
@@ -1,116 +1,3 @@
1
- require 'rexml/document'
2
- require 'xmlrpc/client'
3
-
4
1
  class Ping < ActiveRecord::Base
5
2
  belongs_to :article
6
-
7
- class Pinger
8
- attr_accessor :article
9
- attr_accessor :blog
10
-
11
- def send_pingback_or_trackback
12
- @response = Net::HTTP.get_response(URI.parse(ping.url))
13
- send_pingback or send_trackback
14
- rescue Timeout::Error
15
- Rails.logger.info 'Sending pingback or trackback timed out'
16
- return
17
- rescue => err
18
- Rails.logger.info "Sending pingback or trackback failed with error: #{err}"
19
- end
20
-
21
- def pingback_url
22
- if response['X-Pingback']
23
- response['X-Pingback']
24
- elsif response.body =~ /<link rel="pingback" href="([^"]+)" ?\/?>/
25
- Regexp.last_match[1]
26
- end
27
- end
28
-
29
- attr_reader :origin_url
30
-
31
- attr_reader :response
32
-
33
- attr_reader :ping
34
-
35
- def send_xml_rpc(*args)
36
- ping.send(:send_xml_rpc, *args)
37
- end
38
-
39
- def trackback_url
40
- rdfs = response.body.scan(/<rdf:RDF.*?<\/rdf:RDF>/m)
41
- rdfs.each do |rdf|
42
- xml = REXML::Document.new(rdf)
43
- xml.elements.each('//rdf:Description') do |desc|
44
- if rdfs.size == 1 || desc.attributes['dc:identifier'] == ping.url
45
- return desc.attributes['trackback:ping']
46
- end
47
- end
48
- end
49
- # Didn't find a trackback url, so fall back to the url itself.
50
- @ping.url
51
- end
52
-
53
- def send_pingback
54
- if pingback_url
55
- send_xml_rpc(pingback_url, 'pingback.ping', origin_url, ping.url)
56
- true
57
- else
58
- false
59
- end
60
- end
61
-
62
- def send_trackback
63
- do_send_trackback(trackback_url, origin_url)
64
- end
65
-
66
- def do_send_trackback(trackback_url, origin_url)
67
- trackback_uri = URI.parse(trackback_url)
68
-
69
- post = "title=#{CGI.escape(article.title)}"
70
- post << "&excerpt=#{CGI.escape(article.html(:body).strip_html[0..254])}"
71
- post << "&url=#{origin_url}"
72
- post << "&blog_name=#{CGI.escape(blog.blog_name)}"
73
-
74
- path = trackback_uri.path
75
- path += "?#{trackback_uri.query}" if trackback_uri.query
76
-
77
- Net::HTTP.start(trackback_uri.host, trackback_uri.port) do |http|
78
- http.post(path, post, 'Content-type' => 'application/x-www-form-urlencoded; charset=utf-8')
79
- end
80
- end
81
-
82
- private
83
-
84
- def initialize(origin_url, ping)
85
- @origin_url = origin_url
86
- @ping = ping
87
- # Add this call to text filter cause of a strange thing around text_filter. Need to clean text_filter usage !
88
- ping.article.default_text_filter
89
- ping.article.text_filter
90
- # Make sure these are fetched now for thread safety purposes.
91
- self.article = ping.article
92
- self.blog = article.blog
93
- end
94
- end
95
-
96
- def send_pingback_or_trackback(origin_url)
97
- t = Thread.start(Pinger.new(origin_url, self), &:send_pingback_or_trackback)
98
- t
99
- end
100
-
101
- def send_weblogupdatesping(server_url, origin_url)
102
- t = Thread.start(article.blog.blog_name) do |blog_name|
103
- send_xml_rpc(url, 'weblogUpdates.ping', blog_name, server_url, origin_url)
104
- end
105
- t
106
- end
107
-
108
- protected
109
-
110
- def send_xml_rpc(xml_rpc_url, name, *args)
111
- server = XMLRPC::Client.new2(URI.parse(xml_rpc_url).to_s)
112
- server.call(name, *args)
113
- rescue => e
114
- logger.error(e)
115
- end
116
3
  end
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+
2
3
  class PostType < ActiveRecord::Base
3
4
  validates :name, uniqueness: true
4
5
  validates :name, presence: true
@@ -1,5 +1,5 @@
1
1
  class Redirect < ActiveRecord::Base
2
- belongs_to :contents, optional: true
2
+ belongs_to :contents, optional: true, touch: true
3
3
  belongs_to :blog
4
4
 
5
5
  validates :from_path, uniqueness: true
@@ -3,26 +3,8 @@ require 'carrierwave/orm/activerecord'
3
3
 
4
4
  class Resource < ActiveRecord::Base
5
5
  belongs_to :blog
6
- belongs_to :article, optional: true
6
+ belongs_to :content, optional: true
7
7
 
8
8
  mount_uploader :upload, ResourceUploader
9
- validate :image_mime_type_consistent
10
9
  validates :upload, presence: true
11
-
12
- scope :without_images, -> { where("mime NOT LIKE '%image%'") }
13
- scope :images, -> { where("mime LIKE '%image%'") }
14
- scope :by_filename, -> { order('upload') }
15
- scope :by_created_at, -> { order('created_at DESC') }
16
-
17
- scope :without_images_by_filename, -> { without_images.by_filename }
18
- scope :images_by_created_at, -> { images.by_created_at }
19
-
20
- private
21
-
22
- def image_mime_type_consistent
23
- if upload.content_type =~ %r{^image/}
24
- expected_type = upload.file.send :mime_magic_content_type
25
- errors.add(:upload, 'Has MIME type mismatch') unless upload.content_type == expected_type
26
- end
27
- end
28
10
  end
@@ -125,7 +125,7 @@ class Sidebar < ActiveRecord::Base
125
125
 
126
126
  def to_locals_hash
127
127
  fields.reduce(sidebar: self) do |hash, field|
128
- hash.merge(field.key => config[field.key])
128
+ hash.merge(field.key => field.current_value(self))
129
129
  end
130
130
  end
131
131
 
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+
2
3
  class StaticSidebar < Sidebar
3
4
  DEFAULT_TEXT = '
4
5
  <ul>
data/app/models/tag.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  class Tag < ActiveRecord::Base
2
2
  belongs_to :blog
3
- has_and_belongs_to_many :articles, order: 'created_at DESC', join_table: 'articles_tags'
3
+ has_and_belongs_to_many :contents, order: 'created_at DESC'
4
4
 
5
5
  validates :name, uniqueness: { scope: :blog_id }
6
6
  validates :blog, presence: true
@@ -30,15 +30,15 @@ class Tag < ActiveRecord::Base
30
30
 
31
31
  def ensure_naming_conventions
32
32
  self.display_name = name if display_name.blank?
33
- self.name = display_name.to_url unless display_name.blank?
33
+ self.name = display_name.to_url if display_name.present?
34
34
  end
35
35
 
36
- def self.find_all_with_article_counters
37
- Tag.joins(:articles).
38
- where(contents: { published: true }).
39
- select(*Tag.column_names, 'COUNT(articles_tags.article_id) as article_counter').
36
+ def self.find_all_with_content_counters
37
+ Tag.joins(:contents).
38
+ where(contents: { state: 'published' }).
39
+ select(*Tag.column_names, 'COUNT(contents_tags.content_id) as content_counter').
40
40
  group(*Tag.column_names).
41
- order('article_counter DESC').limit(1000)
41
+ order('content_counter DESC').limit(1000)
42
42
  end
43
43
 
44
44
  def self.find_with_char(char)
@@ -49,14 +49,18 @@ class Tag < ActiveRecord::Base
49
49
  tags.map(&:display_name).sort.map { |name| name =~ / / ? "\"#{name}\"" : name }.join ', '
50
50
  end
51
51
 
52
- def published_articles
53
- articles.already_published
52
+ def published_contents
53
+ contents.published
54
54
  end
55
55
 
56
56
  def permalink
57
57
  name
58
58
  end
59
59
 
60
+ def feed_url(format)
61
+ "#{permalink_url}.#{format.gsub(/\d/, '')}"
62
+ end
63
+
60
64
  def permalink_url(_anchor = nil, only_path = false)
61
65
  blog.url_for(controller: 'tags', action: 'show', id: permalink, only_path: only_path)
62
66
  end