Class Link
In: app/models/link.rb
Parent: ActiveRecord::Base

The Philosophy of Links

Links play a central role in LogiLogi, and Links in LogiLogi are not like ordinary html-links on the web or X(ML)-Links of the everlasting soon, tomorrow…

HTML-links are limited in that they are one-way only, and always controlled by the owner and editor of the document they originate from. They are embedded in the text. Also they cannot be of different precisions or stances (like ‘supports’ or ‘questions’).

Why no X-Links

XML- or X-links are too complicated for any practical use eventhough they are not limited to one-way links, and editor-control. For prospective users XML works a bit like a knot of wool on a kitten… It begins with fun and promises, joyfull play begins, slows down, and irritated entanglement in over-complexity is the end.

Besides this another limit - that XML and HTML links share - is that they always have to point to a definite and static location, while links in LogiLogi can adapt to the growth of the system. A link to Aristotle from /History/Medieval/Philosophers First linking to Aristotle, later as the target page is added to /History/Aristotle, and ultimately to /History/Medieval/Aristotle…

Two-legged links: Requested and Received

Links are kept separately from the text (Logi) in which they appear. So links are not stored within Logis. They are kept as separate Link-Objects.

These Link-Objects have associated bundles of Tags

Links have two legs.

The they are the requested and received tags (to allow a request for /History/Medieval/Aristotle to be temporarily satisfied with /Aristotle).

Different precisions of Links

There are several different kinds of precisions possible.

Links precisions can be of the kind:

  • TAG - Links for which all LinkTags are disambiguated to Tags
  • LOGI - Links that link directly to a Logi
  • LOGI_VERSION - Links that link to a specific LogiVersion

TAG-links are the most general real link-kind. They do not point to a specific document, but are much like a query. LOGI and LOGI_VERSION are more suited for textual commentaries. For example for discussing canonical texts like the works of Kant, Version 3 of the General Public License, or the Bible.

Links with a stance

Links can have different ‘stance‘s like :reference, :question or :critique.

These are usefull for quickly expressing what role the link has in the discourse, and will be especially usefull if there are many links.

Methods

Included Modules

CacheMethodsModule TagsStringsModule ConstantNamedScopesModule

Attributes

position_ranges  [RW]  see TagsStringsModule, for both requested_tags and received_tags, etc…

Public Class methods

Sub-function of Link.from_s.

Takes care of spec strings

[Source]

     # File app/models/link.rb, line 236
236:   def self.extra_specs_hash_from_s(matching_specs_string)
237:     if matching_specs_string !~ Const::Link::CHECK_EXTRA_SPECS_RE
238:       raise ParsingError.new(matching_specs_string), t('m.link.error_invalid_specs')
239:     end
240:     extra_specs_hash = Hash.new
241:     specs = matching_specs_string.scan(Const::Link::SCAN_EXTRA_SPECS_RE).flatten!
242:     specs.each {|spec|
243:       case spec
244:       when Const::Link::RECOGNIZE_SPEC_STANCE_RE
245:         extra_specs_hash[:stance] = Const::Link::STANCES[spec.split('=').last.to_sym]
246:       end
247:     }
248:     return extra_specs_hash
249:   end

Returns all the link-ids that need re-resolving

[Source]

     # File app/models/link.rb, line 255
255:   def self.get_re_resolves
256:     re_resolves = []
257:     while link = Link.find_by_re_resolve(true)
258:       link.re_resolve = false
259:       link.save
260:       re_resolves << link
261:     end
262:     return re_resolves.uniq
263:   end

Parses a link_hash from a link_string

The syntax is as follows: <tag>(/<tag>)*(<logi>(<logi_version>)?)?(<spec suffix>)?

Plus optionally a preceding url which will be stripped.

with: <tag> = ([\w._-])+ <logi> = =<logi_perma_id> <logi_version> = =v<logi version nr> <spec suffix> = \$stance=<stance>

Examples: en.so.logilogi.org/Foucault Foucault=John_Johnson_2=v1 Economics/Foucault/Non_Existing_Word/Botanics

[Source]

     # File app/models/link.rb, line 158
