cartodb-rb-client-rails-322 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. data/.gitignore +5 -0
  2. data/.rvmrc +1 -0
  3. data/.travis.yml +15 -0
  4. data/Gemfile +15 -0
  5. data/LICENSE +28 -0
  6. data/README.markdown +365 -0
  7. data/Rakefile +10 -0
  8. data/cartodb-rb-client.gemspec +34 -0
  9. data/lib/cartodb-rb-client.rb +18 -0
  10. data/lib/cartodb-rb-client/cartodb.rb +6 -0
  11. data/lib/cartodb-rb-client/cartodb/client.rb +4 -0
  12. data/lib/cartodb-rb-client/cartodb/client/authorization.rb +92 -0
  13. data/lib/cartodb-rb-client/cartodb/client/cache.rb +14 -0
  14. data/lib/cartodb-rb-client/cartodb/client/connection.rb +4 -0
  15. data/lib/cartodb-rb-client/cartodb/client/connection/base.rb +44 -0
  16. data/lib/cartodb-rb-client/cartodb/client/connection/cartodb.rb +280 -0
  17. data/lib/cartodb-rb-client/cartodb/client/connection/postgres.rb +255 -0
  18. data/lib/cartodb-rb-client/cartodb/client/error.rb +68 -0
  19. data/lib/cartodb-rb-client/cartodb/client/utils.rb +20 -0
  20. data/lib/cartodb-rb-client/cartodb/helpers.rb +1 -0
  21. data/lib/cartodb-rb-client/cartodb/helpers/sql_helper.rb +36 -0
  22. data/lib/cartodb-rb-client/cartodb/init.rb +30 -0
  23. data/lib/cartodb-rb-client/cartodb/libs.rb +2 -0
  24. data/lib/cartodb-rb-client/cartodb/libs/object.rb +15 -0
  25. data/lib/cartodb-rb-client/cartodb/libs/string.rb +116 -0
  26. data/lib/cartodb-rb-client/cartodb/model.rb +11 -0
  27. data/lib/cartodb-rb-client/cartodb/model/base.rb +20 -0
  28. data/lib/cartodb-rb-client/cartodb/model/constants.rb +30 -0
  29. data/lib/cartodb-rb-client/cartodb/model/defaults.rb +15 -0
  30. data/lib/cartodb-rb-client/cartodb/model/geo.rb +101 -0
  31. data/lib/cartodb-rb-client/cartodb/model/getters.rb +75 -0
  32. data/lib/cartodb-rb-client/cartodb/model/persistence.rb +69 -0
  33. data/lib/cartodb-rb-client/cartodb/model/query.rb +66 -0
  34. data/lib/cartodb-rb-client/cartodb/model/schema.rb +121 -0
  35. data/lib/cartodb-rb-client/cartodb/model/scope.rb +163 -0
  36. data/lib/cartodb-rb-client/cartodb/model/setters.rb +37 -0
  37. data/lib/cartodb-rb-client/cartodb/types.rb +2 -0
  38. data/lib/cartodb-rb-client/cartodb/types/metadata.rb +97 -0
  39. data/lib/cartodb-rb-client/cartodb/types/pg_result.rb +17 -0
  40. data/lib/cartodb-rb-client/install_utils.rb +19 -0
  41. data/lib/cartodb-rb-client/version.rb +7 -0
  42. data/run_tests.sh +6 -0
  43. data/spec/client_spec.rb +357 -0
  44. data/spec/fixtures/cassettes/CartoDB_client/should_add_and_remove_colums_in_a_previously_created_table.yml +635 -0
  45. data/spec/fixtures/cassettes/CartoDB_client/should_allow_reserved_words_in_columns_names.yml +284 -0
  46. data/spec/fixtures/cassettes/CartoDB_client/should_change_a_previously_created_column.yml +362 -0
  47. data/spec/fixtures/cassettes/CartoDB_client/should_create_a_table_and_get_its_table_definition.yml +1634 -0
  48. data/spec/fixtures/cassettes/CartoDB_client/should_create_a_table_forcing_the_schema_and_get_its_table_definition.yml +298 -0
  49. data/spec/fixtures/cassettes/CartoDB_client/should_create_a_table_from_a_csv_file.yml +2947 -0
  50. data/spec/fixtures/cassettes/CartoDB_client/should_create_a_table_with_MULTILINESTRING_type_geometry.yml +299 -0
  51. data/spec/fixtures/cassettes/CartoDB_client/should_create_a_table_with_MULTIPOLYGON_type_geometry.yml +298 -0
  52. data/spec/fixtures/cassettes/CartoDB_client/should_create_a_table_with_POINT_type_geometry.yml +580 -0
  53. data/spec/fixtures/cassettes/CartoDB_client/should_delete_a_table_s_row.yml +410 -0
  54. data/spec/fixtures/cassettes/CartoDB_client/should_drop_a_table.yml +380 -0
  55. data/spec/fixtures/cassettes/CartoDB_client/should_escape_properly_input_data_in_insert_queries.yml +295 -0
  56. data/spec/fixtures/cassettes/CartoDB_client/should_execute_a_select_query_and_return_results.yml +987 -0
  57. data/spec/fixtures/cassettes/CartoDB_client/should_get_a_table_by_its_name.yml +298 -0
  58. data/spec/fixtures/cassettes/CartoDB_client/should_import_any_kind_of_data_file.yml +6951 -0
  59. data/spec/fixtures/cassettes/CartoDB_client/should_insert_a_row_in_a_table.yml +357 -0
  60. data/spec/fixtures/cassettes/CartoDB_client/should_paginate_records.yml +3642 -0
  61. data/spec/fixtures/cassettes/CartoDB_client/should_rename_an_existing_table.yml +299 -0
  62. data/spec/fixtures/cassettes/CartoDB_client/should_return_errors_on_invalid_queries.yml +132 -0
  63. data/spec/fixtures/cassettes/CartoDB_client/should_return_nil_when_requesting_a_table_which_does_not_exists.yml +218 -0
  64. data/spec/fixtures/cassettes/CartoDB_client/should_return_user_s_table_list.yml +244 -0
  65. data/spec/fixtures/cassettes/CartoDB_client/should_update_a_row_in_a_table.yml +347 -0
  66. data/spec/fixtures/cassettes/CartoDB_model_data_methods/should_destroy_a_previously_created_record.yml +1920 -0
  67. data/spec/fixtures/cassettes/CartoDB_model_data_methods/should_initialize_attributes_of_the_model_without_persisting_them.yml +963 -0
  68. data/spec/fixtures/cassettes/CartoDB_model_data_methods/should_persist_into_cartodb_using_the_save_method.yml +1946 -0
  69. data/spec/fixtures/cassettes/CartoDB_model_data_methods/should_persist_into_cartodb_using_the_static_create_method.yml +1796 -0
  70. data/spec/fixtures/cassettes/CartoDB_model_data_methods/should_save_polygons_in_different_formats.yml +1801 -0
  71. data/spec/fixtures/cassettes/CartoDB_model_data_methods/should_update_an_existing_record.yml +2856 -0
  72. data/spec/fixtures/cassettes/CartoDB_model_metadata_methods/should_add_more_columns_if_the_table_previously_exists.yml +1509 -0
  73. data/spec/fixtures/cassettes/CartoDB_model_metadata_methods/should_contain_an_array_of_columns.yml +2007 -0
  74. data/spec/fixtures/cassettes/CartoDB_model_metadata_methods/should_create_a_table_with_custom_name_if_specified.yml +357 -0
  75. data/spec/fixtures/cassettes/CartoDB_model_metadata_methods/should_create_model_with_custom_data_types_columns.yml +565 -0
  76. data/spec/fixtures/cassettes/CartoDB_model_metadata_methods/should_create_model_with_polygon_type_geometry_columns.yml +493 -0
  77. data/spec/fixtures/cassettes/CartoDB_model_metadata_methods/should_create_the_table_in_cartodb_if_it_doesn_t_exists.yml +1048 -0
  78. data/spec/fixtures/cassettes/CartoDB_model_metadata_methods/should_have_a_valid_CartoDB_Client_instance_as_a_connection_object.yml +971 -0
  79. data/spec/fixtures/cassettes/CartoDB_model_metadata_methods/should_have_a_valid_table_name.yml +970 -0
  80. data/spec/fixtures/cassettes/CartoDB_model_metadata_methods/should_return_only_data_columns.yml +1096 -0
  81. data/spec/fixtures/cassettes/CartoDB_model_scopes/should_allow_to_select_the_specified_fiels.yml +25828 -0
  82. data/spec/fixtures/cassettes/CartoDB_model_scopes/should_count_all_records.yml +22401 -0
  83. data/spec/fixtures/cassettes/CartoDB_model_scopes/should_find_a_record_by_its_id.yml +21852 -0
  84. data/spec/fixtures/cassettes/CartoDB_model_scopes/should_order_results.yml +23701 -0
  85. data/spec/fixtures/cassettes/CartoDB_model_scopes/should_paginate_results.yml +35644 -0
  86. data/spec/fixtures/cassettes/CartoDB_model_scopes/should_return_all_records_paginated.yml +23699 -0
  87. data/spec/fixtures/cassettes/CartoDB_model_scopes/should_search_records_by_certain_filters.yml +7080 -0
  88. data/spec/fixtures/cassettes/cartodb_spec_models.yml +3409 -0
  89. data/spec/fixtures/cassettes/clean_tables.yml +224 -0
  90. data/spec/model/data_spec.rb +157 -0
  91. data/spec/model/metadata_spec.rb +124 -0
  92. data/spec/model/scopes_spec.rb +171 -0
  93. data/spec/model_specs_helper.rb +2 -0
  94. data/spec/spec_helper.rb +54 -0
  95. data/spec/support/cartodb_config.yml +11 -0
  96. data/spec/support/cartodb_config.yml.sample +16 -0
  97. data/spec/support/cartodb_factories.rb +33 -0
  98. data/spec/support/cartodb_helpers.rb +14 -0
  99. data/spec/support/cartodb_models.rb +29 -0
  100. data/spec/support/data/110m-glaciated-areas.zip +0 -0
  101. data/spec/support/data/CartoDB_csv_export.zip +0 -0
  102. data/spec/support/data/CartoDB_shp_export.zip +0 -0
  103. data/spec/support/data/rmnp.kml +51 -0
  104. data/spec/support/data/states.kml.zip +0 -0
  105. data/spec/support/database.yml +5 -0
  106. data/spec/support/shp/cereal.dbf +0 -0
  107. data/spec/support/shp/cereal.shp +0 -0
  108. data/spec/support/shp/cereal.shx +0 -0
  109. data/spec/support/shp/cereal.zip +0 -0
  110. data/spec/support/shp/parcelas.dbf +0 -0
  111. data/spec/support/shp/parcelas.shp +0 -0
  112. data/spec/support/shp/parcelas.shx +0 -0
  113. data/spec/support/shp/parcelas.zip +0 -0
  114. data/spec/support/shp/zonas.dbf +0 -0
  115. data/spec/support/shp/zonas.shp +0 -0
  116. data/spec/support/shp/zonas.shx +0 -0
  117. data/spec/support/shp/zonas.zip +0 -0
  118. data/spec/support/whs_features.csv +315 -0
  119. data/spec/support/whs_features.csv.zip +0 -0
  120. data/spec/support/whs_features_temp.csv +315 -0
  121. metadata +400 -0
