summaryrefslogtreecommitdiff
path: root/doc/development/utilities.md
blob: 951c3ef85ced4f3da865bdfb031462cb1d9e4904 (plain)
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
82
83
84
85
86
87
88
89
90
91
92
# GitLab utilities

We developed a number of utilities to ease development.

## [`MergeHash`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/utils/merge_hash.rb)

* Deep merges an array of hashes:

    ``` ruby
    Gitlab::Utils::MergeHash.merge(
      [{ hello: ["world"] },
       { hello: "Everyone" },
       { hello: { greetings: ['Bonjour', 'Hello', 'Hallo', 'Dzien dobry'] } },
        "Goodbye", "Hallo"]
    )
    ```

    Gives:

    ``` ruby
    [
      {
        hello:
          [
            "world",
            "Everyone",
            { greetings: ['Bonjour', 'Hello', 'Hallo', 'Dzien dobry'] }
          ]
      },
      "Goodbye"
    ]
    ```

* Extracts all keys and values from a hash into an array:

    ``` ruby
    Gitlab::Utils::MergeHash.crush(
      { hello: "world", this: { crushes: ["an entire", "hash"] } }
    )
    ```

    Gives:

    ``` ruby
    [:hello, "world", :this, :crushes, "an entire", "hash"]
    ```

## [`StrongMemoize`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/utils/strong_memoize.rb)

* Memoize the value even if it is `nil` or `false`.

    We often do `@value ||= compute`, however this doesn't work well if
    `compute` might eventually give `nil` and we don't want to compute again.
    Instead we could use `defined?` to check if the value is set or not.
    However it's tedious to write such pattern, and `StrongMemoize` would
    help us use such pattern.

    Instead of writing patterns like this:

    ``` ruby
    class Find
      def result
        return @result if defined?(@result)

        @result = search
      end
    end
    ```

    We could write it like:

    ``` ruby
    class Find
      include Gitlab::Utils::StrongMemoize

      def result
        strong_memoize(:result) do
          search
        end
      end
    end
    ```

* Clear memoization

    ``` ruby
    class Find
      include Gitlab::Utils::StrongMemoize
    end

    Find.new.clear_memoization(:result)
    ```