fix error

This commit is contained in:
邱博亞 2022-02-25 14:49:00 +08:00
parent aeffcf2630
commit 0d8972ea29
22 changed files with 394 additions and 93 deletions

View File

@ -8,6 +8,32 @@ class Admin::UniversalTablesController < OrbitAdminController
end end
def update_sort
uid = params[:universal_table_id].split("-").last
@table = UTable.where(:uid => uid).first rescue nil
if !@table.nil?
ids = params[:ids]
ids = ids.reverse if @table.sort_number_order_direction=='desc'
ids.each_with_index do |id,i|
TableEntry.where(id: id).update(sort_number: i)
end
@entries = TableEntry.where(u_table_id: @table.id).sorting(params: params,table: @table)
@columns = @table.table_columns.asc(:order)
@table_fields = ['universal_table.sort_number']+@columns.collect{|tc| tc.title} + ['universal_table.created_at']
render 'update_sort',layout: false
end
end
def edit_sort
uid = params[:universal_table_id].split("-").last
@table = UTable.where(:uid => uid).first rescue nil
if !@table.nil?
@entries = TableEntry.where(u_table_id: @table.id).sorting(params: params,table: @table)
@columns = @table.table_columns.asc(:order)
@table_fields = ['universal_table.sort_number']+@columns.collect{|tc| tc.title} + ['universal_table.created_at']
end
end
def show def show
uid = params[:id].split("-").last uid = params[:id].split("-").last
@table = UTable.where(:uid => uid).first rescue nil @table = UTable.where(:uid => uid).first rescue nil
@ -17,7 +43,7 @@ class Admin::UniversalTablesController < OrbitAdminController
if params[:q].present? if params[:q].present?
@entries = search_data(@table) @entries = search_data(@table)
else else
@entries = @table.table_entries.criteria.sorting(params: params,table: @table,page_num: params[:page],per: 10) @entries = TableEntry.where(u_table_id: @table.id).sorting(params: params,table: @table,page_num: params[:page],per: 10)
end end
end end
end end
@ -88,6 +114,8 @@ class Admin::UniversalTablesController < OrbitAdminController
skip = skip + 1 skip = skip + 1
end end
ce.text_translations = v ce.text_translations = v
when "integer"
ce.number = (val.blank? ? nil : val)
when "editor" when "editor"
v = {} v = {}
@site_in_use_locales.sort.each_with_index do |locale,x| @site_in_use_locales.sort.each_with_index do |locale,x|
@ -110,6 +138,7 @@ class Admin::UniversalTablesController < OrbitAdminController
ce.period_to = val ce.period_to = val
end end
ce.table_column_id = tc.id ce.table_column_id = tc.id
ce.u_table_id = table.id
ce.save ce.save
te.column_entries << ce te.column_entries << ce
end end

View File

@ -34,13 +34,22 @@ class UniversalTablesController < ApplicationController
sort_class = "sort hide" sort_class = "sort hide"
when "text" when "text"
if tc.make_categorizable if tc.make_categorizable
select_values = tc.column_entries.distinct(:text).uniq select_values = tc.column_entries.distinct(:text)
form_field = "<input type=\"hidden\" name=\"authenticity_token\" value=\"#{csrf_value}\"><select class='form-control' name='q'>" form_field = "<input type=\"hidden\" name=\"authenticity_token\" value=\"#{csrf_value}\"><select class='form-control' name='q'>"
select_values.each do |sv| select_values.each do |sv|
form_field = form_field + "<option value='#{sv[I18n.locale.to_s]}'>#{sv[I18n.locale.to_s]}</option>" form_field = form_field + "<option value='#{sv[I18n.locale.to_s]}'>#{sv[I18n.locale.to_s]}</option>"
end end
form_field = form_field + "</select>" form_field = form_field + "</select>"
end end
when "integer"
if tc.make_categorizable
select_values = tc.column_entries.distinct(:number)
form_field = "<input type=\"hidden\" name=\"authenticity_token\" value=\"#{csrf_value}\"><select class='form-control' name='q'>"
select_values.each do |sv|
form_field = form_field + "<option value='#{sv}'>#{sv}</option>"
end
form_field = form_field + "</select>"
end
end end
if params["sortcolumn"] == tc.key if params["sortcolumn"] == tc.key
@ -77,6 +86,8 @@ class UniversalTablesController < ApplicationController
case ce.type case ce.type
when "text" when "text"
text = ce.text text = ce.text
when "integer"
text = ce.number
when "editor" when "editor"
text = ce.content text = ce.content
when "date" when "date"
@ -146,6 +157,8 @@ class UniversalTablesController < ApplicationController
case ce.type case ce.type
when "text" when "text"
text = ce.text text = ce.text
when "integer"
text = ce.number
when "editor" when "editor"
text = ce.content text = ce.content
when "date" when "date"
@ -215,6 +228,8 @@ class UniversalTablesController < ApplicationController
case ce.type case ce.type
when "text" when "text"
text = ce.text text = ce.text
when "integer"
text = ce.number
when "editor" when "editor"
text = ce.content text = ce.content
when "date" when "date"

