Module: StewEucen::Acts::FertileForest::Table::Finders

Defined in:
lib/fertile_forest/modules/finders.rb

Overview

This module is for extending into derived class by ActiveRecord.
The caption contains “Instance Methods”, but it means “Class Methods” of each derived class.

Instance Method Summary collapse

Instance Method Details

#ancestors(base_obj, columns = nil) ⇒ ActiveRecord::Relation? Also known as: superiors, forebears

Find all ancestor nodes from base node (without base node).

Parameters:

  • base_obj (Entity|Integer)

    Base node|id to find.

  • columns (Array) (defaults to: nil)

    Columns for SELECT clause.

Returns:

  • (ActiveRecord::Relation)

    Basic query for finding ancestor nodes.

  • (nil)

    No ancestor nodes.



86
87
88
# File 'lib/fertile_forest/modules/finders.rb', line 86

def ancestors(base_obj, columns = nil)
  trunk(base_obj, ANCESTOR_ALL, columns)
end

#children(base_obj, columns = nil) ⇒ ActiveRecord::Relation?

Find child nodes from base node.

Parameters:

  • base_obj (Entity|Integer)

    Base node|id to find.

  • columns (Array) (defaults to: nil)

    Columns for SELECT clause.

Returns:

  • (ActiveRecord::Relation)

    Basic query for finding child nodes.

  • (nil)

    No child nodes.



245
246
247
# File 'lib/fertile_forest/modules/finders.rb', line 245

def children(base_obj, columns = nil)
  subtree(base_obj, DESCENDANTS_ONLY_CHILD, false, columns)
end

#cousins(base_obj, columns = nil) ⇒ ActiveRecord::Relation?

Find cousin nodes from base node. Note: Results includes siblngs nodes.

Parameters:

  • base_obj (Entity|Integer)

    Base node|id to find.

  • columns (Array) (defaults to: nil)

    Columns for SELECT clause.

Returns:

  • (ActiveRecord::Relation)

    Basic query for finding cousin nodes.

  • (nil)

    No cousin nodes.

Since:

  • 1.1.0



384
385
386
# File 'lib/fertile_forest/modules/finders.rb', line 384

def cousins(base_obj, columns = nil)
  kinships(base_obj, KINSHIPS_AS_COUSIN, KINSHIPS_SAME_LEVEL, columns)
end

#descendants(base_obj, columns = nil) ⇒ ActiveRecord::Relation? Also known as: inferiors, afterbears

Find descendant nodes from base node.

Parameters:

  • base_obj (Entity|Integer)

    Base node|id to find.

  • columns (Array) (defaults to: nil)

    Columns for SELECT clause.

Returns:

  • (ActiveRecord::Relation)

    Basic query for finding descendant nodes.

  • (nil)

    No descendant nodes.



233
234
235
# File 'lib/fertile_forest/modules/finders.rb', line 233

def descendants(base_obj, columns = nil)
  subtree(base_obj, DESCENDANTS_ALL, false, columns)
end

#elder_sibling(base_obj, columns = nil) ⇒ Entity?

Find elder sibling node from base node.

Parameters:

  • base_obj (Entity|Integer)

    Base node|id to find.

  • columns (Array) (defaults to: nil)

    Columns for SELECT clause.

Returns:

  • (Entity)

    Elder sibling node of base node.

  • (nil)

    No elder sibling node.



442
443
444
# File 'lib/fertile_forest/modules/finders.rb', line 442

def elder_sibling(base_obj, columns = nil)
  offset_sibling(base_obj, -1, columns)
end

#genitor(base_obj, columns = nil) ⇒ Entity?

Find genitor (= parent) node from base node.

Parameters:

  • base_obj (Entity|Integer)

    Base node|id to find.

  • columns (Array) (defaults to: nil)

    Columns for SELECT clause.

Returns:

  • (Entity)

    Genitor node.

  • (nil)

    No genitor node.



98
99
100
101
102
103
104
# File 'lib/fertile_forest/modules/finders.rb', line 98

def genitor(base_obj, columns = nil)
  trunk_query = trunk(base_obj, ANCESTOR_ONLY_PARENT, columns)

  return nil if trunk_query.blank?

  trunk_query.first
end

#grandchildren(base_obj, columns = nil) ⇒ ActiveRecord::Relation?

Find grandchild nodes from base node.

