| Class | Logi |
| In: |
app/models/logi.rb
|
| Parent: | ActiveRecord::Base |
Logis are the articles within LogiLogi. Logis are short in size (preferably max 3 normal book-pages) and they should focus on one idea, and make only one point or tag clear. Trains of thought that are more complex should be dissected into separate Logis and be globally described in a single Logi that links to the others giving increased levels of detail. Of course it is also possible to first start with the more general level, and to extend it in- depth as needed.
The central reasons for this are:
Logis an LogiVersions work in concert. The text_stack of a Logi is filtered by LogiVersions to only show the contents that remain in that LogiVersion. After editing a Logi, the additions are appended to the text_stack of the Logi, and the character-ranges are added to the position_ranges of the LogiVersion. Likewise if something is removed in a newer version, only the position_ranges are removed, not the text_stack.
This allows the position_ranges of Links and Authorships to remain the same between LogiVersions.
Creates a Logi from a logi_hash.
A logi_hash can contain the following elements: :logi_id => <the id of the existing Logi>
# File app/models/logi.rb, line 170
170: def self.from_h(logi_hash)
171: if logi_hash[:perma_id].nil?
172: raise HashError.new(logi_hash), t('m.logi.error_invalid_hash')
173: end
174: logi = Logi.find_by_perma_id(logi_hash[:perma_id])
175: if logi.nil?
176: raise ExistenceError.new(logi_hash), t('m.logi.error_nonexisting')
177: end
178: return logi
179: end
Parses a Logi from a string
See hash_from_s for the syntax.
# File app/models/logi.rb, line 144
144: def self.from_s(logi_string)
145: return Logi.from_h(Logi.hash_from_s(logi_string))
146: end
Creates a logi_hash from a logi_string.
The syntax is as follows:
An example:
# File app/models/logi.rb, line 156
156: def self.hash_from_s(logi_string)
157: if logi_string !~ Const::Logi::CHECK_LOGI_RE
158: raise ParsingError.new(logi_string), t('m.logi.error_wrong_spec')
159: end
160: logi_string =~ Const::Logi::MATCH_LOGI_RE
161: match = $~
162: return {:perma_id => match[1]}
163: end
Getters
# File app/models/logi.rb, line 132
132: def self.main_page
133: link = Link.new_from_s(GlobalConfig.main_page_tag.to_s)
134: link.resolve
135: return link.volatile_to_logi
136: end
Shortcut for creation.
Options:
Returns the new Logi.
# File app/models/logi.rb, line 196
196: def self.new_with(options = {})
197: options[:restriction] ||= options[:user_group].default_restriction
198: logi = Logi.new(:creator => options[:creator],
199: :user_group => options[:user_group],
200: :restriction => options[:restriction],
201: :kind => options[:kind])
202: logi.logi_versions.build(:logi => logi,
203: :title => options[:title], :body => options[:body],
204: :text => options[:text], :editor => options[:creator])
205: return logi
206: end
Changes
# File app/models/logi.rb, line 210
210: def self.paginate_recent_changes(options)
211: paginate_by_sql('SELECT DISTINCT l.* FROM logis AS l,' +
212: ' (SELECT logi_id, MAX(created_at) AS created_at' +
213: ' FROM logi_versions GROUP BY logi_id ) AS v' +
214: ' WHERE l.id = v.logi_id ORDER BY v.created_at DESC', options)
215: end
Adds the links at the positions given by the link_p_r_list.
(links themselves should be set as the link attribute of the PositionRanges in the list).
NOTE: That no checking is done for overlap and the like.
# File app/models/logi.rb, line 402
402: def add_links_to_position_ranges(link_p_r_list)
403: link_p_r_list.each do |link_p_r|
404: if self.from_links.detect {|li| link_p_r.link.eql?(li)} # eql? uses <=>
405: link = self.from_links.detect {|li| li.eql?(link_p_r.link)}
406: link_p_r.link = link
407: link.position_ranges << link_p_r
408: link.save
409: else
410: link = link_p_r.link
411: link.position_ranges << link_p_r
412: self.from_links << link
413: end
414: end
415: end
Returns true if the given user has admin-rights for this Logi.
# File app/models/logi.rb, line 263
263: def admin_rights?(user)
264: if (self.creator.anonymous? or user == self.creator or
265: self.user_group.admin_permissions?(user))
266: return true
267: else
268: return false
269: end
270: end
For the Search-index, returns the creator string.
# File app/models/logi.rb, line 607
607: def creator_for_index
608: self.creator.name
609: end
For the Search-index, returns the html of the current logi_version.
# File app/models/logi.rb, line 633
633: def current_body_for_index
634: self.current_logi_version.body
635: end
For the Search-index, returns the editor string of the current logi_version.
# File app/models/logi.rb, line 613
613: def current_editor_for_index
614: self.current_logi_version.editor.name
615: end
Returns a smaller version of the current snippet.
# File app/models/logi.rb, line 336
336: def current_tiny_snippet
337: return LogiVersion.chop_body(self.current_snippet, 150)
338: end
For the Search-index, returns the title string of the current logi_version.
# File app/models/logi.rb, line 627
627: def current_title_for_index
628: self.current_logi_version.title
629: end
Returns true if the given user has edit-rights for this Logi.
# File app/models/logi.rb, line 274
274: def edit_rights?(user)
275: if (self.restriction != Const::Logi::EDIT or
276: user == self.creator or
277: self.user_group.member?(user) or
278: user.admin?)
279: return true
280: else
281: return false
282: end
283: end
Returns true if the logi is of a home-page kind.
# File app/models/logi.rb, line 307
307: def home_page?
308: return (self.user_home_page? or
309: self.user_group_home_page? or self.peer_group_home_page?)
310: end
Returns all things that are inserted in this logi.
# File app/models/logi.rb, line 342
342: def inserts
343: return self.annotations + self.from_links + self.external_links
344: end
Returns true if the given version is different from the current logi version.
# File app/models/logi.rb, line 328
328: def logi_version_different?(logi_version)
329: current = self.current_logi_version
330: return (current.title != logi_version.title or
331: current.body != logi_version.body)
332: end
Returns true if it‘s a presentable logi, which means it‘s not a sandbox-logi.
# File app/models/logi.rb, line 321
321: def presentable?
322: self.tags.size != 1 or (self.tags.first != Tag.sandbox)
323: end
Returns the previous logi_version (can be the one currently saved in the db, as opposed to the one being constructed).
# File app/models/logi.rb, line 251
251: def previous_logi_version
252: return self.logi_versions.before_last
253: end
Returns the rating this logi received for the provided peer_group.
# File app/models/logi.rb, line 233
233: def rating_for(peer_group)
234: rating = self.ratings.find_by_peer_group_id(peer_group)
235: if rating.nil?
236: rating = self.ratings.build(:peer_group => peer_group)
237: end
238: return rating
239: end
Removes the links at the positions given by the link_p_r_list
(links themselves should be set as the link attribute of the PositionRanges in the list).
# File app/models/logi.rb, line 383
383: def remove_links_from_position_ranges(link_p_r_list)
384: link_p_r_list.each do |link_p_r|
385: link = self.from_links.detect {|link| link == link_p_r.link}
386: link.position_ranges.delete!(link_p_r)
387: if link.position_ranges.empty?
388: self.from_links.delete(link)
389: else
390: link.save
391: end
392: end
393: end
Maintenance
# File app/models/logi.rb, line 436
436: def roll_back_version
437: self.current_logi_version.destroy
438: pos = self.text_stack.rindex(DiffLCS::WordSplitArray::SEPARATOR)
439: self.text_stack = self.text_stack[0...pos]
440: self.save
441: end
For the Search-Index, returns a string with all the tags
# File app/models/logi.rb, line 619
619: def tags_for_index
620: self.tags.collect {|t|
621: t.to_s(:for => :show) + (t.to_s(:for => :show) != t.to_s ? ' ' + t.to_s : '')
622: }.join(' ')
623: end
Parses a Logi to a string.
Options
# File app/models/logi.rb, line 424
424: def to_s(options = {})
425: if options[:for] == :show
426: return self.creator.name
427: elsif options[:for] == :full_show
428: return self.creator.name + ', logi ' + self.perma_id.split('_').last
429: else
430: return '=' + self.perma_id
431: end
432: end
Removes all tags and makes this an untagged logi.
# File app/models/logi.rb, line 374
374: def untag
375: self.tags = [Tag.untagged]
376: end
Returns true if the logi is tagless.
# File app/models/logi.rb, line 314
314: def untagged?
315: return (self.tags.size == 1 and self.tags.first == Tag.untagged)
316: end
Saves the given new logi_version if it changed.
Saves only the logi if it‘s tags changed.
Note that validation of both the logi and the logi version has to be done before calling this method.
# File app/models/logi.rb, line 355
355: def update_if_changed(logi_version)
356: if self.logi_version_different?(logi_version)
357: self.logi_versions << logi_version
358: self.save
359: elsif self.tags_strings_before_validation and self.tags_string_changed?
360: self.save
361: end
362: end
Initializes the tags_strings.
# File app/models/logi.rb, line 449
449: def after_initialize
450: self.reset_methods_cache # see CacheMethodsModule
451: self.tags_strings_after_initialize # See TagsStringsModule
452: if self.kind.nil?
453: self.kind = Const::Logi::KINDS[:normal]
454: end
455: return true
456: end
Logs creation to log.logilogi.org
# File app/models/logi.rb, line 501
501: def log_create_to_log_log
502: if GlobalConfig.use_log_log and !self.home_page?
503: m = LogLogMessage.new(
504: :kind => "Logi",
505: :channel_names => ['all','logis',
506: 'by_' + self.creator.unix_name].join(','),
507: :title => self.current_title,
508: :author => self.creator.name,
509: :text => self.current_snippet,
510: :url => GlobalConfig.site_url + self.link.to_s)
511: m.save
512: end
513: end
Logs save & change to log.logilogi.org
# File app/models/logi.rb, line 517
517: def log_save_to_log_log
518: if GlobalConfig.use_log_log
519: if self.text_stack_changed?
520: if self.current_logi_version.nr == 1
521: change = "Create"
522: else
523: change = "Edit"
524: end
525: elsif self.tags_string_changed?
526: change = "Tagging"
527: else
528: change = nil
529: end
530: if change
531: m = LogLogMessage.new(
532: :kind => change,
533: :channel_name => 'changes',
534: :author => self.creator.name,
535: :title => self.current_title,
536: :text => 'Current version: ' + self.current_logi_version.nr.to_s,
537: :url => GlobalConfig.site_url + self.link.to_s)
538: m.save
539: end
540: end
541: end
Sets the perma_id to the creator-user + the next perma-nr for that user…
# File app/models/logi.rb, line 461
461: def set_perma_id
462: creator = self.creator
463: self.perma_id = self.creator.home_page_tag.to_s + '_' +
464: creator.next_logi_nr.to_s
465: creator.increment!(:next_logi_nr)
466: return true
467: end
Sets re_resolve to true on links that matched this logi.
# File app/models/logi.rb, line 545
545: def set_re_resolve_on_matchless_links
546: self.link_matches.each do |l_m|
547: link = l_m.link
548: # zero already (just) before_destroy
549: if link.link_matches.size == 0 or !link.to_logi.nil?
550: link.re_resolve = true
551: link.save
552: end
553: end
554: return true
555: end
Sets re_resolve to true on to_logi links.
# File app/models/logi.rb, line 490
490: def set_re_resolve_on_to_links
491: if self.tags_string_changed?
492: self.to_links.each do |link|
493: link.re_resolve = true
494: link.save
495: end
496: end
497: end
Stores the tags as used tags.
# File app/models/logi.rb, line 471
471: def use_or_release_tags
472: if self.tags_string_changed?
473: if !self.tags_string_was.nil?
474: old_tags = self.tags_string_was.split('/').collect {|s|
475: Tag.from_s(s)}
476:
477: old_tags.each do |t|
478: UsedTag.release(t)
479: end
480: end
481: self.tags.each do |t|
482: UsedTag.use(t)
483: end
484: end
485: return true
486: end
Validates presence of tags and non-overlap with user page.
# File app/models/logi.rb, line 575
575: def validate
576: # size
577: if GlobalConfig.done_with_basics?
578: if self.text_stack.size > GlobalConfig.maximum_logi_size
579: self.errors.add(:changes_history, t('m.logi.error_too_long',
580: :max => GlobalConfig.maximum_logi_size))
581: end
582: end
583: # tags
584: if self.tags.include?(Tag.replace)
585: self.errors.add(:link, t('m.logi.error_link_should_not_include') + ' ' +
586: Tag.replace.to_s)
587: end
588: if self.tags.empty?
589: self.errors.add(:link, t('m.logi.error_is_empty'))
590: end
591: if self.tags_string_changed?
592: if self.home_page? and !self.new_record?
593: self.errors.add(:tags, t('m.logi.error_cannot_change'))
594: end
595: if !self.home_page? and self.link.to_home_page?
596: self.errors.add(:tags, t('m.logi.error_cannot_contend'))
597: end
598: end
599: end