View File

@ -28,4 +28,16 @@ module Admin::UniversalTablesHelper
"<div class='select-holder'> <span>Or</span> " + select + "</div>" "<div class='select-holder'> <span>Or</span> " + select + "</div>"
end end
def render_unique_number(f,column,i)
select_values = column.column_entries.distinct(:number).uniq
select = "<select id='#{column.key}_#{i}'>"
s = ""
select = select + "<option class='muted' value='#{s}'>---------------Select---------------</option>"
select_values.each do |sv|
select = select + "<option value='#{sv}'>#{sv}</option>"
end
select = select + "</select>"
"<div class='select-holder'> <span>Or</span> " + select + "</div>"
end
end end

View File

@ -7,6 +7,7 @@ class ColumnEntry
field :date, type: DateTime field :date, type: DateTime
field :period_from, type: DateTime field :period_from, type: DateTime
field :period_to, type: DateTime field :period_to, type: DateTime
field :number, type: Integer
mount_uploader :image, ImageUploader mount_uploader :image, ImageUploader

View File

@ -19,6 +19,8 @@ class TableColumn
case self.type case self.type
when "text" when "text"
{text: direction} {text: direction}
when "integer"
{number: direction}
when "editor" when "editor"
{content: direction} {content: direction}
when "image" when "image"

View File

@ -4,13 +4,20 @@ class TableEntry
include Slug include Slug
attr_accessor :sort_value attr_accessor :sort_value
field :sort_number, type: Integer, default: 0 field :sort_number, type: Integer
has_many :column_entries, :dependent => :destroy has_many :column_entries, :dependent => :destroy
belongs_to :u_table belongs_to :u_table
accepts_nested_attributes_for :column_entries, :allow_destroy => true accepts_nested_attributes_for :column_entries, :allow_destroy => true
before_save do
if self[:sort_number].nil?
sort_number_to_set = self.class.where(u_table_id: self.u_table_id).order_by(sort_number: :desc).first.sort_number
self.sort_number = sort_number_to_set + 1
end
end
def self.u_table def self.u_table
UTable.find(criteria.selector['u_table_id']) UTable.find(criteria.selector['u_table_id'])
end end
@ -30,23 +37,30 @@ class TableEntry
direction = params[:order].blank? ? 'desc' : params[:order] direction = params[:order].blank? ? 'desc' : params[:order]
end end
if field.nil? if field.nil?
field = table.default_ordered_field field,direction = table.default_ordered
if field != 'created_at' else
columns = table.table_columns field = field.to_s
sort_column = columns.where(:key=>field).first || columns.where(:title=>field).first if !(field=='created_at' || field == 'sort_number')
direction = sort_column.order_direction field = table.table_columns.where(key: field).first || table.table_columns.where(title: field).first
end end
end end
end end
field = field.to_s if (field=='created_at' || field == 'sort_number')
if (field=='created_at' || field == 'sort_number') && column_entries.nil? if column_entries.nil?
values = self.order_by({field => direction}) values = self.order_by({field => direction})
if !per.nil? if !per.nil?
values = values.page(page_num).per(per) values = values.page(page_num).per(per)
end end
else else
column_to_sort = table.table_columns.where(key: field).first || table.table_columns.where(title: field).first values = column_entries.map{|v| v.table_entry}
values = values.sort_by{|v| v.send(field)}
if direction == 'desc'
values = values.reverse
end
end
else
column_to_sort = field
if column_entries.nil? if column_entries.nil?
if criteria.selector.keys != ['u_table_id'] if criteria.selector.keys != ['u_table_id']
column_entries = ColumnEntry.where(:table_column_id=>column_to_sort.id,:table_entry_id.in => criteria.pluck(:id)).order_by(column_to_sort.sort_hash(direction)) column_entries = ColumnEntry.where(:table_column_id=>column_to_sort.id,:table_entry_id.in => criteria.pluck(:id)).order_by(column_to_sort.sort_hash(direction))

