File: validatable.rb

package info (click to toggle)
ruby-awesome-nested-set 3.9.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 176 kB
  • sloc: ruby: 1,044; makefile: 2
file content (81 lines) | stat: -rw-r--r-- 2,664 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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
77
78
79
80
81
require 'awesome_nested_set/set_validator'

module CollectiveIdea
  module Acts
    module NestedSet
      module Model
        module Validatable

          def valid?
            left_and_rights_valid? && no_duplicates_for_columns? && all_roots_valid?
          end

          def left_and_rights_valid?
            SetValidator.new(self).valid?
          end

          def no_duplicates_for_columns?
            [quoted_left_column_full_name, quoted_right_column_full_name].all? do |column|
              # No duplicates
              select("#{scope_string}#{column}, COUNT(#{column}) as _count").
                group("#{scope_string}#{column}", quoted_primary_key_column_full_name).
                having("COUNT(#{column}) > 1").
                order(primary_column_name => :asc).
                first.nil?
            end
          end

          # Wrapper for each_root_valid? that can deal with scope.
          def all_roots_valid?
            if acts_as_nested_set_options[:scope]
              all_roots_valid_by_scope?(roots)
            else
              each_root_valid?(roots)
            end
          end

          def all_roots_valid_by_scope?(roots_to_validate)
            roots_grouped_by_scope(roots_to_validate).all? do |scope, grouped_roots|
              each_root_valid?(grouped_roots)
            end
          end

          def each_root_valid?(roots_to_validate)
            left_column = acts_as_nested_set_options[:left_column]
            reordered_roots = roots_reordered_by_column(roots_to_validate, left_column)
            left = right = 0
            reordered_roots.all? do |root|
              (root.left > left && root.right > right).tap do
                left = root.left
                right = root.right
              end
            end
          end

          private
          def roots_grouped_by_scope(roots_to_group)
            roots_to_group.group_by {|record|
              scope_column_names.collect {|col| record.send(col) }
            }
          end

          def roots_reordered_by_column(roots_to_reorder, column)
            if roots_to_reorder.respond_to?(:reorder) # ActiveRecord's relation
              roots_to_reorder.reorder(column)
            elsif roots_to_reorder.respond_to?(:sort) # Array
              roots_to_reorder.sort { |a, b| a.send(column) <=> b.send(column) }
            else
              roots_to_reorder
            end
          end

          def scope_string
            Array(acts_as_nested_set_options[:scope]).map do |c|
              connection.quote_column_name(c)
            end.push(nil).join(", ")
          end
        end
      end
    end
  end
end