File: active_model.rb

package info (click to toggle)
ruby-shoulda-matchers 7.0.1%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,652 kB
  • sloc: ruby: 34,046; sh: 280; makefile: 9
file content (136 lines) | stat: -rw-r--r-- 3,126 bytes parent folder | download
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
module UnitTests
  module ModelCreationStrategies
    class ActiveModel
      def self.call(name, attribute_names = [], options = {}, &block)
        new(name, attribute_names, options, &block).call
      end

      def initialize(name, attribute_names = [], options = {}, &block)
        @name = name
        @attribute_names =
          if attribute_names.is_a?(Hash)
            # mimicking columns
            attribute_names.keys
          else
            attribute_names
          end
        @options = options
        @model_customizers = []

        if block
          customize_model(&block)
        end
      end

      def customize_model(&block)
        model_customizers << block
      end

      def call
        ClassBuilder.define_class(name, Model).tap do |model|
          attribute_names.each do |attribute_name|
            model.attribute(attribute_name)
          end

          model_customizers.each do |block|
            run_block(model, block)
          end
        end
      end

      private

      attr_reader :name, :attribute_names, :model_customizers, :options

      def run_block(model, block)
        if block
          if block.arity == 0
            model.class_eval(&block)
          else
            block.call(model)
          end
        end
      end

      module PoorMansAttributes
        extend ActiveSupport::Concern

        included do
          class_attribute :attribute_names

          self.attribute_names = Set.new
        end

        module ClassMethods
          def attribute(name)
            include attributes_module

            name = name.to_sym

            if
              attribute_names.include?(name) &&
              attributes_module.instance_methods.include?(name)

              attributes_module.module_eval do
                remove_method(name)
                remove_method("#{name}=")
              end
            end

            self.attribute_names += [name]

            attributes_module.module_eval do
              define_method(name) do
                attributes[name]
              end

              define_method("#{name}=") do |value|
                attributes[name] = value
              end
            end
          end

          private

          def attributes_module
            @_attributes_module ||= Module.new
          end
        end

        attr_reader :attributes

        def initialize(attributes = {})
          @attributes = attributes.symbolize_keys
        end

        def inspect
          middle = '%s:0x%014x%s' % [
            self.class,
            object_id * 2,
            " #{inspected_attributes.join(' ')}",
          ]

          "#<#{middle.strip}>"
        end

        private

        def inspected_attributes
          self.class.attribute_names.map do |name|
            "#{name}: #{attributes[name].inspect}"
          end
        end
      end

      class Model
        include ::ActiveModel::Model

        if defined?(::ActiveModel::Attributes)
          include ::ActiveModel::Attributes
        else
          include PoorMansAttributes
        end
      end
    end
  end
end