Parameters:

  • base_obj (Entity|Integer)

    Base node|id to find.

  • columns (Array) (defaults to: nil)

    Columns for SELECT clause.

Returns:

  • (ActiveRecord::Relation)

    Basic query for finding grandchild nodes.

  • (nil)

    No grandchild nodes.



279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
# File 'lib/fertile_forest/modules/finders.rb', line 279

def grandchildren(base_obj, columns = nil)
  base_node = ff_resolve_nodes(base_obj)
  return [] if base_node.blank?

  grand_number = 2

  # return value
  subtree(
      base_node,
      grand_number,
      SUBTREE_WITHOUT_TOP_NODE,
      columns
    )
    .where(@_ff_depth => base_node.ff_depth + grand_number)
end

#grandparent(base_obj, columns = nil) ⇒ Entity?

Find grandparent node from base node.

Parameters:

  • base_obj (Entity|int)

    Base node|id to find.

  • columns (Array) (defaults to: nil)

    Columns for SELECT clause.

Returns:

  • (Entity)

    Grandparent node.

  • (nil)

    No grandparent node.



134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/fertile_forest/modules/finders.rb', line 134

def grandparent(base_obj, columns = nil)
  base_node = ff_resolve_nodes(base_obj)
  return nil if base_node.blank?

  grand_number = 2

  grandparent_depth = base_node.ff_depth - grand_number
  return nil if grandparent_depth < ROOT_DEPTH

  trunk_query = trunk(base_node, grand_number, columns)
  return nil if trunk_query.blank?

  trunk_query.first
end

#grove_nodes(grove_id = nil, columns = nil) ⇒ ActiveRecord::Relation

TODO:

Pagination.

Find all nodes in grove.

Parameters:

  • grove_id (Integer|nil) (defaults to: nil)

    Grove ID to find.

  • columns (Array) (defaults to: nil)

    Columns for SELECT clause.

Returns:

  • (ActiveRecord::Relation)

    Query for finding nodes.



571
572
573
574
# File 'lib/fertile_forest/modules/finders.rb', line 571

def grove_nodes(grove_id = nil, columns = nil)
  ff_usual_conditions_scope(grove_id)
    .ff_usual_order_scope()
end

#grovesActiveRecord::Relation

TODO:

Test.

Find grove informations that has enable (not soft deleted and not grove deleted).

Returns:

  • (ActiveRecord::Relation)

    Query for finding grove ids.



598
599
600
601
602
603
604
605
606
607
# File 'lib/fertile_forest/modules/finders.rb', line 598

def groves
  return nil unless has_grove?

  ffid = arel_table[@_ff_id]
  ffgg = arel_table[@_ff_grove]

  ff_usual_conditions_scope()
      .select([ffgg, ffid.count('*').as('ff_count')])
      .group([ffgg])
end

#internals(base_obj, columns = nil) ⇒ Array?

Find internal nodes from base node.

Parameters:

  • base_obj (Entity|Integer)

    Base node|id to find.

  • columns (Array) (defaults to: nil)

    Columns for SELECT clause.

Returns:

  • (Array)

    Basic query for finding internal nodes.

  • (nil)

    No internal nodes.



520
521
522
# File 'lib/fertile_forest/modules/finders.rb', line 520

def internals(base_obj, columns = nil)
  ff_features(base_obj, true, columns)
end

#kinships(base_obj, next_branch = KINSHIPS_AS_SIBLING, level_offset = KINSHIPS_SAME_LEVEL, columns = nil) ⇒ ActiveRecord::Relation?

Find any kind of kinship from base node.

Parameters:

  • base_obj (Entity|Integer)

    Base node|id to find.

  • next_branch (Integer) (defaults to: KINSHIPS_AS_SIBLING)

    Branch distance of finding nodes from base nodes.

  • level_offset (Integer) (defaults to: KINSHIPS_SAME_LEVEL)

    Offset of kinship level of finding nodes from base nodes.

  • columns (Array) (defaults to: nil)

    Columns for SELECT clause.

Returns:

  • (ActiveRecord::Relation)

    Basic query for finding kinship nodes.

  • (nil)

    No kinship nodes.

Since:

  • 1.1.0



306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
# File 'lib/fertile_forest/modules/finders.rb', line 306

