Class: ActiveRecord::Acts::Partitioned::Factory

Inherits:
Object
  • Object
show all
Defined in:
lib/active_record/acts/partitioned/factory.rb

Overview

TODO: Rename to Proxy TODO: If we were clever we would merge this with the Partiton AR model - can’t merge as you need a proxy instance but we can move lots of methods over

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model, partition_class, options = {}) ⇒ Factory

Returns a new instance of Factory.



14
15
16
17
18
19
20
21
22
# File 'lib/active_record/acts/partitioned/factory.rb', line 14

def initialize(model, partition_class, options = {})
  @model = model
  @keys = Keys.new
 # TODO: Should we raise if we never add any keys?
  @partition_class = partition_class
  partition_class.factory = self
  # TODO: Raise if model does not have key column(s)
  @options = options
end

Instance Attribute Details

#keysObject (readonly)

Returns the value of attribute keys.



9
10
11
# File 'lib/active_record/acts/partitioned/factory.rb', line 9

def keys
  @keys
end

#modelObject (readonly)

Returns the value of attribute model.



8
9
10
# File 'lib/active_record/acts/partitioned/factory.rb', line 8

def model
  @model
end

#partition_classObject (readonly)

Returns the value of attribute partition_class.



8
9
10
# File 'lib/active_record/acts/partitioned/factory.rb', line 8

def partition_class
  @partition_class
end

Instance Method Details

#archive?Boolean

Returns:

  • (Boolean)


117
118
119
# File 'lib/active_record/acts/partitioned/factory.rb', line 117

def archive?
   @options[:archive] || false
end

#clearObject



72
73
74
75
76
# File 'lib/active_record/acts/partitioned/factory.rb', line 72

def clear
  partition_class.find(:all).each do |partition|
    partition.drop!
  end
end

#copy(filename, db_name = nil) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
# File 'lib/active_record/acts/partitioned/factory.rb', line 48

def copy(filename, db_name = nil)
  port, host, user, db = if db_name
    config = ActiveRecord::Base.configurations[db_name.to_s]
    raise "No such DB configuration: #{db_name}" unless config
    [config['port'], config['host'], config['username'], config['database']]
  else
    conn = @model.connection.raw_connection
    [conn.port, conn.host, conn.user, conn.db]
  end
  "psql --set ON_ERROR_STOP=1 --single-transaction -p #{port} -h #{host} -U #{user} #{db} < #{filename}"
end

#create(key_hash) ⇒ Object

Arguments are the keys specified in creation as a hash eg: create(:date => Date.today, :domain => domain)



62
63
64
65
66
67
68
69
70
# File 'lib/active_record/acts/partitioned/factory.rb', line 62

def create(key_hash)
  # TODO: Raise if a key missing
  @model.transaction do
    partition = partition_class.create!(key_hash)
    @keys.create_partition_tables(@model, :key_hash => key_hash)
    # TODO: Indexes
    partition
  end
end

#dump_ageObject



109
110
111
112
113
114
115
# File 'lib/active_record/acts/partitioned/factory.rb', line 109

def dump_age
   if @options[:dump_age].kind_of?(Proc)
     @options[:dump_age].call || 0
   else
     @options[:dump_age] || 0
   end
end

#find_for(_hash) ⇒ Object

Finds a partition to which these keys belong Not by keys used to create the partition This is the same thing for discrete keys but for continuous (ie; ranged keys) the end points of a range may not equal the values stored in the part Here we see if a value fits within the range Use this method if you want to know which partition to write data to



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/active_record/acts/partitioned/factory.rb', line 87

def find_for(_hash)
  hash = _hash.symbolize_keys
  conditions = {}
  @keys.each do |key|
    value = hash[key.column.to_sym]
    raise "No value provided for #{key.column}" unless value
    case key.type
      when :discrete
        conditions[key.column.to_sym] = value
      when :continuous
        conditions[:"#{key.column}_begin"] = value.begin
        conditions[:"#{key.column}_end"] = value.end
        conditions[:"#{key.column}_exclusive"] = value.exclude_end?
    end
  end
  partition_class.find_by(conditions)
end

#find_or_create_for(hash) ⇒ Object



105
106
107
# File 'lib/active_record/acts/partitioned/factory.rb', line 105

def find_or_create_for(hash)
  find_for(hash) || create(hash)
end

#init(options = {:force => false}) ⇒ Object



44
45
46
# File 'lib/active_record/acts/partitioned/factory.rb', line 44

def init(options = {:force => false})
  Structure.init_partition_catalog(model, @keys, options)
end

#partition_by(column, options = {}) ⇒ Object



24
25
26
27
# File 'lib/active_record/acts/partitioned/factory.rb', line 24

def partition_by(column, options = {})
  # TODO: Raise if caller tries to partition on primary key
  @keys << Key.new(column, options)
end

#set_validationsObject

TODO: Private?



31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/active_record/acts/partitioned/factory.rb', line 31

def set_validations
  # TODO: Move below this line to the partition class itself
  @keys.each do |key|
    case key.type
      when :continuous
        partition_class.validates_uniqueness_of("#{key.column}_begin", :scope => @keys.remaining_columns("#{key.column}_begin"))
        partition_class.validates_uniqueness_of("#{key.column}_end", :scope => @keys.remaining_columns("#{key.column}_end"))
      when :discrete
        partition_class.validates_uniqueness_of(key.column, :scope => @keys.remaining_columns(key.column))
    end
  end
end