Class: TableSetter::Table

Inherits:
Object
  • Object
show all
Defined in:
lib/table_setter/table.rb

Instance Attribute Summary

Class Method Summary

Instance Method Summary

Constructor Details

- (Table) initialize(slug, opts = {:defer => false})

A new Table should accept a slug, mapped to a yaml in the tables directory, optionally you can defer loading of the table until you’re ready to render it.



14
15
16
17
18
19
20
21
22
# File 'lib/table_setter/table.rb', line 14

def initialize(slug, opts={:defer => false})
  options = indifferent_access YAML.load_file(Table.table_path(slug))
  @table_opts = options[:table]
  @table_opts[:slug] = slug
  @deferred = opts[:defer]
  if !@deferred
    self.load
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

- (Object) method_missing(method)

We magically need access to the top level keys like google_key, or uri for the other methods. It’s a bit dangerous because everything returns nil otherwise. At some point we should eval and create methods at boot time.



110
111
112
113
114
# File 'lib/table_setter/table.rb', line 110

def method_missing(method)
  if @table_opts[method]
    @table_opts[method]
  end
end

Instance Attribute Details

- (Object) data (readonly)

The Table class handles processing the yaml processing and csv loading, through table fu



10
11
12
# File 'lib/table_setter/table.rb', line 10

def data
  @data
end

- (Object) facets (readonly)

The Table class handles processing the yaml processing and csv loading, through table fu



10
11
12
# File 'lib/table_setter/table.rb', line 10

def facets
  @facets
end

- (Object) next_page (readonly)

The Table class handles processing the yaml processing and csv loading, through table fu



10
11
12
# File 'lib/table_setter/table.rb', line 10

def next_page
  @next_page
end

- (Object) page (readonly)

The Table class handles processing the yaml processing and csv loading, through table fu



10
11
12
# File 'lib/table_setter/table.rb', line 10

def page
  @page
end

- (Object) prev_page (readonly)

The Table class handles processing the yaml processing and csv loading, through table fu



10
11
12
# File 'lib/table_setter/table.rb', line 10

def prev_page
  @prev_page
end

- (Object) table_opts (readonly)

The Table class handles processing the yaml processing and csv loading, through table fu



10
11
12
# File 'lib/table_setter/table.rb', line 10

def table_opts
  @table_opts
end

Class Method Details

+ (Object) all

Returns all the tables in the table directory. Each table is deferred so accessing the @data attribute will throw and error.



176
177
178
179
180
181
182
183
# File 'lib/table_setter/table.rb', line 176

def all
  tables=[] 
  Dir.glob("#{TableSetter.table_path}/*.yml").each do |file|
    table = new(File.basename(file, ".yml"), :defer => true)
    tables << table if table.live
  end
  tables
end

+ (Boolean) exists?(slug)

Does a table with this slug exist?

Returns:

  • (Boolean)


207
208
209
# File 'lib/table_setter/table.rb', line 207

def exists?(slug)
  File.exists? table_path(slug)
end

+ (Object) fresh_yaml_time

fresh_yaml_time checks each file in the tables directory and returns the newest file’s modification time — there’s probably a more unix-y way to do this but for now this is plenty speedy.



188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/table_setter/table.rb', line 188

def fresh_yaml_time
  newest_file = Dir["#{TableSetter.table_path}/*.yml"].inject do |memo, obj|
    memo_time = File.new(File.expand_path memo).mtime
    obj_time = File.new(File.expand_path obj).mtime
    if memo_time > obj_time
      memo
    else 
      obj
    end
  end
  File.new(newest_file).mtime
end

+ (Object) table_path(slug)

Convenience method for looking up by slug.



202
203
204
# File 'lib/table_setter/table.rb', line 202

def table_path(slug)
  "#{TableSetter.table_path}#{slug}.yml"
end

Instance Method Details

- (Object) csv_data

The csv_data for the table fu instance is loaded either from the remote source or from a local file, depending on the keys present in the yaml file.



