Class: Mist::Post
Constant Summary
collapse
- TAG_DELIM =
/\s*,\s*/
Class Method Summary
collapse
Instance Method Summary
collapse
Methods included from Permalink
#permalink
Methods inherited from GitModel
#==, #attributes, #class_name, #commit, #commit_message, #default_attributes!, #destroy, #initialize, #inspect, #new_record?, #path, #path_was, #persisted?, #save, #save!, #save_record_file, #update_attributes
#[], #add_attribute_default, #add_attribute_getter, #add_attribute_setter, #all, #attribute, #count, #create!, #exist?, extended, #find, #inherited, #last, #load, #meta_file_path, #record_path, #save_meta_data, #table_name, #timestamps
Constructor Details
This class inherits a constructor from Mist::GitModel
Class Method Details
.all_by_publication_date ⇒ Object
53
54
55
56
|
# File 'app/models/mist/post.rb', line 53
def self.all_by_publication_date
load_existing_with_attribute :published_at, self[:published_at].sort { |a, b| -(a[1] <=> b[1]) }
end
|
.increase_popularity(post) ⇒ Object
37
38
39
40
41
|
# File 'app/models/mist/post.rb', line 37
def self.increase_popularity(post)
self[:popular_posts][post.id] = popularity_for(post.id) + 1
save_meta_data :popular_posts
post.popularity = self[:popular_posts][post.id]
end
|
.load_existing_with_attribute(attribute_name, array) ⇒ Object
28
29
30
|
# File 'app/models/mist/post.rb', line 28
def self.load_existing_with_attribute(attribute_name, array)
array.collect { |(post_id, attribute_value)| find post_id, attribute_name => attribute_value }.reject { |i| i.nil? }
end
|
58
59
60
61
62
|
# File 'app/models/mist/post.rb', line 58
def self.matching_tags(tags)
return [] if tags.blank?
matches = self[:tags].inject({}) { |h,(k,v)| ((t = v.split(TAG_DELIM)) & tags).size > 0 ? h[k] = t : nil; h }
load_existing_with_attribute :tags, matches.sort { |a, b| -((a[1] & tags).size <=> (b[1] & tags).size) }
end
|
.most_popular(count) ⇒ Object
32
33
34
35
|
# File 'app/models/mist/post.rb', line 32
def self.most_popular(count)
load_existing_with_attribute :popularity, self[:popular_posts].sort { |a, b| -(a[1].to_i <=> b[1].to_i) }
end
|
.popularity_for(post_id) ⇒ Object
43
44
45
|
# File 'app/models/mist/post.rb', line 43
def self.popularity_for(post_id)
self[:popular_posts][post_id] || 0
end
|
.recently_published(count) ⇒ Object
47
48
49
50
51
|
# File 'app/models/mist/post.rb', line 47
def self.recently_published(count)
all_by_publication_date.tap do |result|
result.pop while result.length > count
end
end
|
Instance Method Details
#content=(c) ⇒ Object
128
129
130
|
# File 'app/models/mist/post.rb', line 128
def content=(c)
attributes[:content] = c.gsub(/\r/, "")
end
|
#content_as_html ⇒ Object
155
156
157
|
# File 'app/models/mist/post.rb', line 155
def content_as_html
GitHub::Markup.render("#{title}.markdown", content_with_embedded_gists).html_safe
end
|
#content_as_html_preview ⇒ Object
159
160
161
162
163
164
|
# File 'app/models/mist/post.rb', line 159
def content_as_html_preview
first_paragraph = /\A(.+?)(\n\n|\n |\z)/m.match(content.gsub(/\r/, ''))
GitHub::Markup.render("#{title}.markdown", first_paragraph[1]).html_safe
end
|
#content_with_embedded_gists ⇒ Object
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
|
# File 'app/models/mist/post.rb', line 166
def content_with_embedded_gists
return content.dup if gist_id.blank?
template = '<script src="https://gist.github.com/__ID__.js?file=__FILENAME__"></script>'
template['__ID__'] = gist_id.to_s
content.dup.tap do |result|
code_examples.reverse.each do |example|
result[example.offset] = template.sub(/__FILENAME__/, example.filename) + "\n"
end
end
end
|
#destroy_gist ⇒ Object
237
238
239
|
# File 'app/models/mist/post.rb', line 237
def destroy_gist
gist.destroy if gist && gist.persisted?
end
|
#draft? ⇒ Boolean
112
113
114
|
# File 'app/models/mist/post.rb', line 112
def draft?
!published?
end
|
#generated_gist_description ⇒ Object
132
133
134
|
# File 'app/models/mist/post.rb', line 132
def generated_gist_description
'Code examples for "%s" - %s' % [title, url]
end
|
#gist ⇒ Object
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
# File 'app/models/mist/post.rb', line 136
def gist
@gist ||= begin
if gist_id.blank?
if has_code_examples?
ActiveGist.new(:description => generated_gist_description, :public => true)
else
nil
end
else
begin
ActiveGist.find(gist_id)
rescue RestClient::ResourceNotFound
self.gist_id = nil
nil
end
end
end
end
|
#has_code_examples? ⇒ Boolean
183
184
185
|
# File 'app/models/mist/post.rb', line 183
def has_code_examples?
code_examples.length > 0
end
|
#load_code_examples_from_gist ⇒ Object
191
192
193
194
195
196
197
198
199
200
201
202
203
|
# File 'app/models/mist/post.rb', line 191
def load_code_examples_from_gist
if gist && gist.persisted?
self.content = self.content.dup.tap do |result|
code_examples.reverse.each do |example|
if gist.files[example.filename]
lines = gist.files[example.filename][:content].split("\n")
lines.unshift " file: #{example.filename}"
result[example.offset] = lines.join("\n ") + "\n"
end
end
end
end
end
|
#publish ⇒ Object
116
117
118
|
# File 'app/models/mist/post.rb', line 116
def publish
self.published_at = Time.now unless published?
end
|
#published=(bool) ⇒ Object
124
125
126
|
# File 'app/models/mist/post.rb', line 124
def published=(bool)
bool ? publish : unpublish
end
|
#published? ⇒ Boolean
108
109
110
|
# File 'app/models/mist/post.rb', line 108
def published?
!published_at.blank?
end
|
#set_gist_data ⇒ Object
Assigns the file contents of each file in the gist according to what’s found in #content. Does not save the gist. Returns the list of files themselves.
207
208
209
210
211
212
213
214
|
# File 'app/models/mist/post.rb', line 207
def set_gist_data
gist.description = generated_gist_description
gist.files.keys.each { |filename| gist.files[filename] = nil }
code_examples.each do |example|
gist.files[example.filename] = { :content => example }
end
gist.files
end
|
#similar_posts(max_count = nil) ⇒ Object
64
65
66
67
68
69
70
71
|
# File 'app/models/mist/post.rb', line 64
def similar_posts(max_count = nil)
self.class.matching_tags(tags).tap do |matching|
matching.delete self while max_count && matching.length > max_count
matching.pop
end
end
end
|
73
74
75
76
77
78
79
|
# File 'app/models/mist/post.rb', line 73
def tags=(t)
if t.kind_of?(String)
attributes[:tags] = t.split(TAG_DELIM)
else
attributes[:tags] = t
end
end
|
#title=(value) ⇒ Object
104
105
106
|
# File 'app/models/mist/post.rb', line 104
def title=(value)
attributes[:title] = value
end
|
#unpublish ⇒ Object
120
121
122
|
# File 'app/models/mist/post.rb', line 120
def unpublish
self.published_at = nil
end
|
#update_gist_if_necessary ⇒ Object
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
|
# File 'app/models/mist/post.rb', line 220
def update_gist_if_necessary
return unless errors.empty?
if has_code_examples?
set_gist_data
if gist.changed?
errors.add(:gist, "could not be saved: #{gist.errors.full_messages.join('; ')}") unless gist.save
end
self.gist_id = gist.id
else
gist.destroy if gist && gist.persisted?
end
end
|
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
# File 'app/models/mist/post.rb', line 81
def update_meta
if popularity_changed? || new_record?
self.class[:popular_posts][id] = popularity
self.class.save_meta_data :popular_posts
end
if published_at_changed?
if published_at.blank?
self.class[:published_at].delete id
else
self.class[:published_at][id] = published_at
end
self.class.save_meta_data :published_at
end
if tags && !tags.empty?
self.class[:tags][id] = tags.join(', ')
else
self.class[:tags].delete id
end
self.class.save_meta_data :tags
end
|
#url(options = {}) ⇒ Object
216
217
218
|
# File 'app/models/mist/post.rb', line 216
def url(options = {})
Mist::Engine.routes.url_helpers.post_path(id, options.reverse_merge(:only_path => false).reverse_merge(Rails.application.default_url_options))
end
|