def kinships(
  base_obj,
  next_branch = KINSHIPS_AS_SIBLING,
  level_offset = KINSHIPS_SAME_LEVEL,
  columns = nil
)
  base_node = ff_resolve_nodes(base_obj)
  return nil if base_node.blank?

  aim_queue = base_node.ff_queue
  aim_depth = base_node.ff_depth
  aim_grove = base_node.ff_grove  # When no grove, nil

  top_depth = aim_depth - next_branch

  # Impossible to find.
  return nil if top_depth < ROOT_DEPTH

  ffqq = arel_table[@_ff_queue]
  ffdd = arel_table[@_ff_depth]
  ffgg = arel_table[@_ff_grove]

  # create subquery
  before_nodes_subquery = ff_usual_projection(aim_grove)
      .project(ffqq.maximum.to_sql + " + 1 AS head_queue")
      .where(ffqq.lt(aim_queue))
      .where(ffdd.lt(top_depth))

  after_nodes_subquery = ff_usual_projection(aim_grove)
      .project(ffqq.minimum.to_sql + " - 1 AS tail_queue")
      .where(ffqq.gt(aim_queue))
      .where(ffdd.lt(top_depth))

  func_maker = Arel::Nodes::NamedFunction

  before_coalesce_condition = func_maker.new(
      'COALESCE',
      [before_nodes_subquery, 0]
  )

  after_coalesce_condition = func_maker.new(
      'COALESCE',
      [after_nodes_subquery, QUEUE_MAX_VALUE]
  )

  # find nodes by ancestor queues
  ff_required_columns_scope()
      .ff_usual_conditions_scope(aim_grove)
      .ff_usual_order_scope()
      .where(ffdd.eq(aim_depth + level_offset))
      .where(ffqq.gteq(before_coalesce_condition))
      .where(ffqq.lteq(after_coalesce_condition))
      .select(ff_all_optional_columns(columns))
end

#leaves(base_obj, columns = nil) ⇒ Array? Also known as: externals, terminals

TODO:

Pagination, Create limit as desc.

Find leaf nodes from base node.

Parameters:

  • base_obj (Entity|Integer)

    Base node|id to find.

  • columns (Array) (defaults to: nil)

    Columns for SELECT clause.

Returns:

  • (Array)

    Basic query for finding leaf nodes.

  • (nil)

    No leaf nodes.



508
509
510
# File 'lib/fertile_forest/modules/finders.rb', line 508

def leaves(base_obj, columns = nil)
  ff_features(base_obj, false, columns)
end

#nested_ids(haystack_nodes) ⇒ Array

Create nested IDs

Parameters:

  • haystack_nodes (ActiveRecord::Relation|Array)

    Iteratorable nodes data.

Returns:

  • (Array)

    Nested IDs data.



697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
# File 'lib/fertile_forest/modules/finders.rb', line 697

def nested_ids(haystack_nodes)
  res = {}
  if haystack_nodes.present?
    if has_grove?
      haystack_nodes.each_pair do |grove_id, grove_nodes|
        res[grove_id] = {}
        grove_nodes.each_pair do |the_id, the_node|
          res[grove_id].merge!(ff_nest_children(the_id, grove_nodes))
        end
      end
    else
      haystack_nodes.each_pair do |the_id, the_node|
        res.merge!(ff_nest_children(the_id, haystack_nodes))
      end
    end
  end

  # return value
  res
end

#nested_nodes(haystack_nodes) ⇒ Hash|Array

Create nested nodes from subtree nodes.

Parameters:

  • haystack_nodes (ActiveRecord::Relation|Array)

    Iteratorable nodes data.

Returns:

  • (Hash|Array)

    When has grove is Hash, otherwise Array.



615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
# File 'lib/fertile_forest/modules/finders.rb', line 615