View File

@ -6,15 +6,35 @@ class UTable
field :title, as: :slug_title, localize: true field :title, as: :slug_title, localize: true
field :ordered_with_sort_number, type: Boolean, default: false
field :sort_number_order_direction, type: String, default: 'desc'
field :ordered_with_created_at, type: Boolean, default: true
field :created_at_order_direction, type: String, default: 'desc'
has_many :table_columns, :dependent => :destroy has_many :table_columns, :dependent => :destroy
has_many :table_entries, :dependent => :destroy has_many :table_entries, :dependent => :destroy
accepts_nested_attributes_for :table_columns, :allow_destroy => true accepts_nested_attributes_for :table_columns, :allow_destroy => true
FIELD_TYPES = ["text", "editor", "image", "date", "period"] FIELD_TYPES = ["text", "integer", "editor", "image", "date", "period"]
DATE_FORMATS = ["yyyy/MM/dd hh:mm", "yyyy/MM/dd","yyyy/MM", "yyyy"] DATE_FORMATS = ["yyyy/MM/dd hh:mm", "yyyy/MM/dd","yyyy/MM", "yyyy"]
def default_ordered_field def default_ordered
f = self.table_columns.where(default_ordered_field: true).first if self.ordered_with_created_at
f ? (f.key||f.title) : 'created_at' sort_column = 'created_at'
direction = self.created_at_order_direction
elsif self.ordered_with_sort_number
sort_column = 'sort_number'
direction = self.sort_number_order_direction
else
sort_column = self.table_columns.where(default_ordered_field: true).first
if sort_column
direction = sort_column.order_direction
else
sort_column = 'created_at'
direction = self.created_at_order_direction
end
end
[sort_column,direction]
end end
end end

View File

@ -70,7 +70,7 @@
<div class="controls"> <div class="controls">
<% select_values = UTable::FIELD_TYPES.collect{|ft| [ft.capitalize,ft]} %> <% select_values = UTable::FIELD_TYPES.collect{|ft| [ft.capitalize,ft]} %>
<%= f.select :type, select_values, {}, {class: "type-selector"} %> <%= f.select :type, select_values, {}, {class: "type-selector"} %>
<span class="link_to_show <%= !defined?(i) || column.type == "text" ? "" : "hide" %>"> <span class="link_to_show <%= (!defined?(i) || column.type == "text" || column.type == "integer") ? "" : "hide" %>">
<label class="checkbox inline attributes-checkbox "> <label class="checkbox inline attributes-checkbox ">
<%= f.check_box :is_link_to_show %> Link to show <%= f.check_box :is_link_to_show %> Link to show
</label> </label>

View File

