New fields updated_at and created_at

1.0
Fernando Blat 14 years ago
parent 94c2bda943
commit 706213e2f5

@ -14,7 +14,7 @@ class Table < Sequel::Model(:user_tables)
attr_accessor :force_schema, :import_from_file
CARTODB_COLUMNS = %W{ cartodb_id }
CARTODB_COLUMNS = %W{ cartodb_id created_at updated_at }
## Callbacks
def validate
@ -44,6 +44,8 @@ class Table < Sequel::Model(:user_tables)
String :name
column :location, 'geometry'
String :description, :text => true
DateTime :created_at, :default => "now()"
DateTime :updated_at, :default => "now()"
constraint(:enforce_geotype_location){"(geometrytype(location) = 'POINT'::text OR location IS NULL)"}
end
else
@ -57,8 +59,16 @@ class Table < Sequel::Model(:user_tables)
# If import_from_file is blank primary key is added now.
# If not we add it after importing the CSV file, becaus the number of columns
# will not match
sanitized_force_schema.unshift("cartodb_id SERIAL PRIMARY KEY") if import_from_file.blank?
if import_from_file.blank?
sanitized_force_schema.unshift("cartodb_id SERIAL PRIMARY KEY")
sanitized_force_schema.unshift("created_at timestamp")
sanitized_force_schema.unshift("updated_at timestamp")
end
user_database.run("CREATE TABLE #{self.name} (#{sanitized_force_schema.join(', ')})")
if import_from_file.blank?
user_database.run("alter table #{self.name} alter column created_at SET DEFAULT now()")
user_database.run("alter table #{self.name} alter column updated_at SET DEFAULT now()")
end
end
end
end
@ -161,9 +171,14 @@ class Table < Sequel::Model(:user_tables)
end
def schema
owner.in_database do |user_database|
temporal_schema = owner.in_database do |user_database|
user_database.schema(name.to_sym).map{ |c| [c.first, c[1][:db_type]] }
end
schema = temporal_schema.delete([:cartodb_id, "integer"])
schema = [schema] + temporal_schema
created_at = schema.delete([:created_at, "timestamp without time zone"])
updated_at = schema.delete([:updated_at, "timestamp without time zone"])
schema.push([:created_at, "timestamp"]).push([:updated_at, "timestamp"])
end
def add_column!(options)
@ -212,16 +227,20 @@ class Table < Sequel::Model(:user_tables)
end
def to_json(options = {})
rows, columns = [], []
rows = []
limit = (options[:rows_per_page] || 10).to_i
offset = (options[:page] || 0).to_i*limit
owner.in_database do |user_database|
columns = user_database.schema(name.to_sym).map{ |c| [c.first, c[1][:db_type]] }
rows = user_database[name.to_sym].limit(limit,offset).order(:cartodb_id).all
rows = user_database[name.to_sym].limit(limit,offset).
order(:cartodb_id).select(*schema.map{ |e| e[0]}).all.map do |row|
row[:created_at] = row[:created_at].strftime("%H:%M:%S %Y-%m-%d")
row[:updated_at] = row[:updated_at].strftime("%H:%M:%S %Y-%m-%d")
row
end
end
{
:total_rows => rows_counted,
:columns => columns,
:columns => schema,
:rows => rows
}
end
@ -270,6 +289,8 @@ class Table < Sequel::Model(:user_tables)
user_database.run("alter table #{self.name} add unique (cartodb_id)")
user_database.run("alter table #{self.name} drop constraint #{self.name}_cartodb_id_key restrict")
user_database.run("alter table #{self.name} add primary key (cartodb_id)")
user_database.run("alter table #{self.name} add column created_at timestamp DEFAULT now()")
user_database.run("alter table #{self.name} add column updated_at timestamp DEFAULT now()")
end
ensure
FileUtils.rm filename
@ -365,6 +386,19 @@ class Table < Sequel::Model(:user_tables)
CREATE TRIGGER protect_data_trigger
BEFORE UPDATE ON #{self.name}
FOR EACH ROW EXECUTE PROCEDURE protect_data();
DROP TRIGGER IF EXISTS update_updated_at_trigger ON #{self.name};
CREATE OR REPLACE FUNCTION update_updated_at() RETURNS TRIGGER AS $update_updated_at_trigger$
BEGIN
NEW.updated_at := now();
RETURN NEW;
END;
$update_updated_at_trigger$ LANGUAGE plpgsql;
CREATE TRIGGER update_updated_at_trigger
BEFORE UPDATE ON #{self.name}
FOR EACH ROW EXECUTE PROCEDURE update_updated_at();
TRIGGER
)
end

