Class: ActiveTsv::Relation

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/active_tsv/relation.rb

Constant Summary collapse

BUF_SIZE =
1024

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model) ⇒ Relation

Returns a new instance of Relation.



14
15
16
17
18
19
# File 'lib/active_tsv/relation.rb', line 14

def initialize(model)
  @model = model
  @where_values = []
  @order_values = []
  @group_values = []
end

Instance Attribute Details

#group_valuesObject

Returns the value of attribute group_values.



12
13
14
# File 'lib/active_tsv/relation.rb', line 12

def group_values
  @group_values
end

#modelObject (readonly)

Returns the value of attribute model.



9
10
11
# File 'lib/active_tsv/relation.rb', line 9

def model
  @model
end

#order_valuesObject

Returns the value of attribute order_values.



11
12
13
# File 'lib/active_tsv/relation.rb', line 11

def order_values
  @order_values
end

#where_valuesObject

Returns the value of attribute where_values.



10
11
12
# File 'lib/active_tsv/relation.rb', line 10

def where_values
  @where_values
end

Instance Method Details

#==(other) ⇒ Object



27
28
29
30
31
# File 'lib/active_tsv/relation.rb', line 27

def ==(other)
  where_values == other.where_values &&
    order_values == other.order_values &&
    group_values == other.group_values
end

#countObject



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/active_tsv/relation.rb', line 121

def count
  if @group_values.empty?
    super
  else
    h = if @group_values.one?
      group_by { |i| i[@group_values.first] }
    else
      group_by { |i| @group_values.map { |c| i[c] } }
    end
    h.each do |k, v|
      h[k] = v.count
    end
    h
  end
end

#each(*args, &block) ⇒ Object



149
150
151
# File 'lib/active_tsv/relation.rb', line 149

def each(*args, &block)
  to_a.each(*args, &block)
end

#exists?Boolean

Returns:

  • (Boolean)


75
76
77
# File 'lib/active_tsv/relation.rb', line 75

def exists?
  !first.nil?
end

#find(*ids) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/active_tsv/relation.rb', line 33

def find(*ids)
  case ids.length
  when 0
    raise ActiveTsv::RecordNotFound, "Couldn't find #{@model} without an ID"
  when 1
    id = ids.first
    record = where(@model.primary_key => id).first
    unless record
      raise ActiveTsv::RecordNotFound, "Couldn't find #{@model} with '#{@model.primary_key}'=#{id}"
    end
    record
  else
    records = where(@model.primary_key => ids).to_a
    unless ids.length == records.length
      raise ActiveTsv::RecordNotFound, "Couldn't find all #{@model} with '#{@model.primary_key}': (#{ids.join(', ')}) (found #{records.length} results, but was looking for #{ids.length})"
    end
    records
  end
end

#firstObject



79
80
81
82
83
84
85
# File 'lib/active_tsv/relation.rb', line 79

def first
  if @order_values.empty?
    each_model.first
  else
    to_a.first
  end
end

#group(*columns) ⇒ Object



143
144
145
146
147
# File 'lib/active_tsv/relation.rb', line 143

def group(*columns)
  @group_values += columns
  @group_values.uniq!
  self
end

#initialize_copy(copy) ⇒ Object



21
22
23
24
25
# File 'lib/active_tsv/relation.rb', line 21

def initialize_copy(copy)
  copy.where_values = where_values.dup
  copy.order_values = order_values.dup
  copy.group_values = group_values.dup
end

#inspectObject



157
158
159
160
161
162
# File 'lib/active_tsv/relation.rb', line 157

def inspect
  a = to_value_a.take(11).map! { |i| @model.new(i) }.map!(&:inspect)
  a[10] = '...' if a.length == 11

  "#<#{self.class.name} [#{a.join(', ')}]>"
end

#lastObject



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/active_tsv/relation.rb', line 87

def last
  if @where_values.empty? && @order_values.empty?
    last_value = File.open(@model.table_path, "r:#{@model.encoding}:UTF-8") do |f|
      f.seek(0, IO::SEEK_END)
      buf_size = [f.size, self.class::BUF_SIZE].min
      while true
        f.seek(-buf_size, IO::SEEK_CUR)
        buf = f.read(buf_size)
        if index = buf.rindex($INPUT_RECORD_SEPARATOR, -2)
          f.seek(-buf_size + index + 1, IO::SEEK_CUR)
          break f.read.chomp
        else
          f.seek(-buf_size, IO::SEEK_CUR)
        end
      end
    end
    @model.new(CSV.new(last_value, col_sep: @model::SEPARATER).shift)
  else
    @model.new(to_value_a.last)
  end
end

#maximum(column) ⇒ Object



164
165
166
# File 'lib/active_tsv/relation.rb', line 164

def maximum(column)
  pluck(column).max
end

#minimum(column) ⇒ Object



168
169
170
# File 'lib/active_tsv/relation.rb', line 168

def minimum(column)
  pluck(column).min
end

#order(*columns) ⇒ Object



137
138
139
140
141
# File 'lib/active_tsv/relation.rb', line 137

def order(*columns)
  @order_values += order_conditions(columns)
  @order_values.uniq!
  self
end

#pluck(*fields) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
# File 'lib/active_tsv/relation.rb', line 63

def pluck(*fields)
  key_to_value_index = @model.column_names.each_with_index.to_h
  if fields.empty?
    to_value_a
  elsif fields.one?
    to_value_a.map! { |v| v[key_to_value_index[fields.first.to_s]] }
  else
    indexes = fields.map(&:to_s).map! { |field| key_to_value_index[field] }
    to_value_a.map! { |v| v.values_at(*indexes) }
  end
end

#take(n = nil) ⇒ Object



109
110
111
112
113
114
115
116
117
118
119
# File 'lib/active_tsv/relation.rb', line 109

def take(n = nil)
  if n
    if @order_values.empty?
      each_model.take(n)
    else
      to_value_a.take(n).map! { |i| @model.new(i) }
    end
  else
    first
  end
end

#to_aObject



153
154
155
# File 'lib/active_tsv/relation.rb', line 153

def to_a
  to_value_a.map! { |v| @model.new(v) }
end

#where(where_value = nil) ⇒ Object



53
54
55
56
57
58
59
60
61
# File 'lib/active_tsv/relation.rb', line 53

def where(where_value = nil)
  if where_value
    dup.tap do |r|
      r.where_values << Condition::Equal.new(where_value)
    end
  else
    WhereChain.new(dup)
  end
end