def nested_nodes(haystack_nodes)
  return {} if haystack_nodes.blank?

  #
  # pick up nodes by iterator
  #  (1) array
  #  (2) query
  #  (3) ResultSet
  # return by hash [id => node]
  #
  sorted_nodes = ff_queue_sorted_nodes(haystack_nodes)
  return {} if sorted_nodes.blank?

  # ネストがroot(=1)からじゃない場合の対応
  # queueで並べた先頭のdepthを暫定root depthとする
  the_root_depth = sorted_nodes[0].ff_depth

  sorted_nodes.each do |node|
    node.nest_unset_parent
    node.nest_unset_children
  end

  # 遡って見えているnodesを格納する配列
  retro_nodes = {}
  if has_grove?
    sorted_nodes.each do |node|
      retro_nodes[node.ff_grove] = []
    end
  else
    retro_nodes[:singular] = []
  end

  # 戻り値の生成用の、IDをキーとしたhashによるnest情報
  res_nested_nodes = {}

  grove_key = :singular
  sorted_nodes.each do |node|
    the_id = node.id
    depth = node.ff_depth

    grove_key = node.ff_grove if has_grove?

    res_nested_nodes[the_id] = node;  # 今回のnodesを登録

    depth_index = depth - the_root_depth   # ネストがroot(=1)からじゃない場合の対応
    parent_depth_index = depth_index - 1

    # このnodeに親があれば、親子関係を登録
    if 0 <= parent_depth_index && retro_nodes[grove_key][parent_depth_index].present?
      parent_id = retro_nodes[grove_key][parent_depth_index]

      res_nested_nodes[parent_id].nest_set_child_id(the_id)
      res_nested_nodes[the_id].nest_set_parent_id(parent_id)
    end

    # 今回の深度のところまで親リストを消した上で自分を登録する
    retro_nodes[grove_key] = retro_nodes[grove_key].slice(0, depth_index)
    retro_nodes[grove_key][depth_index] = the_id
  end

  return res_nested_nodes unless has_grove?

  # set grove hash
  grove_res = {}

  retro_nodes.keys.each do |grove|
    grove_res[grove] = {}
  end

  res_nested_nodes.each_pair do |id, node|
    grove_res[node.ff_grove][id] = node
  end

  grove_res
end

#niblings(base_obj, columns = nil) ⇒ ActiveRecord::Relation? Also known as: nephews, nieces

Find nibling nodes from base node. Note: Results includes siblngs nodes.

Parameters:

  • base_obj (Entity|Integer)

    Base node|id to find.

  • columns (Array) (defaults to: nil)

    Columns for SELECT clause.

Returns:

  • (ActiveRecord::Relation)

    Basic query for finding nibling nodes.

  • (nil)

    No nibling nodes.

Since:

  • 1.1.0



410
411
412
# File 'lib/fertile_forest/modules/finders.rb', line 410

def niblings(base_obj, columns = nil)
  kinships(base_obj, KINSHIPS_AS_SIBLING, KINSHIPS_CHILD_LEVEL, columns)
end

#nth_child(base_obj, nth = 0, columns = nil) ⇒ Entity?

Find nth-child node from base node.

Parameters:

  • base_obj (Entity|Integer)

    Base node|id to find.

  • nth (Integer) (defaults to: 0)

    Order in child nodes.

  • columns (Array) (defaults to: nil)

    Columns for SELECT clause.

Returns:

  • (Entity)

    Nth-child node.

  • (nil)

    No nth-child node.



258
259
260
261
262
263
264
265
266
267
268
269
# File 'lib/fertile_forest/modules/finders.rb', line 258

def nth_child(base_obj, nth = 0, columns = nil)
  children_query = children(base_obj, columns)

  nth = nth.to_i
  if nth < 0
    sibling_count = children_query.all.length
    nth = sibling_count - 1
    return nil if nth < 0
  end

  children_query.offset(nth).first
end

#nth_sibling(base_obj, nth = 0, columns = nil) ⇒ Entity?

Find nth-sibling node from base node.

Parameters:

  • base_obj (Entity|Integer)

    Base node|id to find.

  • nth (Integer) (defaults to: 0)

    Order in child nodes.

  • columns (Array) (defaults to: nil)

    Columns for SELECT clause.

Returns:

  • (Entity)

    Nth-sibling node.

  • (nil)

    No nth-sibling node.



423
424
425
426
427
428
429
430
431
432
# File 'lib/fertile_forest/modules/finders.rb', line 423

def nth_sibling(base_obj, nth = 0, columns = nil)
  base_node = ff_resolve_nodes(base_obj)
  return nil if base_node.blank?

  parent_node = genitor(base_node)
  return nil if parent_node.blank?

  nth = nth.to_i
  nth_child(parent_node, nth, columns)
end

#offset_sibling(base_obj, offset, columns = nil) ⇒ Entity?

Find offsetted sibling node from base node.