@ -0,0 +1,79 @@
<div id="data-table" class="ut-table">
<table class="table main-list">
<thead>
<tr class="sort-header">
<% @table_fields.each do |field| %>
<%
field_text = field.to_s.include?('.') ? t(field.to_s) : field.to_s
sort = field.to_s.split('.')[-1]
active = params[:sort].eql? sort
order = active ? (["asc", "desc"]-[params[:order]]).first : "asc"
arrow = (order.eql? "desc") ? "<b class='icons-arrow-up-3'></b>" : "<b class='icons-arrow-down-4'></b>"
klass = field.eql?(:title) ? "span5" : "span2"
th_data = "<a href='?sort=#{sort}&order=#{order}'>#{field_text} #{active ? arrow : ""}</a>"
%>
<th class='<%= klass %> <%= active ? "active" : "" %>'><%= th_data.html_safe %></th>
<% end %>
</tr>
</thead>
<tbody id="sortable">
<% can_edit = can_edit_or_delete?(@entries.first.u_table) if !(@entries.first.nil?) %>
<% @entries.each do |entry| %>
<tr data-id="<%= entry.id %>">
<td>
<%= entry.sort_number %>
</td>
<% @columns.each_with_index do |column, index| %>
<% ce = entry.column_entries.where(:table_column_id => column.id).first rescue nil %>
<% if !ce.nil? %>
<td>
<% case ce.type %>
<% when "text" %>
<%= ce.text %>
<% when "integer" %>
<%= ce.number %>
<% when "editor" %>
<%= ce.content.html_safe rescue "" %>
<% when "image" %>
<div class="image-expander">
<% if !ce.image.nil? %>
<a href="<%= ce.image.url %>" target="_blank"><img src="<%= ce.image.thumb.url %>" class="image-preview" /></a>
<% end %>
</div>
<% when "date" %>
<%= format_date(ce.date, column.date_format) %>
<% when "period" %>
<% if !ce.period_from.nil? %>
<%= format_date(ce.period_from, column.date_format) %> ~ <%= format_date(ce.period_to, column.date_format) %>
<% end %>
<% end %>
<% if index == 0 && can_edit %>
<div class="quick-edit">
<ul class="nav nav-pills">
<li><a href="<%= admin_universal_table_edit_entry_path(entry) %>"><%= t(:edit) %></a></li>
<li><a href="<%= admin_universal_table_delete_entry_path(entry.id) %>" class="delete text-error" data-method="delete" data-confirm="Are you sure?"><%= t(:delete_) %></a></li>
</ul>
</div>
<% end %>
</td>
<% else %>
<td>
&nbsp;
</td>
<% end %>
<% end %>
<td>
<%= entry.created_at %>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>

View File

@ -24,18 +24,7 @@
%> %>
<% end %> <% end %>
<%= f.fields_for :column_entries, object, :child_index => index do |f| %> <%= f.fields_for :column_entries, object, :child_index => index do |f| %>
<% case column.type %> <%= render :partial => "#{column.type}_field", :object => object, :locals => {:f => f, :column => column, :i => index} %>
<% when "text" %>
<%= render :partial => "text_field", :object => object, :locals => {:f => f, :column => column, :i => index} %>
<% when "editor" %>
<%= render :partial => "editor_field", :object => object, :locals => {:f => f, :column => column, :i => index} %>
<% when "image" %>
<%= render :partial => "image_field", :object => object, :locals => {:f => f, :column => column, :i => index} %>
<% when "date" %>
<%= render :partial => "date_field", :object => object, :locals => {:f => f, :column => column, :i => index} %>
<% when "period" %>
<%= render :partial => "period_field", :object => object, :locals => {:f => f, :column => column, :i => index} %>
<% end %>
<% end %> <% end %>
<% end %> <% end %>
</div> </div>

View File

@ -16,6 +16,9 @@
<ul class="nav nav-pills"> <ul class="nav nav-pills">
<% if can_edit %> <% if can_edit %>
<li><a href="<%= edit_admin_universal_table_path(table) %>"><%= t(:edit) %></a></li> <li><a href="<%= edit_admin_universal_table_path(table) %>"><%= t(:edit) %></a></li>
<% if table.ordered_with_sort_number %>
<li><a href="<%= admin_universal_table_edit_sort_path(table) %>"><%= t('universal_table.edit_sort') %></a></li>
<% end %>
<li><a href="/admin/universal_tables/<%=table.id.to_s%>/export_data?format=xlsx" data-table-id="<%= table.id.to_s %>" class="export-xls"><%= t('universal_table.export_xls') %></a></li> <li><a href="/admin/universal_tables/<%=table.id.to_s%>/export_data?format=xlsx" data-table-id="<%= table.id.to_s %>" class="export-xls"><%= t('universal_table.export_xls') %></a></li>
<li><a href="<%= admin_universal_table_path(table) %>" class="delete text-error" data-method="delete" data-confirm="Are you sure?"><%= t(:delete_) %></a></li> <li><a href="<%= admin_universal_table_path(table) %>" class="delete text-error" data-method="delete" data-confirm="Are you sure?"><%= t(:delete_) %></a></li>
<% end %> <% end %>

View File

