Class: Plumber::Context

Inherits:
Object
  • Object
show all
Defined in:
lib/plumber/context.rb

Constant Summary collapse

MAX_ASSOCIATION_COUNT =
50

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(scope, parent = nil) ⇒ Context

Returns a new instance of Context.



7
8
9
10
11
12
13
# File 'lib/plumber/context.rb', line 7

def initialize(scope, parent = nil)
  @scope = scope
  @parent = parent
  @conditions = {}
  @mapping = {}
  @associations = []
end

Instance Attribute Details

#associationsObject (readonly)

Returns the value of attribute associations.



5
6
7
# File 'lib/plumber/context.rb', line 5

def associations
  @associations
end

#conditions(hash) ⇒ Object (readonly)

Returns the value of attribute conditions.



5
6
7
# File 'lib/plumber/context.rb', line 5

def conditions
  @conditions
end

#mapping(hash) ⇒ Object (readonly)

Returns the value of attribute mapping.



5
6
7
# File 'lib/plumber/context.rb', line 5

def mapping
  @mapping
end

#scopeObject (readonly)

Returns the value of attribute scope.



5
6
7
# File 'lib/plumber/context.rb', line 5

def scope
  @scope
end

Instance Method Details

#association(name) {|context| ... } ⇒ Object

Yields:

  • (context)


23
24
25
26
27
28
29
30
31
32
33
# File 'lib/plumber/context.rb', line 23

def association(name)
  scope = record.send(name)
  context = self.class.new(scope, self)

  yield context

  @associations << context

  # Return the record defined in the yielded context:
  context.record
end

#recordObject



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
# File 'lib/plumber/context.rb', line 35

def record
  if @record.nil?
    @record = if @parent.nil?
                # If this is a top-level context, use a database query to look up an
                # existing record that matches the conditions supplied.
                @scope.where(@conditions).first
              else
                # Because ActiveRecord (currently) doesn't have an "Identity Map" feature,
                # unfortunately for associated records we can't run a DB query to find
                # existing records.
                #
                # Instead we load all records in the scope and search for one matching
                # the conditions supplied. This is why we check the scope size and raise
                # an exception if it's too large - for situations where there are
                # potentially large numbers of associated records, a separate Importer
                # instance should be defined for handling those records.
                if @scope.count > MAX_ASSOCIATION_COUNT
                  message = "%s scope contains too many records (%s)" % [
                      @scope.new.class, @scope.count
                  ]

                  raise RuntimeError, message
                end

                @scope.detect do |record|
                  @conditions.all? { |k, v| record.send(k) == v }
                end
              end

    # If an existing record hasn't been found in the scope, build a new one:
    @record ||= @scope.build

    @conditions.merge(@mapping).each do |key, value|
      @record.send("#{key}=", value)
    end
  end

  @record
end