Parameters:

  • base_obj (Entity|Integer)

    Base node|id to find.

  • offset (Integer)

    Order in child nodes.

  • columns (Array) (defaults to: nil)

    Columns for SELECT clause.

Returns:

  • (Entity)

    Offsetted sibling node from base node.

  • (nil)

    No offsetted sibling node.



467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
# File 'lib/fertile_forest/modules/finders.rb', line 467

def offset_sibling(base_obj, offset, columns = nil)
  base_node = ff_resolve_nodes(base_obj)
  return nil if base_node.blank?

  parent_node = genitor(base_node)
  return nil if parent_node.blank?

  sibling_nodes = children(parent_node, [@_id]).all
  return nil if sibling_nodes.blank?

  base_id = base_node.id

  nth = nil
  Array(sibling_nodes).each.with_index do |node, i|
    if node.id == base_id
      nth = i
      break
    end
  end

  return nil if nth.nil?

  offset = offset.to_i

  # OFFSET -1 make an error
  # Error: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax;
  # check the manual that corresponds to your MySQL server version for the right syntax to use near '-1' at line 1
  return nil if nth + offset < 0

  nth_child(parent_node, nth + offset, columns)
end

#piblings(base_obj, columns = nil) ⇒ ActiveRecord::Relation? Also known as: auncles, aunts, uncles

Find aunt|uncle nodes from base node. Note: Results includes siblngs nodes.

Parameters:

  • base_obj (Entity|Integer)

    Base node|id to find.

  • columns (Array) (defaults to: nil)

    Columns for SELECT clause.

Returns:

  • (ActiveRecord::Relation)

    Basic query for finding aunt|uncle nodes.

  • (nil)

    No aunt|uncle nodes.

Since:

  • 1.1.0



397
398
399
# File 'lib/fertile_forest/modules/finders.rb', line 397

def piblings(base_obj, columns = nil)
  kinships(base_obj, KINSHIPS_AS_COUSIN, KINSHIPS_PARENT_LEVEL, columns)
end

#root(base_obj, columns = nil) ⇒ Entity, Enil

Find root node from base node.

Parameters:

  • base_obj (Entity|int)

    Base node|id to find.

  • columns (Array) (defaults to: nil)

    Columns for SELECT clause.

Returns:

  • (Entity)

    Root node. When base node is root, return base node.

  • (Enil)

    No root node.



114
115
116
117
118
119
120
121
122
123
124
# File 'lib/fertile_forest/modules/finders.rb', line 114

def root(base_obj, columns = nil)
  base_node = ff_resolve_nodes(base_obj)
  return nil if base_node.blank?

  return base_node if base_node.ff_depth == ROOT_DEPTH

  trunk_query = trunk(base_node, ANCESTOR_ONLY_ROOT, columns)
  return nil if trunk_query.blank?

  trunk_query.first
end

#roots(grove_id = nil, columns = nil) ⇒ ActiveRecord::Relation

TODO:

Pagination.

Find all root nodes in grove.

Parameters:

  • grove_id (Integer|nil) (defaults to: nil)

    Grove ID to find.

  • columns (Array) (defaults to: nil)

    Columns for SELECT clause.

Returns:

  • (ActiveRecord::Relation)

    Query for finding nodes.



584
585
586
587
588
589
590
# File 'lib/fertile_forest/modules/finders.rb', line 584

def roots(grove_id = nil, columns = nil)
  grove_id = grove_id.to_i
  ffdd = arel_table[@_ff_depth]
  ff_usual_conditions_scope(grove_id)
      .ff_usual_order_scope()
      .where(ffdd.eq(ROOT_DEPTH))
end

#siblings(base_obj, columns = nil) ⇒ ActiveRecord::Relation?

Find sibling nodes from base node. Note: Results includes base node.

Parameters:

  • base_obj (Entity|Integer)

    Base node|id to find.

  • columns (Array) (defaults to: nil)

    Columns for SELECT clause.

Returns:

  • (ActiveRecord::Relation)

    Basic query for finding sibling nodes.

  • (nil)

    No sibling nodes.

Version:

  • 1.1.0 Replace to use kinships()



371
372
373
# File 'lib/fertile_forest/modules/finders.rb', line 371

def siblings(base_obj, columns = nil)
  kinships(base_obj, KINSHIPS_AS_SIBLING, KINSHIPS_SAME_LEVEL, columns)
