File: associations.rb

package info (click to toggle)
ruby-protected-attributes 1.0.8-2
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 304 kB
  • ctags: 382
  • sloc: ruby: 1,977; makefile: 2
file content (121 lines) | stat: -rw-r--r-- 3,572 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
module ActiveRecord
  module Associations
    class Association
      def build_record(attributes, options)
        reflection.build_association(attributes, options) do |record|
          attributes = create_scope.except(*(record.changed - [reflection.foreign_key]))
          record.assign_attributes(attributes, without_protection: true)
        end
      end

      private :build_record
    end

    class CollectionAssociation
      def build(attributes = {}, options = {}, &block)
        if attributes.is_a?(Array)
          attributes.collect { |attr| build(attr, options, &block) }
        else
          add_to_target(build_record(attributes, options)) do |record|
            yield(record) if block_given?
          end
        end
      end

      def create(attributes = {}, options = {}, &block)
        create_record(attributes, options, &block)
      end

      def create!(attributes = {}, options = {}, &block)
        create_record(attributes, options, true, &block)
      end

      def create_record(attributes, options, raise = false, &block)
        unless owner.persisted?
          raise ActiveRecord::RecordNotSaved, "You cannot call create unless the parent is saved"
        end

        if attributes.is_a?(Array)
          attributes.collect { |attr| create_record(attr, options, raise, &block) }
        else
          transaction do
            add_to_target(build_record(attributes, options)) do |record|
              yield(record) if block_given?
              insert_record(record, true, raise)
            end
          end
        end
      end

      private :create_record
    end

    class CollectionProxy
      def build(attributes = {}, options = {}, &block)
        @association.build(attributes, options, &block)
      end
      alias_method :new, :build

      def create(attributes = {}, options = {}, &block)
        @association.create(attributes, options, &block)
      end

      def create!(attributes = {}, options = {}, &block)
        @association.create!(attributes, options, &block)
      end
    end

    class HasManyThroughAssociation
      def build_record(attributes, options = {})
        ensure_not_nested

        record = super(attributes, options)

        inverse = source_reflection.inverse_of
        if inverse
          if inverse.macro == :has_many
            record.send(inverse.name) << build_through_record(record)
          elsif inverse.macro == :has_one
            record.send("#{inverse.name}=", build_through_record(record))
          end
        end

        record
      end
      private :build_record

      def options_for_through_record
        [through_scope_attributes, without_protection: true]
      end
      private :options_for_through_record
    end

    class SingularAssociation
      def create(attributes = {}, options = {}, &block)
        create_record(attributes, options, &block)
      end

      def create!(attributes = {}, options = {}, &block)
        create_record(attributes, options, true, &block)
      end

      def build(attributes = {}, options = {})
        record = build_record(attributes, options)
        yield(record) if block_given?
        set_new_record(record)
        record
      end

      def create_record(attributes, options = {}, raise_error = false)
        record = build_record(attributes, options)
        yield(record) if block_given?
        saved = record.save
        set_new_record(record)
        raise RecordInvalid.new(record) if !saved && raise_error
        record
      end

      private :create_record
    end
  end
end