Class: Zermelo::Associations::Multiple

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/zermelo/associations/multiple.rb

Instance Method Summary collapse

Constructor Details

#initialize(type, parent_klass, parent_id, name) ⇒ Multiple

Returns a new instance of Multiple.



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
# File 'lib/zermelo/associations/multiple.rb', line 17

def initialize(type, parent_klass, parent_id, name)
  @type         = type
  @parent_klass = parent_klass
  @parent_id    = parent_id
  @name         = name

  @backend      = parent_klass.send(:backend)

  @key_type = case @type
  when :has_many, :has_and_belongs_to_many
    :set
  when :has_sorted_set
    :sorted_set
  end

  @record_ids_key = Zermelo::Records::Key.new(
    :klass  => parent_klass,
    :id     => parent_id,
    :name   => "#{name}_ids",
    :type   => @key_type,
    :object => :association
  )

  parent_klass.send(:with_association_data, name.to_sym) do |data|
    @associated_class = data.data_klass
    @lock_klasses     = [data.data_klass] + data.related_klasses
    @inverse          = data.inverse
    @sort_key         = data.sort_key
    @sort_order       = data.sort_order
    @callbacks        = data.callbacks
  end

  raise ':inverse_of must be set' if @inverse.nil?
end

Instance Method Details

#<<(record) ⇒ Object



62
63
64
65
# File 'lib/zermelo/associations/multiple.rb', line 62

def <<(record)
  add(record)
  self  # for << 'a' << 'b'
end

#add(*records) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/zermelo/associations/multiple.rb', line 67

def add(*records)
  raise 'No records to add' if records.empty?
  raise 'Invalid record class' if records.any? {|r| !r.is_a?(@associated_class)}
  raise 'Record(s) must have been saved' unless records.all? {|r| r.persisted?} # may need to be moved
  @parent_klass.lock(*@lock_klasses) do
    record_ids = case @type
    when :has_many, :has_and_belongs_to_many
      records.is_a?(Zermelo::Filter) ? records.ids : records.map(&:id)
    when :has_sorted_set
      records.map {|r| [r.send(@sort_key.to_sym).to_f, r.id]}
    end
    _add_ids({:callbacks => true}, *record_ids)
  end
end

#add_ids(*record_ids) ⇒ Object



82
83
84
85
86
87
88
# File 'lib/zermelo/associations/multiple.rb', line 82

def add_ids(*record_ids)
  raise 'No record ids to add' if record_ids.empty?
  @parent_klass.lock(*@lock_klasses) do
    @associated_class.find_by_ids!(*record_ids) # ensure they exist
    _add_ids({:callbacks => true}, *record_ids)
  end
end

#clearObject



108
109
110
111
112
# File 'lib/zermelo/associations/multiple.rb', line 108

def clear
  @parent_klass.lock(*@lock_klasses) do
    _remove_ids({:callbacks => true}, *filter.ids) unless filter.empty?
  end
end

#firstObject



52
53
54
55
# File 'lib/zermelo/associations/multiple.rb', line 52

def first
  # FIXME raise error unless :has_sorted_set.eql?(@type)
  filter.first
end

#key_dumpObject



114
115
116
# File 'lib/zermelo/associations/multiple.rb', line 114

def key_dump
  [@backend.key_to_backend_key(@record_ids_key), @record_ids_key]
end

#lastObject



57
58
59
60
# File 'lib/zermelo/associations/multiple.rb', line 57

def last
  # FIXME raise error unless :has_sorted_set.eql?(@type)
  filter.last
end

#remove(*records) ⇒ Object

TODO support dependent delete, for now just removes the association



91
92
93
94
95
96
97
98
99
# File 'lib/zermelo/associations/multiple.rb', line 91

def remove(*records)
  raise 'No records to remove' if records.empty?
  raise 'Invalid record class' if records.any? {|r| !r.is_a?(@associated_class)}
  raise 'Record(s) must have been saved' unless records.all? {|r| r.persisted?} # may need to be moved
  @parent_klass.lock(*@lock_klasses) do
    _remove_ids({:callbacks => true},
      *(records.is_a?(Zermelo::Filter) ? records.ids : records.map(&:id)))
  end
end

#remove_ids(*record_ids) ⇒ Object



101
102
103
104
105
106
# File 'lib/zermelo/associations/multiple.rb', line 101

def remove_ids(*record_ids)
  raise 'No record ids to remove' if record_ids.empty?
  @parent_klass.lock(*@lock_klasses) do
    _remove_ids({:callbacks => true}, *record_ids)
  end
end