end

#subtree(base_obj, range = DESCENDANTS_ALL, with_top = true, columns = nil) ⇒ ActiveRecord::Relation?

Find subtree nodes from base node with ordered range.

Parameters:

  • base_obj (Entity|Integer)

    Base node|id to find.

  • range (Integer) (defaults to: DESCENDANTS_ALL)

    Ordered range of trunk nodes. -1:To designate as root node.

  • withTop (boolean)

    Include base node in return query.

  • fields (Array)

    Fields for SELECT clause.

Returns:

  • (ActiveRecord::Relation)

    Basic query for finding subtree nodes.

  • (nil)

    No subtree nodes.



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/fertile_forest/modules/finders.rb', line 161

def subtree(base_obj, range = DESCENDANTS_ALL, with_top = true, columns = nil)
  base_node = ff_resolve_nodes(base_obj)
  return [] if base_node.blank?

  aim_query = ff_required_columns_scope(columns)
    .ff_subtree_scope(
      base_node,
      with_top,
      true   # use COALESCE() must be false for children().count
    )

  ffdd = arel_table[@_ff_depth]
  limited = ff_limited_subtree_depth(
    base_node.ff_depth,
    range,
    aim_query
  )

  aim_query.where!(ffdd.lteq(limited)) if 0 < limited

  aim_query
    .select(ff_all_optional_columns(columns))
    .ff_usual_order_scope()
end

#trunk(base_obj, range = ANCESTOR_ALL, columns = nil) ⇒ ActiveRecord::Relation?

Find trunk (= ancestor) nodes from base node in ordered range.

Parameters:

  • base_obj (Entity|Integer)

    Base node|id to find.

  • range (Integer) (defaults to: ANCESTOR_ALL)

    Ordered range of trunk nodes. -1:To designate as root node.

  • columns (Array) (defaults to: nil)

    Columns for SELECT clause.

Returns:

  • (ActiveRecord::Relation)

    Basic query for finding trunk nodes.

  • (nil)

    No trunk nodes.



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/fertile_forest/modules/finders.rb', line 35

def trunk(base_obj, range = ANCESTOR_ALL, columns = nil)
  base_node = ff_resolve_nodes(base_obj)
  return nil if base_node.blank?

  aim_queue = base_node.ff_queue
  aim_depth = base_node.ff_depth
  aim_grove = base_node.ff_grove  # When no grove, nil

  return nil if aim_depth == ROOT_DEPTH

  ffqq = arel_table[@_ff_queue]
  ffdd = arel_table[@_ff_depth]
  ffgg = arel_table[@_ff_grove]

  # create subquery to find queues of ancestor
  aim_subquery = ff_usual_projection(aim_grove)
      .where(ffqq.lt(aim_queue))

  if range < 0
    aim_subquery = aim_subquery.where(ffdd.eq(ROOT_DEPTH))
  else
    aim_subquery = aim_subquery.where(ffdd.lt(aim_depth))
    aim_subquery = aim_subquery.where(ffdd.gteq(aim_depth - range)) \
        if 0 < range
  end

  aim_group = [ffdd]
  aim_group.unshift(ffgg) if has_grove?

  aim_subquery = aim_subquery.project(ffqq.maximum.as('ancestor_queue'))
    .group(aim_group)

  # find nodes by ancestor queues
  # must use IN(), because trunk() is for general purpose to find ancestors
  # When one row, can use "=". When plural, can not use "=".
  # Error: SQLSTATE[21000]: Cardinality violation: 1242 Subquery returns more than 1 row
  ff_required_columns_scope()
      .ff_usual_conditions_scope(aim_grove)
      .ff_usual_order_scope()
      .where(ffqq.in(aim_subquery))
      .select(ff_all_optional_columns(columns))
end

#younger_sibling(base_obj, columns = nil) ⇒ Entity?

Find younger sibling node from base node.

Parameters:

  • base_obj (Entity|Integer)

    Base node|id to find.

  • columns (Array) (defaults to: nil)

    Columns for SELECT clause.

Returns:

  • (Entity)

    Younger sibling node of base node.

  • (nil)

    No younger sibling node.



454
455
456
# File 'lib/fertile_forest/modules/finders.rb', line 454

def younger_sibling(base_obj, columns = nil)
  offset_sibling(base_obj, 1, columns)
end