158:   def self.hash_from_s(link_string)
159:     if link_string.empty?
160:       raise ParsingError.new(link_string), t('m.link.error_invalid_string')
161:     end
162:     if GlobalConfig.done_with_basics?
163:      if link_string =~ /\/\//
164:         link_string.gsub!(/^.*?\/\/[^\/]+\//,"")
165:       end
166:     end
167:     link_string =~ Const::Link::DISSECT_LINK_RE
168:     match = $~
169:     if match.nil?
170:       raise ParsingError.new(link_string), t('m.link.error_invalid_string')
171:     end
172:     link_hash = Hash.new
173:     if match[1]
174:       link_hash[:requested_tags] = Tag.array_from_s(match[1])
175:     end
176:     if match[2] # requested-logi-and-version
177:       link_hash.merge!(Link.requested_logi_and_version_hash_from_s(match[2]))
178:     end
179:     if match[3] # extra specifications
180:       link_hash.merge!(Link.extra_specs_hash_from_s(match[3]))
181:     end
182:     return link_hash
183:   end

Creates a new link from a hash

Arguments:

  • link_hash = the link_hash

[Source]

     # File app/models/link.rb, line 190
190:   def self.new_from_h(link_hash)
191:     navs_array = link_hash[:navs_array]
192:     if link_hash[:requested_tags].nil? and link_hash[:to_logi_perma_id].nil?
193:       raise HashError.new(link_hash), t('m.link.error_hash_without')
194:     end
195:     if link_hash[:to_logi_perma_id]
196:       to_logi = Logi.from_h(:perma_id => link_hash[:to_logi_perma_id])
197:     end
198:     if link_hash[:to_logi_version_nr]
199:       to_logi_version_nr = LogiVersion.from_h(to_logi,
200:           :logi_version_nr => link_hash[:to_logi_version_nr]).nr
201:     end
202:     link = Link.new(:requested_tags => link_hash[:requested_tags],
203:           :to_logi => to_logi,
204:           :to_logi_version_nr => to_logi_version_nr,
205:           :stance => link_hash[:stance]
206:         )
207:     return link
208:   end

Parses a Link from a string

See hash_from_s for the syntax

[Source]

     # File app/models/link.rb, line 130
130:   def self.new_from_s(link_string)
131:     begin
132:       return Link.new_from_h(Link.hash_from_s(link_string))
133:     rescue => error
134:       l = Link.new
135:       l.errors.add_to_base(error.message)
136:       return l
137:     end
138:   end

Sub-function of Link.from_s.

Handles Logi and LogiVersion strings.

[Source]

     # File app/models/link.rb, line 214
214:   def self.requested_logi_and_version_hash_from_s(matching_logi_and_version_string)
215:     requested_logi_and_version_hash = Hash.new
216:     if matching_logi_and_version_string !~ Const::Link::CHECK_REQUESTED_LOGI_AND_VERSION_RE
217:       raise ParsingError.new(matching_logi_and_version_string), t('m.link.error_version_malformed')
218:     end
219:     matching_logi_and_version_string =~ Const::Link::MATCH_REQUESTED_LOGI_AND_VERSION_RE
220:     match = $~
221:     if match[1]
222:       logi_hash = Logi.hash_from_s(match[1])
223:       requested_logi_and_version_hash[:to_logi_perma_id] = logi_hash[:perma_id]
224:     end
225:     if match[2] # LogiVersion::BLOCK_LOGI_VERSION
226:       logi_version_hash = LogiVersion.hash_from_s(match[2])
227:       requested_logi_and_version_hash[:to_logi_version_nr] = logi_version_hash[:logi_version_nr]
228:     end
229:     return requested_logi_and_version_hash
230:   end

Re-resolves all the given links

[Source]

     # File app/models/link.rb, line 267
267:   def self.run_re_resolves(re_resolves)
268:     for r_l in re_resolves
269:       link = Link.find_by_id(r_l)
270:       if link
271:         link.resolve
272:         link.save
273:       end
274:     end
275:   end

Public Instance methods

Compares links alphabetically, by tag and link-precision (precise to vague).

Options:

  • direction = the direction: :requested, :received, defaults to :requested

[Source]

     # File app/models/link.rb, line 348
348:   def <=>(other, options = {})
349:     options[:direction] ||= :requested
350:     self_tags, other_tags = \
351:         case options[:direction]
352:         when :requested
353:           [self.requested_tags, other.requested_tags]
354:         when :received
355:           [self.received_tags, other.received_tags]
356:         end
357:     comparison = 0
358:     i = 0
359:     while self_tags[i] and other_tags[i] do
360:       comparison = self_tags[i] <=> other_tags[i]
361:       if comparison != 0
362:         return comparison
363:       end
364:       i += 1
365:     end
366:     # the same size and equal link-parts or size-difference
367:     comparison = self_tags.size <=> other_tags.size
368:     if comparison != 0
369:       # size-difference, done!
370:       return comparison
371:     end
372:     # the link-precision must make the difference now
373:     if self.to_logi and other.to_logi
374:       if self.to_logi_version_nr and !other.to_logi_version_nr
375:         return 1
376:       elsif !self.to_logi_version_nr and other.to_logi_version_nr
377:         return -1
378:       end
379:     elsif self.to_logi
380:       return 1
381:     elsif other.to_logi
382:       return -1
383:     end
384:     return 0
385:   end

[Source]

     # File app/models/link.rb, line 387
387:   def eql?(other)
388:     self.hash == other.hash
389:   end

Returns true if a match was found for requested tags in their given order.

[Source]

     # File app/models/link.rb, line 321
321:   def exact_match?
322:     return (self.unreduced_match? and 
323:         self.volatile_to_logi.tags == self.received_tags)
324:   end

Returns true if there are matches.

[Source]

     # File app/models/link.rb, line 305
305:   def found_logi?
306:     return !self.link_matches.empty?
307:   end

[Source]

     # File app/models/link.rb, line 391
391:   def hash
392:     return self.to_s.hash
393:   end

Returns all matching logis.

Unsorted.

[Source]

     # File app/models/link.rb, line 518
518:   def matching_logis
519:     return self.link_matches.collect {|m| m.logi}
520:   end

Dups into a new Link.

LinkTags and to_logi & to_logi_version_nr-stuff is copied.

[Source]

     # File app/models/link.rb, line 528
528:   def new_record_dup
529:     link = Link.new(:requested_tags => self.requested_tags.dup,
530:         :received_tags => self.received_tags.dup,
531:         :to_logi => self.to_logi,
532:         :to_logi_version_nr => self.to_logi_version_nr)
533:     link.link_matches = self.link_matches.dup
534:     return link
535:   end

Also called when adding links.

[Source]

     # File app/models/link.rb, line 986
986:   def quick_validate
987:     if self.from_logi == self.to_logi
988:       self.errors.add(:to_logi, t('defaults.error_cannot_point'))
989:     end
990:   end

Resolves the link into the before-save state.

Will try less tags when no match is found and at each step-level look for logis with the tags in the links exact order first.

When the links to_logi is set, it will use the tags of the logi.

Options: (only meaningfull for tag-links, that is without to_logi)

  • :force => true if you want a match for all requested_tags
        in exactly the same order.
    

The value of exact_match? is unpredictable when called with :match => :all_tags

[Source]

     # File app/models/link.rb, line 411
411:   def resolve(options = {})
412:     self.reset_methods_cache([:requested_tags, :received_tags])
413:     self.received_tags.clear
414:     self.link_matches.clear
415:     if !self.to_logi
416:       # resolve tag-link
417:       if options[:force].nil?
418:         # step down untill a match is found, exact or not.
419:         self.resolve_matches_and_tags_for_requested_tags
420:       else
421:         # if forced to do a certain match for all tags, go for it.
422:         self.resolve_matches_for_all_requested_tags
423:       end
424:     else
425:       # resolve to-logi-link
426:       if options[:force].nil?
427:         # resolve logi-link
428:         self.resolve_tags_for_to_logi
429:       else
430:         # simply set received tags
431:         self.receive_tags_for_to_logi
432:       end
433:     end
434:     return self
435:   end

Returns true if this link is resolved.

[Source]

     # File app/models/link.rb, line 299
299:   def resolved?
300:     return !self.received_tags.empty?
301:   end

Returns the number of link-parts the link has for the given direction.

  • direction = the direction: :requested, :received

[Source]

     # File app/models/link.rb, line 286
286:   def size(direction)
287:     case direction
288:     when :requested
289:       return self.requested_tags.size
290:     when :received
291:       return self.received_tags.size
292:     else
293:       raise StandardError.new, t('m.link.error_wrong_direction')
294:     end
295:   end

Acts_as index feeding

[Source]

      # File app/models/link.rb, line 994
 994:   def tag_sets_for_term_index
 995:     rec_tags = self.received_tags.dup
 996:     not_rec_req_tags = self.requested_tags.dup
 997:     rec_tags.each do |r_t|
 998:       not_rec_req_tags.delete(r_t)
 999:     end
1000:     tag_sets = [rec_tags]
1001:     not_rec_req_tags.each do |n_r_r_t|
1002:       rec_tags = rec_tags.dup
1003:       rec_tags.push(n_r_r_t)
1004:       tag_sets << rec_tags
1005:     end
1006:     tag_sets_string = ''
1007:     tag_sets.collect {|t_s| t_s.sort}.each do |t_s|
1008:       tag_sets_string += '__' + t_s.collect {|t| t.to_s}.join('__').downcase + '__ '
1009:     end
1010:     return tag_sets_string[0...-1]
1011:   end

Returns true if this link is to a homepage.

Options:

  • direction = the direction: :requested, :received, defaults to :received

[Source]

     # File app/models/link.rb, line 332
332:   def to_home_page?(options = {})
333:     options[:direction] ||= :received
334:     tags = self.get_tags_in_direction(options[:direction])
335:     return false if tags.size != 2
336:     return tags[1].home_page?
337:   end

Turns the Link into a string that can be used as a href value in a link as displayed in output. Tags + Logi and extra specs.

Options

  • :for => :use (default), :show, :edit
  • :direction => the direction: :requested, :received, defaults to :requested
  • :step => <step_nr>, so many tags
  • :spec_step => <spec_step> (:logi, :logi_version)
  • :no_volatiles => if true no volatiles are shown for the :received direction

When :for => :use:

If :step XOR :spec_step is given, the segments upto the denoted segment of the url are returned.

When :for => :show

Extra specs are not for show-urls.

If :step XOR :spec_step is given, only one segment of the url is returned.

When :for => :edit

No options are used.

[Source]

     # File app/models/link.rb, line 586
586:   def to_s(options = {})
587:     case options[:for]
588:     when :show
589:       direction = options[:direction] || :requested
590:       tags = self.get_tags_in_direction(direction)
591:       if options[:step]
592:         if options[:per_part]
593:           if tags[options[:step]]
594:             return tags[options[:step]].to_s(:for => :show)
595:           else
596:             return nil
597:           end
598:         else
599:           return self.tags_to_s(self.step_tags(tags, options[:step]), :for => :show)
600:         end
601:       elsif options[:spec_step]
602:         if options[:per_part]
603:           return case options[:spec_step]
604:                  when :logi
605:                    self.logi_to_s(direction, options.merge(:for => :show))
606:                  when :logi_version
607:                    self.logi_version_to_s(direction)
608:                  else
609:                    raise StandardError.new, t('m.link.error_wrong_spec_step')
610:                  end
611:         else
612:           return self.tags_to_s(tags, :for => :show) +
613:               self.spec_to_s(options[:spec_step], direction, options)
614:         end
615:       else
616:         return self.tags_to_s(tags, :for => :show) +
617:             self.logi_to_s(direction, options.merge(:for => :link)) + self.logi_version_to_s(direction)
618:             # logi_to_s not for :show in non-spec_stepped links
619:       end
620:     when :edit
621:       tags = self.get_tags_in_direction(:requested)
622:       return self.tags_to_s(tags) +
623:           self.logi_to_s(:requested) +
624:           self.logi_version_to_s(:requested) +
625:           self.extra_specs_to_s
626:     else #:use
627:       direction = options[:direction] || :requested
628:       tags = self.get_tags_in_direction(direction)
629:       if options[:step]
630:         return self.tags_to_s(self.step_tags(tags, options[:step]))
631:       else
632:         string = self.tags_to_s(tags)
633:         if options[:spec_step]
634:           string += self.spec_to_s(options[:spec_step], direction, options)
635:         else
636:           string << self.logi_to_s(direction, options) \
637:                  << self.logi_version_to_s(direction)
638:         end
639:         return string
640:       end
641:     end
642:   end

Returns true if a match was found for all requested tags in any order (including given order). Returns false if only matches were found for reduced tagsets.

[Source]

     # File app/models/link.rb, line 313
313:   def unreduced_match?
314:     return (self.found_logi? and 
315:         self.requested_tags == self.received_tags)
316:   end

Dups into a new, unresolved Link.

Options

  • :step => <step_nr>, so many tags

MAYDO Other step options

[Source]

     # File app/models/link.rb, line 544
544:   def unresolved_dup(options = {})
545:     tags = self.requested_tags.dup
546:     if options[:step]
547:       link_options = {:requested_tags => self.requested_tags[0..options[:step]]}
548:     else
549:       link_options = {:requested_tags => self.requested_tags.dup,
550:         :to_logi => self.to_logi,
551:         :to_logi_version_nr => self.to_logi_version_nr}
552:     end
553:     link = Link.new(link_options)
554:     return link
555:   end

Resolves all exact and non-exact logi-matches, for all roles.

Unsorted.

Cached.

[Source]

     # File app/models/link.rb, line 492
492:   def volatile_all_logis
493:     if !self.found_logi? or self.exact_match?
494:       query = 'tags:' + self.received_tags.collect {|t| t.to_s.downcase}.join(' AND tags:')
495:       return (LogiLogiXapian.search([Logi], query) || [])
496:     else
497:       return self.matching_logis
498:     end
499:   end

Resolves all commenting logis for the volatile_to_logis.

Cached.

[Source]

     # File app/models/link.rb, line 505
505:   def volatile_to_commenting_logis
506:     logis = []
507:     self.volatile_to_logis.each do |logi|
508:       logis.concat(logi.commenting_logis)
509:     end
510:     logis.uniq!
511:     return logis
512:   end

Resolves a volatile to_logi.

Only content logi‘s can become a volatile_to_logi.

Cached.

[Source]

     # File app/models/link.rb, line 465
465:   def volatile_to_logi
466:     if !self.found_logi?
467:       return nil
468:     elsif self.to_logi
469:       return self.to_logi
470:     else
471:       return self.volatile_to_logis.first
472:     end
473:   end

Resolves a volatile to_logi_version

Volatile_*’s are the parts of the link that normally only can be determined after loading them for a certain user, using his PrefsProfile. The normal to_logi for example is only valid for LOGI and LOGI_VERSION links, while a volatile_to_logi can be determined for every link that has found_logi? == true.

Cached.

[Source]

     # File app/models/link.rb, line 449
449:   def volatile_to_logi_version
450:     if !self.found_logi?
451:       return nil
452:     elsif self.to_logi_version_nr
453:       return self.volatile_to_logi.logi_versions[self.to_logi_version_nr - 1]
454:     else
455:       return self.volatile_to_logi.current_logi_version
456:     end
457:   end

Resolves all logi_matches.

Used as Contenders and sorted.

Cached.

[Source]

     # File app/models/link.rb, line 481
481:   def volatile_to_logis
482:     return self.matching_logis.order_by_rating_for(
483:         PrefsProfile.current_prefs.peer_group)
484:   end

Protected Instance methods

Loads the position_ranges attribute, and associates itself as the reference with each PositionRange in the list.

[Source]

     # File app/models/link.rb, line 900
900:   def after_initialize
901:     if self.new_record?
902:       if self.stance.nil?
903:         self.stance = Const::Link::STANCES[:reference]
904:       end
905:       @position_ranges = PositionRange::List.new()
906:     else
907:       @position_ranges = PositionRange::List.from_s(self.position_ranges_string, :link => self)
908:     end
909:     self.reset_methods_cache # see CacheMethodsModule
910:     self.tags_strings_after_initialize # see TagsStringsModule
911:     return true
912:   end

Destroys the commenting that points to the same logi.

A commenting is only destroyed if this link is to_logi, and thus likely a link created with a comment.

[Source]

     # File app/models/link.rb, line 930
930:   def destroy_matching_commenting
931:     if self.to_logi
932:       commenting = self.from_logi.from_commentings.find_by_to_logi_id(self.to_logi)
933:       if commenting
934:         commenting.destroy
935:       end
936:     end
937:   end

Sub-function for the different *_to_s functions.

[Source]

     # File app/models/link.rb, line 884
884:   def extra_specs_to_s
885:     string = ''
886:     if self.stance != Const::Link::STANCES[:reference]
887:       string << Const::Link::BLOCK_SPEC_STANCE_S \
888:              << Const::Link::STANCE_SYMS[self.stance].to_s
889:     end
890:     return string
891:   end

Sub-function for the different *_to_s functions that turns a tag- string into a string.

Returns the tags for the given direction.

[Source]

     # File app/models/link.rb, line 781
781:   def get_tags_in_direction(direction)
782:     case direction
783:     when :requested
784:       return self.requested_tags
785:     when :received
786:       return self.received_tags
787:     else
788:       raise StandardError.new, t('m.link.error_wrong_direction')
789:     end
790:   end

Sub-function for resolve.

Creates a resolve_list for the requested_tags. This list is used by the resolve matches functions

Tags are resolved in a stair-wise way until a fit is found. The combinations that are requested to be tried out are as follows:

 A simple step down
 1 2 3 4
 1 2 3
 1 2
 1

We chose to keep it this simple.

Also this still is a consistent way of resolving tags as semi- hierarchies.

[Source]

     # File app/models/link.rb, line 740
740:   def list_for_requested_tags_resolving
741:     tags = self.requested_tags.dup
742:     tags_list = Array.new
743:     while !tags.empty?
744:       tags_list.push(tags.dup)
745:       tags.pop
746:     end
747:     return tags_list
748:   end

Logs the link‘s creation to LogLog

[Source]

     # File app/models/link.rb, line 941
941:   def log_create_to_log_log
942:     if GlobalConfig.use_log_log
943:       # Outgoing
944:       m = LogLogMessage.new(
945:           :kind => "Link",
946:           :channel_names => ['all', 'links',
947:               'for_' + self.from_logi.creator.unix_name].join(','),
948:           :title => 'Outgoing: ' + self.from_logi.current_title,
949:           :author => self.user.name,
950:           :text => GlobalConfig.site_url + self.to_s,
951:           :url => GlobalConfig.site_url + self.from_logi.link.to_s)
952:       m.save
953:       # Incoming
954:       if self.to_logi
955:         m = LogLogMessage.new(
956:             :kind => "Link",
957:             :channel_name => 
958:                 'for_' + self.to_logi.creator.unix_name,
959:             :title => 'Incoming: ' + self.to_logi.current_title,
960:             :author => self.user.name,
961:             :text => GlobalConfig.site_url + self.to_s,
962:             :url => GlobalConfig.site_url + self.to_logi.link.to_s)
963:         m.save
964:       else
965:         self.matching_logis.each do |logi|
966:           m = LogLogMessage.new(
967:               :kind => "Link",
968:               :channel_name => 
969:                   'for_' + logi.creator.unix_name,
970:               :title => 'Incoming: ' + logi.current_title,
971:               :author => self.user.name,
972:               :text => GlobalConfig.site_url + self.to_s,
973:               :url => GlobalConfig.site_url + logi.link.to_s)
974:           m.save
975:         end
976:       end
977:     end
978:   end

Sub-function for the different *_to_s functions

Returns the logi as a string

Valid Options same as for logi.to_s

[Source]

     # File app/models/link.rb, line 845
845:   def logi_to_s(direction, options = {})
846:     if direction == :requested
847:       logi = self.to_logi
848:     elsif direction == :received
849:       logi = self.volatile_to_logi
850:     else
851:       raise StandardError.new, t('m.link.error_wrong_direction')
852:     end
853:     if logi
854:       return logi.to_s(options)
855:     else
856:       return ''
857:     end
858:   end

Sub-function for the different *_to_s functions

Returns the logi_version as a string

[Source]

     # File app/models/link.rb, line 864
864:   def logi_version_to_s(direction)
865:     if direction == :requested
866:       if self.to_logi and self.to_logi_version_nr
867:         return self.to_logi.logi_versions[self.to_logi_version_nr - 1].to_s
868:       else
869:         return ''
870:       end
871:     elsif direction == :received
872:       if self.volatile_to_logi_version
873:         return self.volatile_to_logi_version.to_s
874:       else
875:         return ''
876:       end
877:     else
878:       raise StandardError.new, t('m.link.error_wrong_direction')
879:     end
880:   end

Sub-function for resolve.

Sets the received_tags to the requested tags, and the match to the logi, forced.

[Source]

     # File app/models/link.rb, line 769
769:   def receive_tags_for_to_logi
770:     self.received_tags = self.requested_tags.dup
771:     self.link_matches.build(:logi => self.to_logi)
772:   end

Sub-function for resolve.

Resolves all LinkTags upto the to_logi setting. Starts with the requested_tags, and steps down according to the list_for_requested_tags_resolving.

[Source]

     # File app/models/link.rb, line 666
666:   def resolve_matches_and_tags_for_requested_tags
667:     match_hash = self.resolve_tag_lists_matches_hash
668:     if match_hash[:receiveds].empty?
669:       self.received_tags = [self.requested_tags.first]
670:     else
671:       match_hash[:matches].each {|logi|
672:         self.link_matches << LinkMatch.new(:logi => logi)
673:       }
674:       self.received_tags = match_hash[:receiveds]
675:     end
676:   end

Sub-function for resolve.

Resolves all requested_tags. No stepping down.

[Source]

     # File app/models/link.rb, line 652
652:   def resolve_matches_for_all_requested_tags
653:     matches = self.resolve_tags_matches(self.requested_tags, :exact)
654:     matches.each {|logi|
655:       self.link_matches << LinkMatch.new(:logi => logi)
656:     }
657:     self.received_tags = self.requested_tags.dup
658:   end

Resolves tag matches for the list_for_requested_tags_resolving, trying one tag_list after the other, untill one results in matches.

Returns a hash containing:

  • :matches = the matched logi‘s
  • :receiveds = the received tag_list

[Source]

     # File app/models/link.rb, line 686
686:   def resolve_tag_lists_matches_hash
687:     tag_lists = self.list_for_requested_tags_resolving
688:     tag_lists.each {|tags|
689:       matches = self.resolve_tags_matches(tags, :exact)
690:       if matches.empty?
691:         matches = self.resolve_tags_matches(tags, :all)
692:       end
693:       if !matches.empty?
694:         return {:matches => matches, :receiveds => tags}
695:       end
696:     }
697:     return {:matches => [], :receiveds => []}
698:   end

Sub-function for resolve.

Resolves the received_tags for the to_logi

[Source]

     # File app/models/link.rb, line 754
754:   def resolve_tags_for_to_logi
755:     if self.requested_tags.empty? or 
756:         self.requested_tags.detect {|tag| !self.to_logi.tags.include?(tag)}
757:       self.received_tags = self.to_logi.tags.dup
758:     else
759:       self.received_tags = self.requested_tags.dup
760:     end
761:     self.link_matches.build(:logi => self.to_logi)
762:   end

Sub-function for resolve.

Resolves matches for a list of tags.

match_type is :all or :exact

Returns a list of matching Logis.

[Source]

     # File app/models/link.rb, line 708
708:   def resolve_tags_matches(tags, match_type)
709:     if match_type == :exact
710:       logis = Logi.find_all_by_tags_string(tags.collect {|t| t.to_s}.join('/'))
711:     elsif match_type == :all
712:       query = 'tags:' + tags.collect {|t| t.to_s.downcase}.join(' AND tags:')
713:       logis = LogiLogiXapian.search([Logi], query)
714:     else
715:       raise t('m.link.error_wrong_match_type')
716:     end
717:     logis.delete(self.from_logi) # remove self from matches
718:     return logis
719:   end

Returns the special things like to_logi and to_logi_version_nr as strings, depending on the spec-step given.

[Source]

     # File app/models/link.rb, line 827
827:   def spec_to_s(spec_step, direction, options)
828:     case options[:spec_step]
829:     when :logi
830:       return self.logi_to_s(direction, options)
831:     when :logi_version
832:       return self.logi_to_s(direction, options) +
833:              self.logi_version_to_s(direction)
834:     else
835:       raise StandardError.new, t('m.link.error_wrong_spec_step')
836:     end
837:   end

Returns the set of tags within the step-range.

Returns nil if range is bad.

[Source]

     # File app/models/link.rb, line 796
796:   def step_tags(tags, step)
797:     i = tags.index(tags[step])
798:     if i
799:       return tags[0..i]
800:     else
801:       return nil
802:     end
803:   end

Turns the requested- and received-tags into strings for storage.

[Source]

     # File app/models/link.rb, line 916
916:   def stringify_position_ranges
917:     if !@position_ranges.below?(self.from_logi.text_stack.size) # sanity check
918:       raise StandardError, t('defaults.error_end_position_range_bigger') + ' ' +
919:           self.from_logi.text_stack.size.to_s + ')'
920:     end
921:     self.position_ranges_string = @position_ranges.to_s
922:     return true
923:   end

Sub-function for the different *_to_s functions that turns a bundle of Tags into a string.

Options

  • :for => :use (default), :show, :edit

[Source]

     # File app/models/link.rb, line 811
811:   def tags_to_s(tags, options = {})
812:     if !tags.nil?
813:       tags = tags.collect {|tag| tag.to_s(options)}
814:       if options[:for] == :show
815:         return tags.join(' / ')
816:       else
817:         return tags.join('/')
818:       end
819:     else
820:       return nil
821:     end
822:   end

[Validate]