@@ -0,0 +1,163 @@
1
+ module CartoDB
2
+ module Model
3
+ class Scope
4
+ extend Forwardable
5
+ include CartoDB::Model::Constants
6
+
7
+ def_delegators :@model, :connection, :table_name, :cartodb_table
8
+
9
+ def initialize(model)
10
+ @model = model
11
+ @records = nil
12
+ @custom_fields = nil
13
+ @rows_per_page = nil
14
+ end
15
+
16
+ def to_a
17
+ @records ||= begin
18
+
19
+ results = connection.query build_sql
20
+
21
+ if results && results.rows
22
+ results.rows.map{|r| @model.new(r)}
23
+ else
24
+ []
25
+ end
26
+ rescue Exception => e
27
+ []
28
+ end
29
+
30
+ end
31
+ alias all to_a
32
+
33
+ def length
34
+ to_a.length
35
+ end
36
+ alias size length
37
+ alias count length
38
+
39
+ def select(*fields)
40
+ case fields
41
+ when String
42
+ @custom_fields = fields
43
+ when Array
44
+ @custom_fields = fields.join(', ')
45
+ end
46
+
47
+ self
48
+ end
49
+
50
+ def where(attributes = nil, *rest)
51
+ @records = nil
52
+ return all if attributes.nil? || (attributes.is_a?(Hash) && attributes.empty?) || (attributes.is_a?(Integer) && attributes <= 0)
53
+
54
+ if attributes.is_a?(Integer) || (attributes.length == 1 && (attributes[:cartodb_id] || attributes[:id]))
55
+ row_id = attributes.is_a?(Integer) ? attributes : (attributes[:cartodb_id] || attributes[:id])
56
+ return @model.new(connection.row(table_name, row_id))
57
+ end
58
+
59
+ create_filters(attributes, rest)
60
+
61
+ self
62
+ end
63
+
64
+ def page(page_number)
65
+ @page = page_number
66
+
67
+ self
68
+ end
69
+
70
+ def per_page(ammount)
71
+ @rows_per_page = ammount
72
+
73
+ self
74
+ end
75
+
76
+ def order(order_clause)
77
+ @order_clauses ||= []
78
+ @order_clauses << order_clause
79
+
80
+ self
81
+ end
82
+
83
+ def method_missing(method, *args, &block)
84
+ if Array.method_defined?(method)
85
+ to_a.send(method, *args, &block)
86
+ else
87
+ super
88
+ end
89
+ end
90
+ protected :method_missing
91
+
92
+ def filters
93
+ @filters ||= []
94
+ end
95
+ private :filters
96
+
97
+ def build_sql
98
+ select = build_select
99
+ from = build_from
100
+ where = build_where
101
+ order = build_order
102
+ pagination = build_pagination
103
+
104
+ sql = "#{select} #{from} #{where} #{order} #{pagination}"
105
+ end
106
+ alias to_sql build_sql
107
+
108
+ def build_select
109
+ columns = @custom_fields || cartodb_table.schema.map{|c| c[0]}.join(', ')
110
+ select = "SELECT #{columns}"
111
+ end
112
+ private :build_select
113
+
114
+ def build_from
115
+ from = "FROM #{table_name}"
116
+ end
117
+ private :build_from
118
+
119
+ def build_where
120
+ where = "WHERE #{filters.join(' AND ')}" if filters && filters.any?
121
+ end
122
+ private :build_where
123
+
124
+ def build_pagination
125
+ offset = (current_page - 1) * rows_per_page
126
+ pagination = "LIMIT #{rows_per_page} OFFSET #{offset}"
127
+ end
128
+ private :build_pagination
129
+
130
+ def build_order
131
+ order = "ORDER BY #{order_clauses.join(', ')}" unless order_clauses.nil? || order_clauses.empty?
132
+ end
133
+ private :build_order
134
+
135
+ def create_filters(attributes, values)
136
+ case attributes
137
+ when Hash
138
+ filters << attributes.to_a.map{|i| "#{table_name}.#{i.first} = #{i.last}"}.join(' AND ')
139
+ when String
140
+ values = values.flatten
141
+ filters << attributes.gsub(/[\?]/){|r| values.shift}
142
+ end
143
+ end
144
+ private :create_filters
145
+
146
+ def current_page
147
+ @page || 1
148
+ end
149
+ private :current_page
150
+
151
+ def rows_per_page
152
+ @rows_per_page || DEFAULT_ROWS_PER_PAGE
153
+ end
154
+ private :rows_per_page
155
+
156
+ def order_clauses
157
+ @order_clauses || []
158
+ end
159
+ private :order_clauses
160
+
161
+ end
162
+ end
163
+ end
@@ -0,0 +1,37 @@
1
+ module CartoDB
2
+ module Model
3
+ module Setters
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
7
+
8
+ module ClassMethods
9
+
10
+ def cartodb_table_name(table_name)
11
+ @table_name = table_name
12
+ end
13
+
14
+ def cartodb_table=(table)
15
+ @cartodb_table = table
16
+ end
17
+
18
+ def columns=(columns)
19
+ @columns = columns
20
+ end
21
+
22
+ def geometry_type=(geometry_type)
23
+ @geometry_type = geometry_type
24
+ end
25
+ end
26
+
27
+ def cartodb_table=(table)
28
+ self.class.cartodb_table = table
29
+ end
30
+
31
+ def attributes=(attributes)
32
+ @attributes = prepare_geo_attributes(attributes)
33
+ end
34
+
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,2 @@
1
+ require 'cartodb-rb-client/cartodb/types/metadata'
2
+ require 'cartodb-rb-client/cartodb/types/pg_result'
@@ -0,0 +1,97 @@
1
+ module CartoDB
2
+ module Types
3
+ class Metadata < Hash
4
+
5
+ RESERVED_WORDS = %w(
6
+ alias and BEGIN begin break case class def defined? do else elsif END end
7
+ ensure false for if in module next nil not or redo rescue retry return self
8
+ super then true undef unless until when while yield
9
+ )
10
+
11
+ class << self
12
+ def from_hash(hash = {})
13
+ metadata = self.new
14
+
15
+ hash.each do |key, value|
16
+ metadata[key.to_sym] = value
17
+ end
18
+ metadata
19
+ end
20
+ end
21
+
22
+ def []=(key, value)
23
+ key = :"#{key}_" if RESERVED_WORDS.include?(key.to_s)
24
+
25
+ if key.to_s.eql?('the_geom')
26
+ value = _geometry_features(value)
27
+ else
28
+ value = cast_value(value) unless CartoDB::Settings[:type_casting] == false
29
+ end
30
+
31
+ self.class.send :define_method, "#{key}" do
32
+ self[key.to_sym]
33
+ end
34
+
35
+ self.class.send :define_method, "#{key}=" do |value|
36
+ self[key.to_sym] = value
37
+ end
38
+
39
+ super(key, value)
40
+ end
41
+
42
+ def method_missing(name, *args, &block)
43
+ if name.to_s.end_with?('=') && args.size == 1
44
+ key = name.to_s[0...-1]
45
+ self[key.to_sym] = args[0]
46
+ else
47
+ super
48
+ end
49
+ end
50
+
51
+ def _geometry_features(the_geom)
52
+
53
+ begin
54
+ the_geom = RGeo::WKRep::WKBParser.new(RGeo::Geographic.spherical_factory(:srid => 4326), :support_ewkb => true).parse(the_geom)
55
+ rescue
56
+ begin
57
+ the_geom = RGeo::GeoJSON.decode(the_geom, :json_parser => :json, :geo_factory => RGeo::Geographic.spherical_factory(:srid => 4326))
58
+ rescue
59
+ end
60
+ end
61
+
62
+ case the_geom
63
+ when RGeo::Feature::Point || RGeo::Geographic::SphericalPointImpl
64
+ self.class.send :define_method, :latitude do
65
+ self.the_geom ? self.the_geom.y : nil
66
+ end
67
+
68
+ self.class.send :define_method, :longitude do
69
+ self.the_geom ? self.the_geom.x : nil
70
+ end
71
+ end
72
+
73
+ the_geom
74
+ end
75
+ private :_geometry_features
76
+
77
+ def cast_value(value)
78
+ return nil if value.nil?
79
+ return true if value.eql?('t')
80
+ return false if value.eql?('f')
81
+
82
+ begin
83
+ value = Float(value)
84
+ return value == value.floor ? value.to_i : value
85
+ rescue
86
+ end
87
+
88
+ return DateTime.strptime(value, '%Y-%m-%d') rescue
89
+ return DateTime.strptime(value, '%d-%m-%Y') rescue
90
+
91
+ value
92
+ end
93
+ private :cast_value
94
+
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,17 @@
1
+ class PGresult
2
+ def empty?
3
+ to_a.empty?
4
+ end
5
+
6
+ def items
7
+ to_a
8
+ end
9
+
10
+ def sample
11
+ to_a.sample
12
+ end
13
+
14
+ def size
15
+ to_a.size
16
+ end
17
+ end
@@ -0,0 +1,19 @@
1
+ module InstallUtils
2
+ def postgresql_installed?
3
+
4
+ return false unless system 'which pg_config > /dev/null'
5
+
6
+ pg_config_file = %x[cat `which pg_config`]
7
+ pgconfig_dirs_keys = %w(BINDIR INCLUDEDIR PKGINCLUDEDIR INCLUDEDIR-SERVER LIBDIR PKGLIBDIR SHAREDIR PGXS)
8
+
9
+ dirs_to_check = Hash[*%x[`which pg_config`].split("\n").map{|o| o.split(' = ')}.select{|o| pgconfig_dirs_keys.include?(o.first)}.flatten]
10
+
11
+ if dirs_to_check.keys.count == pgconfig_dirs_keys.count
12
+ return dirs_to_check.values.inject(true){|exists, dir| exists && File.exists?(dir)}
13
+ end
14
+
15
+ false
16
+ end
17
+ end
18
+
19
+ include InstallUtils
@@ -0,0 +1,7 @@
1
+ module Cartodb
2
+ module Rb
3
+ module Client
4
+ VERSION = "0.4.3"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,6 @@
1
+ #!/bin/sh
2
+ rvm 1.8.7@cartodb-rb-client
3
+ bundle install
4
+ rvm 1.9.2@cartodb-rb-client
5
+ bundle install
6
+ rvm 1.8.7@cartodb-rb-client,1.9.2@cartodb-rb-client rake spec
@@ -0,0 +1,357 @@
1
+ # coding: UTF-8
2
+ require 'spec_helper'
3
+
4
+ describe 'CartoDB client', :vcr => true do
5
+
6
+ it "should create a table and get its table definition" do
7
+
8
+ table = CartoDB::Connection.create_table 'cartodb_spec'
9
+
10
+ table.should_not be_nil
11
+ table = CartoDB::Connection.table 'cartodb_spec'
12
+ table.schema.should have(6).items
13
+ table.schema.should include(["cartodb_id", "number"])
14
+ table.schema.should include(["created_at", "date"])
15
+ table.schema.should include(["updated_at", "date"])
16
+ table.schema.should include(["name", "string"])
17
+ table.schema.should include(["description", "string"])
18
+ table.schema.should include(["the_geom", "geometry", "geometry", "point"])
19
+ end
20
+
21
+ it "should create a table forcing the schema and get its table definition" do
22
+ table = CartoDB::Connection.create_table 'cartodb_spec', [
23
+ {:name => 'field1', :type => 'text'},
24
+ {:name => 'field2', :type => 'numeric'},
25
+ {:name => 'field3', :type => 'date'},
26
+ {:name => 'field4', :type => 'boolean'}
27
+ ]
28
+
29
+ table.should_not be_nil
30
+ table = CartoDB::Connection.table 'cartodb_spec'
31
+ table.schema.should have(7).items
32
+ table.schema.should include(["cartodb_id", "number"])
33
+ table.schema.should include(["created_at", "date"])
34
+ table.schema.should include(["updated_at", "date"])
35
+ table.schema.should include(["field1", "string"])
36
+ table.schema.should include(["field2", "number"])
37
+ table.schema.should include(["field3", "date"])
38
+ table.schema.should include(["field4", "boolean"])
39
+ end
40
+
41
+ it "should create a table from a csv file" do
42
+
43
+ table = CartoDB::Connection.create_table 'whs_sites', File.open("#{File.dirname(__FILE__)}/support/whs_features.csv", 'r')
44
+
45
+ table.should_not be_nil
46
+ table[:id].should be > 0
47
+ table = CartoDB::Connection.table table[:name]
48
+ table.schema.should have(24).items
49
+
50
+ records = CartoDB::Connection.records table[:name]
51
+ records.should_not be_nil
52
+ records.rows.should have(10).whs_sites
53
+
54
+ records.rows.first.cartodb_id.should be > 0
55
+ records.rows.first.title.should be == "Aflaj Irrigation Systems of Oman"
56
+ records.rows.first.latitude.should be > 0
57
+ records.rows.first.longitude.should be > 0
58
+ records.rows.first.description.should match /A qanāt \(from Arabic: قناة‎\) \(Iran, Syria and Jordan\) is a water management system used to provide/
59
+ records.rows.first.region.should be == "Dakhiliya, Sharqiya and Batinah Regions"
60
+ records.rows.first.type.should be == "cultural"
61
+ records.rows.first.endangered_reason.should be_empty
62
+ records.rows.first.edited_region.should be == "Dakhiliya, Sharqiya and Batinah Regions"
63
+ records.rows.first.endangered_year.should be_empty
64
+ records.rows.first.external_links.should_not be_empty
65
+ records.rows.first.wikipedia_link.should be == "http://en.wikipedia.org/wiki/Qanat"
66
+ records.rows.first.comments.should be_empty
67
+ records.rows.first.criteria.should be == "[v]"
68
+ records.rows.first.iso_code.should be == "OM"
69
+ records.rows.first.size.should be == 14560000.0
70
+ records.rows.first.name.should be == "Aflaj Irrigation Systems of Oman"
71
+ records.rows.first.country.should be == "Oman"
72
+ records.rows.first.whs_site_id.should be == 1207
73
+ records.rows.first.date_of_inscription.should be == 2006
74
+ records.rows.first.whs_source_page.should be == "http://whc.unesco.org/en/list/1207"
75
+ records.rows.first.created_at.should_not be_nil
76
+ records.rows.first.updated_at.should_not be_nil
77
+
78
+ end
79
+
80
+ it "should import any kind of data file" do
81
+ Dir["#{File.dirname(__FILE__)}/support/data/*"].each do |file|
82
+ table = CartoDB::Connection.create_table File.basename(file, '.*'), File.open(file, 'r')
83
+
84
+ table.should_not be_nil
85
+ table[:id].should be > 0
86
+ table[:name].should_not be_empty
87
+ end
88
+ end
89
+
90
+ it "should create a table with POINT type geometry" do
91
+ table = CartoDB::Connection.create_table 'cartodb_spec', 'point'
92
+
93
+ table.should_not be_nil
94
+ table = CartoDB::Connection.table 'cartodb_spec'
95
+ table.schema.should have(6).items
96
+ table.schema.should include(["cartodb_id", "number"])
97
+ table.schema.should include(["created_at", "date"])
98
+ table.schema.should include(["updated_at", "date"])
99
+ table.schema.should include(["name", "string"])
100
+ table.schema.should include(["description", "string"])
101
+ table.schema.should include(["the_geom", "geometry", "geometry", "point"])
102
+ end
103
+
104
+ it "should create a table with MULTIPOLYGON type geometry" do
105
+ table = CartoDB::Connection.create_table 'cartodb_spec', 'multipolygon'
106
+
107
+ table.should_not be_nil
108
+ table = CartoDB::Connection.table 'cartodb_spec'
109
+ table.schema.should have(6).items
110
+ table.schema.should include(["cartodb_id", "number"])
111
+ table.schema.should include(["created_at", "date"])
112
+ table.schema.should include(["updated_at", "date"])
113
+ table.schema.should include(["name", "string"])
114
+ table.schema.should include(["description", "string"])
115
+ table.schema.should include(["the_geom", "geometry", "geometry", "multipolygon"])
116
+ end
117
+
118
+ it "should rename an existing table" do
119
+ table = CartoDB::Connection.create_table 'cartodb_spec'
120
+
121
+ table.name.should be == 'cartodb_spec'
122
+
123
+ table = CartoDB::Connection.rename_table 'cartodb_spec', 'renamed_cartodb_spec'
124
+ table.name.should be == 'renamed_cartodb_spec'
125
+ end
126
+
127
+ it "should create a table with MULTILINESTRING type geometry" do
128
+ table = CartoDB::Connection.create_table 'cartodb_spec', 'multilinestring'
129
+
130
+ table.should_not be_nil
131
+ table = CartoDB::Connection.table 'cartodb_spec'
132
+ table.schema.should have(6).items
133
+ table.schema.should include(["cartodb_id", "number"])
134
+ table.schema.should include(["created_at", "date"])
135
+ table.schema.should include(["updated_at", "date"])
136
+ table.schema.should include(["name", "string"])
137
+ table.schema.should include(["description", "string"])
138
+ table.schema.should include(["the_geom", "geometry", "geometry", "multilinestring"])
139
+ end
140
+
141
+ it "should add and remove colums in a previously created table" do
142
+ CartoDB::Connection.create_table 'cartodb_spec'
143
+ CartoDB::Connection.add_column 'cartodb_spec', 'field1', 'text'
144
+ CartoDB::Connection.add_column 'cartodb_spec', 'field2', 'numeric'
145
+ CartoDB::Connection.add_column 'cartodb_spec', 'field3', 'date'
146
+
147
+ table = CartoDB::Connection.table 'cartodb_spec'
148
+ table.schema.should have(9).items
149
+ table.schema.should include(["field1", "string"])
150
+ table.schema.should include(["field2", "number"])
151
+ table.schema.should include(["field3", "date"])
152
+
153
+ CartoDB::Connection.drop_column 'cartodb_spec', 'field3'
154
+ table = CartoDB::Connection.table 'cartodb_spec'
155
+ table.schema.should have(8).items
156
+ table.schema.should_not include(["field3", "date"])
157
+ end
158
+
159
+ it "should change a previously created column" do
160
+ CartoDB::Connection.create_table 'cartodb_spec', [{:name => 'field1', :type => 'text'}]
161
+ CartoDB::Connection.change_column 'cartodb_spec', "field1", "changed_field", "numeric"
162
+ table = CartoDB::Connection.table 'cartodb_spec'
163
+ table.schema.should_not include(["field1", "string"])
164
+ table.schema.should include(["changed_field", "number"])
165
+ end
166
+
167
+ it "should return user's table list" do
168
+ table_1 = CartoDB::Connection.create_table 'table #1'
169
+ table_2 = CartoDB::Connection.create_table 'table #2'
170
+
171
+ tables_list = CartoDB::Connection.tables
172
+ tables_list.tables.should have(2).items
173
+ tables_list.tables.map(&:name).should include(table_1.name)
174
+ tables_list.tables.map(&:name).should include(table_2.name)
175
+ end
176
+
177
+ it "should drop a table" do
178
+ table_1 = CartoDB::Connection.create_table 'table #1'
179
+ table_2 = CartoDB::Connection.create_table 'table #2'
180
+ table_3 = CartoDB::Connection.create_table 'table #3'
181
+
182
+ CartoDB::Connection.drop_table 'table_2'
183
+
184
+ tables_list = CartoDB::Connection.tables
185
+ tables_list.tables.should have(2).items
186
+ tables_list.tables.map(&:name).should include(table_1.name)
187
+ tables_list.tables.map(&:name).should include(table_3.name)
188
+ end
189
+
190
+ it "should insert a row in a table" do
191
+ table = CartoDB::Connection.create_table 'table #1', [
192
+ {:name => 'field1', :type => 'text'},
193
+ {:name => 'field2', :type => 'numeric'},
194
+ {:name => 'field3', :type => 'date'},
195
+ {:name => 'field4', :type => 'boolean'}
196
+ ]
197
+
198
+ today = DateTime.new(2004, 1, 1)
199
+
200
+ record = CartoDB::Connection.insert_row 'table_1', {
201
+ 'field1' => 'lorem',
202
+ 'field2' => 100.99,
203
+ 'field3' => today,
204
+ 'field4' => true
205
+ }
206
+
207
+ record.field1.should == 'lorem'
208
+ record.field2.should == 100.99
209
+ record.field3.to_date.should == today.to_date
210
+ record.field4.should == true
211
+ end
212
+
213
+ it "should update a row in a table" do
214
+ table = CartoDB::Connection.create_table 'table #1', [
215
+ {:name => 'field1', :type => 'text'},
216
+ {:name => 'field2', :type => 'numeric'},
217
+ {:name => 'field3', :type => 'date'},
218
+ {:name => 'field4', :type => 'boolean'}
219
+ ]
220
+
221
+ today = DateTime.new(2004, 1, 1)
222
+
223
+ record = CartoDB::Connection.insert_row 'table_1', {
224
+ 'field1' => 'lorem',
225
+ 'field2' => 100.99,
226
+ 'field3' => today,
227
+ 'field4' => true
228
+ }
229
+
230
+ record = CartoDB::Connection.update_row 'table_1', record.id, {
231
+ 'field1' => 'illum',
232
+ 'field2' => -83.24,
233
+ 'field3' => today + 1,
234
+ 'field4' => false
235
+ }
236
+
237
+ record.field1.should == 'illum'
238
+ record.field2.should == -83.24
239
+ record.field3.to_date.should == (today + 1).to_date
240
+ record.field4.should == false
241
+ end
242
+
243
+ it "should delete a table's row" do
244
+ table = CartoDB::Connection.create_table 'table #1', [
245
+ {:name => 'field1', :type => 'text'},
246
+ {:name => 'field2', :type => 'numeric'},
247
+ {:name => 'field3', :type => 'date'},
248
+ {:name => 'field4', :type => 'boolean'}
249
+ ]
250
+
251
+ today = Time.now
252
+
253
+ record = CartoDB::Connection.insert_row 'table_1', {
254
+ 'field1' => 'lorem',
255
+ 'field2' => 100.99,
256
+ 'field3' => today,
257
+ 'field4' => true
258
+ }
259
+
260
+ CartoDB::Connection.delete_row 'table_1', record.id
261
+
262
+ records = CartoDB::Connection.records 'table_1'
263
+
264
+ records.name.should be == 'table_1'
265
+ records.total_rows.should == 0
266
+ records.rows.should be_empty
267
+ end
268
+
269
+ it "should execute a select query and return results" do
270
+ table = CartoDB::Connection.create_table 'table #1'
271
+
272
+ 10.times do
273
+ row = CartoDB::Connection.insert_row 'table_1', {
274
+ 'name' => String.random(15),
275
+ 'description' => String.random(200),
276
+ 'the_geom' => RgeoFactory.point(-3.69962, 40.42222)
277
+ }
278
+
279
+ end
280
+ results = CartoDB::Connection.query("SELECT * FROM table_1")
281
+ results.should_not be_nil
282
+ results.time.should be > 0
283
+ results.total_rows.should == 10
284
+ results.rows.should have(10).items
285
+ results.rows.each do |row|
286
+ row.cartodb_id.should be > 0
287
+ row.name.should_not be_empty
288
+ row.latitude.should be == 40.42222
289
+ row.longitude.should be == -3.69962
290
+ row.description.should_not be_empty
291
+ row.created_at.should_not be_nil
292
+ row.updated_at.should_not be_nil
293
+ end
294
+ end
295
+
296
+ it "should get a table by its name" do
297
+ created_table = CartoDB::Connection.create_table 'table_with_name'
298
+
299
+ table = CartoDB::Connection.table 'table_with_name'
300
+ table.should_not be_nil
301
+ table.name.should be == created_table.name
302
+ end
303
+
304
+ it "should return nil when requesting a table which does not exists" do
305
+ expect{CartoDB::Connection.table('non_existing_table')}.to raise_error(CartoDB::Client::Error)
306
+ end
307
+
308
+ it "should return errors on invalid queries" do
309
+ expect{results = CartoDB::Connection.query("SELECT 1 FROM non_existing_table")}.to raise_error(CartoDB::Client::Error, /relation "non_existing_table" does not exist/)
310
+ end
311
+
312
+ it "should paginate records" do
313
+ table = CartoDB::Connection.create_table 'table #1'
314
+
315
+ 50.times do
316
+ CartoDB::Connection.insert_row 'table_1', {
317
+ 'name' => String.random(15),
318
+ 'description' => String.random(200),
319
+ 'the_geom' => RgeoFactory.point(rand(180), rand(90))
320
+ }
321
+ end
322
+
323
+ records = CartoDB::Connection.records 'table_1', :page => 0, :rows_per_page => 20
324
+ records.total_rows.should be == 50
325
+ records.rows.should have(20).records
326
+ records.rows.first.cartodb_id.should be == 1
327
+ records.rows.last.cartodb_id.should be == 20
328
+
329
+ records = CartoDB::Connection.records 'table_1', :page => 1, :rows_per_page => 20
330
+ records.total_rows.should be == 50
331
+ records.rows.should have(20).records
332
+ records.rows.first.cartodb_id.should be == 21
333
+ records.rows.last.cartodb_id.should be == 40
334
+
335
+ end
336
+
337
+ it 'should escape properly input data in insert queries' do
338
+
339
+ table = CartoDB::Connection.create_table 'table #1', 'multipolygon'
340
+ table.schema.should include(["the_geom", "geometry", "geometry", "multipolygon"])
341
+
342
+ record = CartoDB::Connection.insert_row 'table_1', {
343
+ 'the_geom' => "ST_GeomFromText('MULTIPOLYGON(((95.67764648436992 59.894444919406,90.75577148436992 54.16886220825434,103.41202148436992 56.75874227547269,95.67764648436992 59.894444919406)))', 4326)"
344
+ }
345
+
346
+ record.id.should_not be_nil
347
+ end
348
+
349
+ it 'should allow reserved words in columns names' do
350
+ table = CartoDB::Connection.create_table 'table #1', [{:name => 'class', :type => 'text'}]
351
+ table.schema.should include(["class", "string"])
352
+
353
+ record = CartoDB::Connection.insert_row table.name, :class => 'wadus'
354
+ record.class_.should == 'wadus'
355
+ end
356
+
357
+ end