@ -0,0 +1,25 @@
<div class="control-group">
<%= f.label :number, column.title, :class => "control-label" %>
<div class="controls">
<div class="input-append">
<%= f.number_field :number, :value => integer_field.number %>
</div>
<% if column.make_categorizable %>
<%= render_unique_number(f,column,i).html_safe %>
<script type="text/javascript">
$("select#<%= column.key + "_" + i.to_s %>").on("change",function(){
var el = $(this),
value = el.val(),
inputs = el.parent().parent().find("input[type=number]");
inputs.val(value);
})
</script>
<% end %>
</div>
<% if !integer_field.new_record? %>
<%= f.hidden_field :id %>
<% else %>
<%= f.hidden_field :table_column_id, :value => column.id %>
<% end %>
</div>

View File

@ -34,6 +34,34 @@
</div> </div>
</fieldset> </fieldset>
<fieldset>
<div class="utable-heading-header">
<h4><%= t("universal_table.default_ordered_field") %></h4>
</div>
<div class="control-group">
<label class="control-label muted" for=""><%= t('universal_table.created_at') %></label>
<div class="controls">
<div>
<%= f.check_box :ordered_with_created_at, class: 'default_ordered_field ordered_with_created_at' %>
</div>
<div class="order_direction<%= ' hidden' if !f.object.ordered_with_created_at %>">
<%= f.select :created_at_order_direction,['desc','asc'].map{|v| [t("universal_table.#{v}"),v]} %>
</div>
</div>
</div>
<div class="control-group">
<label class="control-label muted" for=""><%= t('universal_table.sort_number') %></label>
<div class="controls">
<div>
<%= f.check_box :ordered_with_sort_number, class: 'default_ordered_field' %>
</div>
<div class="order_direction<%= ' hidden' if !f.object.ordered_with_sort_number %>">
<%= f.select :sort_number_order_direction,['desc','asc'].map{|v| [t("universal_table.#{v}"),v]} %>
</div>
</div>
</div>
</fieldset>
<fieldset class="utable-content"> <fieldset class="utable-content">
<div id="attributes-area" class="input-area"> <div id="attributes-area" class="input-area">
<% @table.table_columns.asc(:order).each_with_index do |table_column, index| %> <% @table.table_columns.asc(:order).each_with_index do |table_column, index| %>
@ -87,7 +115,7 @@
$(document.body).on("change","select.type-selector",function(){ $(document.body).on("change","select.type-selector",function(){
var el = $(this), var el = $(this),
label = el.parent().find("span.link_to_show"); label = el.parent().find("span.link_to_show");
if(el.val() == "text"){ if(el.val() == "text" || el.val() == "integer"){
label.removeClass("hide"); label.removeClass("hide");
}else{ }else{
label.addClass("hide"); label.addClass("hide");
@ -107,6 +135,12 @@
$(this).parents('.controls').eq(0).find('.order_direction').removeClass('hidden'); $(this).parents('.controls').eq(0).find('.order_direction').removeClass('hidden');
} }
}); });
$(document).ready(function(){
if ($('.ordered_with_created_at').prop('checked')){
$('.default_ordered_field').not($('.ordered_with_created_at')[0]).prop('checked',false);
$('.order_direction').not($('.ordered_with_created_at').eq(0).parents('.controls').eq(0).find('.order_direction')[0]).addClass('hidden');
}
})
function key_on_blur() { function key_on_blur() {
$('input[data-type=key]').on('blur',function() { $('input[data-type=key]').on('blur',function() {
var index_this = $(this).parents('.attributes').index() var index_this = $(this).parents('.attributes').index()

View File

@ -0,0 +1,40 @@
<% content_for :page_specific_css do %>
<%= stylesheet_link_tag "universal_table/universal-table" %>
<% end %>
<div style="margin-bottom: 1em;">
<button type="button" class="btn btn-primary" id="update_sort_button"><%= t('universal_table.manual_update_sort') %></button>
</div>
<%= render partial: 'edit_sort' %>
<script type="text/javascript">
function update_sort(){
var ids = $.map($('#sortable>tr'),function(v){return $(v).data('id')});
$.ajax({
url: "<%= admin_universal_table_update_sort_path(@table) %>",
type: 'POST',
dataType: 'text',
data: {ids: ids},
success: function(data){
$('#data-table').replaceWith(data);
sortable();
}
});
}
function sortable(){
$( "#sortable" ).sortable({
update: function( event, ui ) {
update_sort();
}
});
}
$(document).ready(function(){
$('#update_sort_button').click(update_sort);
sortable();
});
</script>

View File

@ -18,6 +18,10 @@ wb.add_worksheet(name: "Structure") do |sheet|
row1 << column.key row1 << column.key
row2 << column.type + "-#{locale}" row2 << column.type + "-#{locale}"
end end
when "integer"
row << column.title
row1 << column.key
row2 << column.type
when "editor" when "editor"
@site_in_use_locales.sort.each do |locale| @site_in_use_locales.sort.each do |locale|
row << column.title + " - " + t(locale.to_s) row << column.title + " - " + t(locale.to_s)

View File

@ -37,6 +37,8 @@
<% case ce.type %> <% case ce.type %>
<% when "text" %> <% when "text" %>
<%= ce.text %> <%= ce.text %>
<% when "integer" %>
<%= ce.number %>
<% when "editor" %> <% when "editor" %>
<%= ce.content.html_safe rescue "" %> <%= ce.content.html_safe rescue "" %>
<% when "image" %> <% when "image" %>

View File

@ -0,0 +1 @@
<%= render partial: 'edit_sort' %>

View File

@ -18,6 +18,10 @@ wb.add_worksheet(name: "Structure") do |sheet|
row1 << column.key row1 << column.key
row2 << column.type + "-#{locale}" row2 << column.type + "-#{locale}"
end end
when "integer"
row << column.title
row1 << column.key
row2 << column.type
when "editor" when "editor"
site_in_use_locales.sort.each do |locale| site_in_use_locales.sort.each do |locale|
row << column.title + " - " + t(locale.to_s) row << column.title + " - " + t(locale.to_s)
@ -52,6 +56,8 @@ wb.add_worksheet(name: "Structure") do |sheet|
site_in_use_locales.sort.each do |locale| site_in_use_locales.sort.each do |locale|
row << (column.text_translations[locale.to_s] rescue "") row << (column.text_translations[locale.to_s] rescue "")
end end
when "integer"
row << column.number
when "editor" when "editor"
site_in_use_locales.sort.each do |locale| site_in_use_locales.sort.each do |locale|
row << (column.content_translations[locale.to_s] rescue "") row << (column.content_translations[locale.to_s] rescue "")

View File

@ -14,3 +14,7 @@ en:
default_ordered_field: Default Ordered Field default_ordered_field: Default Ordered Field
asc: asc asc: asc
desc: desc desc: desc
sort_number: Sort Number
created_at: Created Time
edit_sort: Edit Sorting
manual_update_sort: Manually Update Sorting

View File

@ -14,3 +14,7 @@ zh_tw:
default_ordered_field: 預設排序欄位 default_ordered_field: 預設排序欄位
asc: 升序 asc: 升序
desc: 降序 desc: 降序
sort_number: 排序數
created_at: 創建時間
edit_sort: 編輯排序
manual_update_sort: 手動更新排序

View File

@ -12,6 +12,8 @@ Rails.application.routes.draw do
get "new_entry" get "new_entry"
delete "delete_entry" delete "delete_entry"
get "edit_entry" get "edit_entry"
get "edit_sort"
post "update_sort", to: 'universal_tables#update_sort'
get "export_structure" get "export_structure"
member do member do
get "export_data" get "export_data"

View File

@ -1,6 +1,21 @@
module UniversalTable module UniversalTable
class Engine < ::Rails::Engine class Engine < ::Rails::Engine
initializer "universal_table" do initializer "universal_table" do
if ENV['worker_num']=='0' && File.basename($0) != 'rake' && !Rails.const_defined?('Console')
require File.expand_path('../../../app/models/table_entry', __FILE__)
require File.expand_path('../../../app/models/u_table', __FILE__)
if defined?(TableEntry) && defined?(UTable)
if TableEntry.where(sort_number: nil).count>0
UTable.all.pluck(:id).each do |u_table_id|
table_entries = TableEntry.where(u_table_id: u_table_id).order_by(id: 1)
table_entry_ids = table_entries.pluck(:id)
table_entry_ids.each_with_index do |id,i|
TableEntry.where(id: id).update(sort_number: i)
end
end
end
end
end
OrbitApp.registration "UniversalTable", :type => "ModuleApp" do OrbitApp.registration "UniversalTable", :type => "ModuleApp" do
module_label "universal_table.universal_table" module_label "universal_table.universal_table"
base_url File.expand_path File.dirname(__FILE__) base_url File.expand_path File.dirname(__FILE__)