39
40
41
42
43
44
# File 'lib/table_setter/table.rb', line 39

def csv_data
  case
  when google_key || url then Curl::Easy.perform(uri).body_str
  when file then File.open(uri).read
  end
end

- (Boolean) faceted?

Returns:

  • (Boolean)


62
63
64
# File 'lib/table_setter/table.rb', line 62

def faceted?
  !@facets.nil?
end

- (Boolean) hard_paginate?

hard_paginate instructs the app to render batches of a table.

Returns:

  • (Boolean)


72
73
74
# File 'lib/table_setter/table.rb', line 72

def hard_paginate?
  @table_opts[:hard_paginate] == true
end

- (Object) load

The load method handles the actual request either to the file system or remote url. It performs the requested data manipulations form the yml file after the data has been loaded. We’re keeping this explicit to control against unnecessary http requests.



27
28
29
30
31
32
33
34
35
# File 'lib/table_setter/table.rb', line 27

def load
  csv = csv_data
  @data = TableFu.new(csv_data, @table_opts[:column_options] || {})
  if @table_opts[:faceting]
    @data.col_opts[:ignored] = [@table_opts[:faceting][:facet_by]]
    @facets = @data.faceted_by @table_opts[:faceting][:facet_by]
  end
  @data.delete_rows! @table_opts[:dead_rows] if @table_opts[:dead_rows]
end

- (Object) paginate!(curr_page)

paginate uses TableFu’s only! method to batch the table. It also computes the page attributes which are nil and meaningless otherwise.

Raises:

  • (ArgumentError)


83
84
85
86
87
88
89
90
91
# File 'lib/table_setter/table.rb', line 83

def paginate!(curr_page)
  return if !hard_paginate?
  @page = curr_page.to_i
  raise ArgumentError if @page < 1 || @page > total_pages
  adj_page = @page - 1 > 0 ? @page - 1 : 0 
  @prev_page = adj_page > 0 ? adj_page : nil
  @next_page = page < total_pages ? (@page + 1) : nil
  @data.only!(adj_page * per_page..(@page * per_page - 1))
end

- (Object) per_page

The number of rows per page. Defaults to 20



77
78
79
# File 'lib/table_setter/table.rb', line 77

def per_page
  @table_opts[:per_page] || 20
end

- (Object) sort_array

A convienence method to return the sort array for table setter.



101
102
103
104
105
# File 'lib/table_setter/table.rb', line 101

def sort_array
  @data.sorted_by.inject([]) do |memo, (key, value)|
    memo << [@data.columns.index(key), value == 'descending' ? 0 : 1]
  end
end

- (Boolean) sortable?

A table isn’t sortable by tablesorter if it’s either faceted or multi-page paginated.

Returns:

  • (Boolean)


67
68
69
# File 'lib/table_setter/table.rb', line 67

def sortable?
  !faceted? && !hard_paginate?
end

- (Object) total_pages

The total pages we’ll have. We need to calculate it before paginate, so that we still have the full @data.rows.length



96
97
98
# File 'lib/table_setter/table.rb', line 96

def total_pages
  @total_pages ||= (@data.rows.length / per_page.to_f).ceil
end

- (Object) updated_at

The real updated_at of a Table instance is the newer modification time of the csv file or the yaml file. Updates to either resource should break the cache.



57
58
59
60
# File 'lib/table_setter/table.rb', line 57

def updated_at
  csv_time = google_key.nil? ? modification_time(uri) : google_modification_time
  (csv_time > yaml_time ? csv_time : yaml_time).to_s
end

- (Object) uri

Returns a usable uri based on what sort of input we have.



47
48
49
50
51
52
53
# File 'lib/table_setter/table.rb', line 47

def uri
  case 
  when google_key then "http://spreadsheets.google.com/pub?key=#{google_key}&output=csv"
  when url then url
  when file then File.expand_path("#{TableSetter.table_path}#{file}")
  end
end