@ -24,14 +24,14 @@ feature "Tables JSON API" do
response.status.should == 200
json_response = JSON(response.body)
json_response['total_rows'].should == 100
json_response['rows'][0].symbolize_keys.should == content[0]
json_response['rows'][1].symbolize_keys.should == content[1]
json_response['rows'][0].symbolize_keys.slice(:cartodb_id, :name, :location, :description).should == content[0].slice(:cartodb_id, :name, :location, :description)
json_response['rows'][1].symbolize_keys.slice(:cartodb_id, :name, :location, :description).should == content[1].slice(:cartodb_id, :name, :location, :description)
get_json "/api/json/tables/#{table.id}?rows_per_page=2&page=1"
response.status.should == 200
json_response = JSON(response.body)
json_response['rows'][0].symbolize_keys.should == content[2]
json_response['rows'][1].symbolize_keys.should == content[3]
json_response['rows'][0].symbolize_keys.slice(:cartodb_id, :name, :location, :description).should == content[2].slice(:cartodb_id, :name, :location, :description)
json_response['rows'][1].symbolize_keys.slice(:cartodb_id, :name, :location, :description).should == content[3].slice(:cartodb_id, :name, :location, :description)
end
scenario "Update the privacy status of a table" do
@ -111,7 +111,7 @@ feature "Tables JSON API" do
get_json "/api/json/tables/#{table.id}/schema"
response.status.should == 200
json_response = JSON(response.body)
json_response.should == [["cartodb_id", "integer"], ["name", "text"], ["location", "geometry"], ["description", "text"]]
json_response.should == [["cartodb_id", "integer"], ["name", "text"], ["location", "geometry"], ["description", "text"], ["created_at", "timestamp"], ["updated_at", "timestamp"]]
end
scenario "Get a list of tables" do
@ -156,7 +156,11 @@ feature "Tables JSON API" do
json_response = JSON(response.body)
json_response.should == {"name" => "postal_code", "type" => 'integer'}
table.reload
table.schema.should == [[:cartodb_id, "integer"], [:name, "text"], [:location, "geometry"], [:description, "text"], [:postal_code, "integer"]]
table.schema.should == [
[:cartodb_id, "integer"], [:name, "text"], [:location, "geometry"],
[:description, "text"], [:postal_code, "integer"],
[:created_at, "timestamp"], [:updated_at, "timestamp"]
]
put_json "/api/json/tables/#{table.id}/update_schema", {
:what => "modify", :column => {
@ -167,7 +171,10 @@ feature "Tables JSON API" do
json_response = JSON(response.body)
json_response.should == {"name" => "postal_code", "type" => 'text'}
table.reload
table.schema.should == [[:cartodb_id, "integer"], [:name, "text"], [:location, "geometry"], [:description, "text"], [:postal_code, "text"]]
table.schema.should == [
[:cartodb_id, "integer"], [:name, "text"], [:location, "geometry"], [:description, "text"], [:postal_code, "text"],
[:created_at, "timestamp"], [:updated_at, "timestamp"]
]
put_json "/api/json/tables/#{table.id}/update_schema", {
:what => "add", :column => {
@ -185,7 +192,10 @@ feature "Tables JSON API" do
}
response.status.should == 200
table.reload
table.schema.should == [[:cartodb_id, "integer"], [:name, "text"], [:location, "geometry"], [:description, "text"]]
table.schema.should == [
[:cartodb_id, "integer"], [:name, "text"], [:location, "geometry"], [:description, "text"],
[:created_at, "timestamp"], [:updated_at, "timestamp"]
]
put_json "/api/json/tables/#{table.id}/update_schema", {
:what => "drop", :column => {
@ -331,7 +341,10 @@ feature "Tables JSON API" do
get_json "/api/json/tables/#{response.location.match(/\/(\d+)$/)[1].to_i}/schema"
response.status.should == 200
json_response = JSON(response.body)
json_response.should == [["cartodb_id", "integer"], ["code", "character(5)"], ["title", "character varying(40)"], ["did", "integer"], ["date_prod", "date"], ["kind", "character varying(10)"]]
json_response.should == [
["cartodb_id", "integer"], ["code", "character(5)"], ["title", "character varying(40)"], ["did", "integer"],
["date_prod", "date"], ["kind", "character varying(10)"], ["created_at", "timestamp"], ["updated_at", "timestamp"]
]
end
scenario "Import a file when the schema is wrong" do

@ -45,7 +45,7 @@ feature "Tables" do
page.find("div.performing_op p").text.should == 'Loading...'
sleep 1
page.find("div.performing_op p").text.should == 'Your table tags has been updated'
page.find("div.performing_op p").text.should == 'Your table tags have been updated'
page.all("span.tags p")[0].text.should == 'twitter'
page.all("span.tags p")[1].text.should == 'tag1'
@ -53,7 +53,7 @@ feature "Tables" do
page.find("li.tagit-new input.tagit-input").set("tag3,")
page.find_link("Save").click
page.find("div.performing_op p").text.should == 'Your table tags has been updated'
page.find("div.performing_op p").text.should == 'Your table tags have been updated'
page.all("span.tags p")[0].text.should == 'twitter'
page.all("span.tags p")[1].text.should == 'tag1'
page.all("span.tags p")[2].text.should == 'tag3'

@ -62,7 +62,7 @@ describe Table do
table = create_table :user_id => user.id
table.to_json[:total_rows].should == 0
table.to_json[:columns].should == [[:cartodb_id, "integer"], [:name, "text"], [:location, "geometry"], [:description, "text"]]
table.to_json[:columns].should == [[:cartodb_id, "integer"], [:name, "text"], [:location, "geometry"], [:description, "text"], [:created_at, "timestamp"], [:updated_at, "timestamp"]]
table.to_json[:rows].should be_empty
10.times do
@ -123,12 +123,12 @@ describe Table do
it "can return its schema" do
table = create_table
table.schema.should == [[:cartodb_id, "integer"], [:name, "text"], [:location, "geometry"], [:description, "text"]]
table.schema.should == [[:cartodb_id, "integer"], [:name, "text"], [:location, "geometry"], [:description, "text"], [:created_at, "timestamp"], [:updated_at, "timestamp"]]
end
it "can modify it's schema" do
table = create_table
table.schema.should == [[:cartodb_id, "integer"], [:name, "text"], [:location, "geometry"], [:description, "text"]]
table.schema.should == [[:cartodb_id, "integer"], [:name, "text"], [:location, "geometry"], [:description, "text"], [:created_at, "timestamp"], [:updated_at, "timestamp"]]
lambda {
table.add_column!(:name => "my column with bad status", :type => "textttt")
@ -138,32 +138,32 @@ describe Table do
resp = table.add_column!(:name => "my new column", :type => "integer")
resp.should == {:name => 'my_new_column', :type => 'integer'}
table.reload
table.schema.should == [[:cartodb_id, "integer"], [:name, "text"], [:location, "geometry"], [:description, "text"], [:my_new_column, "integer"]]
table.schema.should == [[:cartodb_id, "integer"], [:name, "text"], [:location, "geometry"], [:description, "text"], [:my_new_column, "integer"], [:created_at, "timestamp"], [:updated_at, "timestamp"]]
resp = table.modify_column!(:old_name => "my_new_column", :new_name => "my new column new name", :type => "text")
resp.should == {:name => 'my_new_column_new_name', :type => 'text'}
table.reload
table.schema.should == [[:cartodb_id, "integer"], [:name, "text"], [:location, "geometry"], [:description, "text"], [:my_new_column_new_name, "text"]]
table.schema.should == [[:cartodb_id, "integer"], [:name, "text"], [:location, "geometry"], [:description, "text"], [:my_new_column_new_name, "text"], [:created_at, "timestamp"], [:updated_at, "timestamp"]]
resp = table.modify_column!(:old_name => "my_new_column_new_name", :new_name => "my new column")
resp.should == {:name => 'my_new_column', :type => nil}
table.reload
table.schema.should == [[:cartodb_id, "integer"], [:name, "text"], [:location, "geometry"], [:description, "text"], [:my_new_column, "text"]]
table.schema.should == [[:cartodb_id, "integer"], [:name, "text"], [:location, "geometry"], [:description, "text"], [:my_new_column, "text"], [:created_at, "timestamp"], [:updated_at, "timestamp"]]
resp = table.modify_column!(:name => "my_new_column", :type => "text")
resp.should == {:name => 'my_new_column', :type => 'text'}
table.reload
table.schema.should == [[:cartodb_id, "integer"], [:name, "text"], [:location, "geometry"], [:description, "text"], [:my_new_column, "text"]]
table.schema.should == [[:cartodb_id, "integer"], [:name, "text"], [:location, "geometry"], [:description, "text"], [:my_new_column, "text"], [:created_at, "timestamp"], [:updated_at, "timestamp"]]
table.drop_column!(:name => "location")
table.reload
table.schema.should == [[:cartodb_id, "integer"], [:name, "text"], [:description, "text"], [:my_new_column, "text"]]
table.schema.should == [[:cartodb_id, "integer"], [:name, "text"], [:description, "text"], [:my_new_column, "text"], [:created_at, "timestamp"], [:updated_at, "timestamp"]]
lambda {
table.drop_column!(:name => "location")
}.should raise_error
table.reload
table.schema.should == [[:cartodb_id, "integer"], [:name, "text"], [:description, "text"], [:my_new_column, "text"]]
table.schema.should == [[:cartodb_id, "integer"], [:name, "text"], [:description, "text"], [:my_new_column, "text"], [:created_at, "timestamp"], [:updated_at, "timestamp"]]
end
it "cannot modify :cartodb_id column" do
@ -191,15 +191,15 @@ describe Table do
it "should be able to modify it's schema with castings that the DB engine doesn't support" do
table = create_table
table.schema.should == [[:cartodb_id, "integer"], [:name, "text"], [:location, "geometry"], [:description, "text"]]
table.schema.should == [[:cartodb_id, "integer"], [:name, "text"], [:location, "geometry"], [:description, "text"], [:created_at, "timestamp"], [:updated_at, "timestamp"]]
table.add_column!(:name => "my new column", :type => "text")
table.reload
table.schema.should == [[:cartodb_id, "integer"], [:name, "text"], [:location, "geometry"], [:description, "text"], [:my_new_column, "text"]]
table.schema.should == [[:cartodb_id, "integer"], [:name, "text"], [:location, "geometry"], [:description, "text"], [:my_new_column, "text"], [:created_at, "timestamp"], [:updated_at, "timestamp"]]
table.modify_column!(:old_name => "my_new_column", :new_name => "my new column new name", :type => "integer", :force_value => "NULL")
table.reload
table.schema.should == [[:cartodb_id, "integer"], [:name, "text"], [:location, "geometry"], [:description, "text"], [:my_new_column_new_name, "integer"]]
table.schema.should == [[:cartodb_id, "integer"], [:name, "text"], [:location, "geometry"], [:description, "text"], [:my_new_column_new_name, "integer"], [:created_at, "timestamp"], [:updated_at, "timestamp"]]
end
it "should be able to insert a new row" do
@ -258,14 +258,14 @@ describe Table do
table = new_table
table.force_schema = "code char(5) CONSTRAINT firstkey PRIMARY KEY, title varchar(40) NOT NULL, did integer NOT NULL, date_prod date, kind varchar(10)"
table.save
table.schema.should == [[:cartodb_id, "integer"], [:code, "character(5)"], [:title, "character varying(40)"], [:did, "integer"], [:date_prod, "date"], [:kind, "character varying(10)"]]
table.schema.should == [[:cartodb_id, "integer"], [:code, "character(5)"], [:title, "character varying(40)"], [:did, "integer"], [:date_prod, "date"], [:kind, "character varying(10)"], [:created_at, "timestamp"], [:updated_at, "timestamp"]]
end
it "should sanitize columns from a given schema" do
table = new_table
table.force_schema = "\"code wadus\" char(5) CONSTRAINT firstkey PRIMARY KEY, title varchar(40) NOT NULL, did integer NOT NULL, date_prod date, kind varchar(10)"
table.save
table.schema.should == [[:cartodb_id, "integer"], [:code_wadus, "character(5)"], [:title, "character varying(40)"], [:did, "integer"], [:date_prod, "date"], [:kind, "character varying(10)"]]
table.schema.should == [[:cartodb_id, "integer"], [:code_wadus, "character(5)"], [:title, "character varying(40)"], [:did, "integer"], [:date_prod, "date"], [:kind, "character varying(10)"], [:created_at, "timestamp"], [:updated_at, "timestamp"]]
end
it "should import a CSV if the schema is given and is valid" do
@ -327,7 +327,7 @@ describe Table do
table.reload
table.rows_counted.should == 7
table.schema.should == [[:url, "character varying"], [:login, "character varying"], [:country, "character varying"], [:followers_count, "integer"], [:unknow_name_1, "character varying"],[:cartodb_id, "integer"]]
table.schema.should == [[:cartodb_id, "integer"], [:url, "character varying"], [:login, "character varying"], [:country, "character varying"], [:followers_count, "integer"], [:unknow_name_1, "character varying"], [:created_at, "timestamp"], [:updated_at, "timestamp"]]
row = table.to_json[:rows][0]
row[:url].should == "http://twitter.com/vzlaturistica/statuses/23424668752936961"
row[:login].should == "vzlaturistica "

@ -79,7 +79,7 @@ describe User do
query_result[:time].should_not be_blank
query_result[:time].to_s.match(/^\d+\.\d+$/).should be_true
query_result[:total_rows].should == 2
query_result[:columns].should == [:id, :name_of_species, :kingdom, :family, :lat, :lon, :views, :cartodb_id]
query_result[:columns].should == [:id, :name_of_species, :kingdom, :family, :lat, :lon, :views, :cartodb_id, :created_at, :updated_at]
query_result[:rows][0][:name_of_species].should == "Barrukia cristata"
query_result[:rows][1][:name_of_species].should == "Eulagisca gigantea"

Loading…
Cancel
Save