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,255 @@
1
+ module CartoDB
2
+ module Client
3
+ module Connection
4
+ class PostgreSQL
5
+ include CartoDB::Helpers::SqlHelper
6
+
7
+ DATA_TYPES_TRANSLATION_TABLE = {
8
+ 'int4' => 'number',
9
+ 'numeric' => 'number',
10
+ 'text' => 'string',
11
+ 'varchar' => 'string',
12
+ 'date' => 'date',
13
+ 'timestamp' => 'date',
14
+ 'bool' => 'boolean',
15
+ 'geometry' => 'geometry'
16
+ }
17
+
18
+ def initialize(connection_settings)
19
+ @pg = connect_to_postgres(connection_settings)
20
+ end
21
+
22
+ def connect_to_postgres(settings)
23
+ pg_connection = PGconn.open(
24
+ :host => settings['host'],
25
+ :port => settings['port'],
26
+ :user => settings['user'],
27
+ :password => settings['password'],
28
+ :dbname => settings['database']
29
+ )
30
+ pg_connection.set_notice_processor{|message| nil}
31
+ pg_connection
32
+ end
33
+ private :connect_to_postgres
34
+
35
+ def create_table(table_name = nil, schema_or_file = nil, the_geom_type = 'Point')
36
+ schema = schema_or_file if schema_or_file && schema_or_file.is_a?(Array)
37
+ file = schema_or_file if schema_or_file && schema_or_file.is_a?(File)
38
+
39
+ params = {:name => table_name}
40
+ params[:file] = file if file
41
+
42
+ table_name = table_name.sanitize
43
+
44
+ if schema.nil? || schema.empty?
45
+ schema = []
46
+ schema << {:name => 'name', :type => 'text'} if schema.select{|c| c[:name].eql?('name')}.empty?
47
+ schema << {:name => 'description', :type => 'text'} if schema.select{|c| c[:name].eql?('description')}.empty?
48
+ create_the_geom = "SELECT AddGeometryColumn('public', '#{table_name}', 'the_geom', 4326, 'POINT', 2)"
49
+ end
50
+
51
+ schema << {:name => 'cartodb_id', :type => 'serial', :extra => 'NOT NULL'} if schema.select{|c| c[:name].eql?('cartodb_id')}.empty?
52
+ schema << {:name => 'created_at', :type => 'timestamp', :extra => 'without time zone DEFAULT current_timestamp::timestamp without time zone'} if schema.select{|c| c[:name].eql?('created_at')}.empty?
53
+ schema << {:name => 'updated_at', :type => 'timestamp', :extra => 'without time zone DEFAULT current_timestamp::timestamp without time zone'} if schema.select{|c| c[:name].eql?('updated_at')}.empty?
54
+ if schema.any? && schema.select{|c| c[:name].downcase.match(/geo/)}.any?
55
+ the_geom_field = schema.select{|c| c[:name].downcase.match(/geo/)}.first
56
+ create_the_geom = "SELECT AddGeometryColumn('public', '#{table_name}', 'the_geom', 4326, '#{the_geom_field[:geometry_type].upcase}', 2)"
57
+ schema.reject!{|c| c[:name].downcase.match(/geo/)}
58
+ end
59
+
60
+ @pg.query(<<-SQL
61
+ CREATE TABLE #{table_name}
62
+ (
63
+ #{schema.map{|s| "#{s[:name]} #{s[:type]} #{s[:extra]}"}.join(', ')}
64
+ )
65
+ WITH (
66
+ OIDS=FALSE
67
+ );
68
+ ALTER TABLE #{table_name} OWNER TO #{@pg.user};
69
+ SQL
70
+ )
71
+
72
+ @pg.query(create_the_geom) if create_the_geom
73
+
74
+ table table_name
75
+ end
76
+
77
+ def add_column(table_name, column_name, column_type)
78
+ @pg.query(<<-SQL
79
+ ALTER TABLE #{table_name} ADD COLUMN #{column_name} #{column_type};
80
+ SQL
81
+ )
82
+ end
83
+
84
+ def drop_column(table_name, column_name)
85
+ @pg.query(<<-SQL
86
+ ALTER TABLE #{table_name} DROP COLUMN #{column_name};
87
+ SQL
88
+ )
89
+ end
90
+
91
+ def change_column(table_name, old_column_name, new_column_name, column_type)
92
+ add_column table_name, new_column_name, column_type
93
+ @pg.query(<<-SQL
94
+ UPDATE #{table_name} SET #{new_column_name}=cast(#{old_column_name} as #{column_type})
95
+ SQL
96
+ )
97
+ drop_column table_name, old_column_name
98
+ end
99
+
100
+ def tables
101
+ pg_result = @pg.query(<<-SQL
102
+ SELECT columns.table_name, columns.column_name, columns.udt_name as data_type
103
+ FROM information_schema.tables tables
104
+ INNER JOIN information_schema.columns columns ON columns.table_name = tables.table_name
105
+ WHERE tables.table_schema = 'public' AND tables.table_name not IN ('spatial_ref_sys', 'geometry_columns', 'geography_columns')
106
+ SQL
107
+ )
108
+
109
+ result = CartoDB::Types::Metadata.new
110
+ tables = {}
111
+ pg_result.each do |column|
112
+ tables[column['table_name']] = CartoDB::Types::Metadata.from_hash({:name => column['table_name'], :schema => []}) unless tables[column['table_name']]
113
+ tables[column['table_name']].schema << %W(#{column['column_name']} #{CartoDB::Client::Connection::PostgreSQL::DATA_TYPES_TRANSLATION_TABLE[column['data_type']]})
114
+ end
115
+
116
+ result.total_entries = tables.to_a.length
117
+ result.tables = tables.to_a.map(&:last)
118
+ result
119
+ end
120
+
121
+ def table(table_name)
122
+ pg_result = @pg.query(<<-SQL
123
+ SELECT columns.table_name, columns.column_name, columns.udt_name as data_type, geo_cols.type as geometry_type
124
+ FROM information_schema.tables tables
125
+ INNER JOIN information_schema.columns columns ON columns.table_name = tables.table_name
126
+ LEFT OUTER JOIN public.geometry_columns geo_cols ON geo_cols.f_table_schema = columns.table_schema AND geo_cols.f_table_name = columns.table_name AND geo_cols.f_geometry_column = columns.column_name
127
+ WHERE tables.table_schema = 'public' AND tables.table_name not IN ('spatial_ref_sys', 'geometry_columns', 'geography_columns') AND tables.table_name ilike '#{table_name}'
128
+ SQL
129
+ )
130
+
131
+ if pg_result.to_a.empty?
132
+ non_existing_table = @pg.query(<<-SQL
133
+ SELECT tables.table_name
134
+ FROM information_schema.tables tables
135
+ WHERE tables.table_schema = 'public' AND tables.table_name not IN ('spatial_ref_sys', 'geometry_columns', 'geography_columns') AND tables.table_name ilike '#{table_name}'
136
+ SQL
137
+ )
138
+ raise CartoDB::Client::Error.new if non_existing_table.to_a.empty?
139
+ end
140
+
141
+ table_result = nil
142
+ pg_result.each do |column|
143
+ table_result = CartoDB::Types::Metadata.from_hash({:name => column['table_name'], :schema => []}) unless table_result
144
+ table_result.schema << %W(#{column['column_name']} #{CartoDB::Client::Connection::PostgreSQL::DATA_TYPES_TRANSLATION_TABLE[column['data_type']]})
145
+ table_result.schema.last << CartoDB::Client::Connection::PostgreSQL::DATA_TYPES_TRANSLATION_TABLE[column['data_type']] if column['geometry_type']
146
+ table_result.schema.last << column['geometry_type'].downcase if column['geometry_type']
147
+ end
148
+ table_result
149
+ end
150
+
151
+ def drop_table(table_name)
152
+ @pg.query(<<-SQL
153
+ DROP TABLE #{table_name}
154
+ SQL
155
+ )
156
+ end
157
+
158
+ def row(table_name, row_id)
159
+ results = query(<<-SQL
160
+ SELECT #{table_name}.cartodb_id as id, #{table_name}.*
161
+ FROM #{table_name}
162
+ WHERE cartodb_id = #{row_id};
163
+ SQL
164
+ )
165
+
166
+ results.rows.first
167
+ end
168
+
169
+ def insert_row(table_name, row)
170
+ row = prepare_data(row)
171
+
172
+ results = query(<<-SQL
173
+ INSERT INTO #{table_name}
174
+ (#{row.keys.join(',')})
175
+ VALUES (#{row.values.join(',')});
176
+
177
+ SELECT #{table_name}.cartodb_id as id, #{table_name}.*
178
+ FROM #{table_name}
179
+ WHERE cartodb_id = currval('public.#{table_name}_cartodb_id_seq');
180
+ SQL
181
+ )
182
+
183
+ results.rows.first
184
+ end
185
+
186
+ def update_row(table_name, row_id, row)
187
+ row = prepare_data(row)
188
+
189
+ results = query(<<-SQL
190
+ UPDATE #{table_name}
191
+ SET (#{row.keys.join(',')})
192
+ = (#{row.values.join(',')})
193
+ WHERE cartodb_id = #{row_id};
194
+ SELECT #{table_name}.cartodb_id as id, #{table_name}.*
195
+ FROM #{table_name}
196
+ WHERE cartodb_id = currval('public.#{table_name}_cartodb_id_seq');
197
+ SQL
198
+ )
199
+
200
+ results.rows.first
201
+ end
202
+
203
+ def delete_row(table_name, row_id)
204
+ @pg.query(<<-SQL
205
+ DELETE FROM #{table_name}
206
+ WHERE cartodb_id = #{row_id}
207
+ SQL
208
+ )
209
+ end
210
+
211
+ def records(table_name, options = {})
212
+ sql = <<-SQL
213
+ SELECT #{table_name}.cartodb_id AS id, #{table_name}.*
214
+ FROM #{table_name}
215
+ SQL
216
+
217
+ results = query(sql, options)
218
+
219
+ results[:name] = table_name
220
+ results
221
+ end
222
+
223
+ def query(sql, options = {})
224
+ sql = sql.strip if sql
225
+
226
+ if sql.include?('*')
227
+ table_name = sql.match(/select(.*)\s((\w+\.)?\*)(.*)from\s+(\w*)[^;]*;?/im)[5]
228
+ schema = table(table_name).schema if table_name
229
+
230
+ sql.gsub!(/^select(.*)\s((\w+\.)?\*)(.*)from/im) do |matches|
231
+ %Q{SELECT #{$1.strip} #{schema.map{|c| "#{$3}#{c[0]}"}.join(', ')} #{$4.strip} FROM}
232
+ end
233
+ end
234
+
235
+ crono = Time.now
236
+ begin
237
+ result = @pg.query(<<-SQL
238
+ #{sql}
239
+ SQL
240
+ )
241
+ rescue PGError => e
242
+ raise CartoDB::Client::Error.new(nil, nil, nil, e.message)
243
+ end
244
+
245
+ CartoDB::Types::Metadata.from_hash({
246
+ :time => Time.now - crono,
247
+ :total_rows => result.cmd_tuples,
248
+ :rows => result.map{|row| CartoDB::Types::Metadata.from_hash(row)}
249
+ })
250
+ end
251
+
252
+ end
253
+ end
254
+ end
255
+ end
@@ -0,0 +1,68 @@
1
+ module CartoDB
2
+ module Client
3
+ class Error < Exception
4
+ attr_accessor :status_code
5
+
6
+ HTTP_MESSAGES = {
7
+ 401 => 'Unauthorized request',
8
+ 404 => 'Not found',
9
+ 500 => 'Server error'
10
+ }
11
+
12
+ def initialize(uri = nil, method = nil, http_response = nil, error_message = nil)
13
+ @uri = uri
14
+ @method = method
15
+ @error_messages = ['undefined CartoDB error']
16
+ @status_code = 400
17
+ @error_messages = [uri] if method == nil && http_response == nil && error_message == nil
18
+ @error_messages = [error_message] if error_message
19
+
20
+ if http_response
21
+ @status_code = http_response.code
22
+ @error_messages = custom_error(http_response) || standard_error
23
+ @body = http_response.body
24
+ end
25
+
26
+ end
27
+
28
+ def to_s
29
+ message = <<-EOF
30
+ #{http_error_message_header}
31
+ #{format_error_messages}
32
+ #{@body}
33
+ EOF
34
+ message.strip
35
+ end
36
+
37
+ def http_error_message_header
38
+ if @method && @uri
39
+ %{There were errors running the #{@method.to_s.upcase} request "#{@uri}":}
40
+ end
41
+ end
42
+ private :http_error_message_header
43
+
44
+ def custom_error(http_response)
45
+ json = Utils.parse_json(http_response)
46
+ json[:error] if json
47
+ end
48
+
49
+ def standard_error
50
+ "#{status_code} - #{HTTP_MESSAGES[status_code.to_i]}"
51
+ end
52
+ private :standard_error
53
+
54
+ def format_error_messages
55
+ return '' unless @error_messages
56
+ if @error_messages.is_a?(String)
57
+ @error_messages
58
+ elsif @error_messages.is_a?(Array) && @error_messages.count == 1
59
+ @error_messages.first
60
+ else
61
+ @error_messages.map{|e| "- #{e}"}.join("\n")
62
+ end
63
+ end
64
+ private :format_error_messages
65
+
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,20 @@
1
+ module CartoDB
2
+ module Client
3
+ module Utils
4
+
5
+ def self.parse_json(response)
6
+ json = nil
7
+
8
+ unless response.nil? || response.body.nil? || response.body.strip == ''
9
+ begin
10
+ json = ::JSON.parse(response.body, :object_class => CartoDB::Types::Metadata, :symbolize_names => true)
11
+ rescue JSON::ParserError => e
12
+ json = CartoDB::Types::Metadata.new
13
+ end
14
+ end
15
+ json
16
+ end
17
+
18
+ end
19
+ end
20
+ end
@@ -0,0 +1 @@
1
+ require 'cartodb-rb-client/cartodb/helpers/sql_helper'
@@ -0,0 +1,36 @@
1
+ module CartoDB
2
+ module Helpers
3
+ module SqlHelper
4
+ require 'time'
5
+
6
+ def prepare_data(hash)
7
+ hash.each do |key, value|
8
+ hash[key] = format_value(key, value)
9
+ end
10
+ hash
11
+ end
12
+
13
+ def format_value(key, value)
14
+ case value
15
+ when ::String
16
+ #value = value.gsub(/\\/, '\&\&').gsub(/'/, "''")
17
+ if key.match(/geo/)
18
+ "#{value}"
19
+ else
20
+ "'#{value.gsub(/\\/, '\&\&').gsub(/'/, "''")}'"
21
+ end
22
+ when ::Date, ::DateTime, ::Time
23
+ "'#{value.to_time.utc}'"
24
+ when RGeo::Feature::Geometry
25
+ "'#{RGeo::WKRep::WKBGenerator.new(:type_format => :ewkb, :emit_ewkb_srid => true, :hex_format => true).generate(value)}'"
26
+ when NilClass
27
+ 'NULL'
28
+ else
29
+ value
30
+ end
31
+ end
32
+ private :format_value
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,30 @@
1
+ module CartoDB
2
+ class Init
3
+
4
+ class << self
5
+
6
+ def start(cartodb_settings = nil)
7
+ if cartodb_settings.blank?
8
+ config_path = Rails.root.join('config/cartodb_config.yml')
9
+ cartodb_settings = YAML.load_file(config_path)[Rails.env.to_s] if File.exists?(config_path)
10
+ end
11
+
12
+ return if cartodb_settings.blank?
13
+
14
+ if CartoDB.const_defined?('Settings')
15
+ CartoDB::Settings.merge!(cartodb_settings)
16
+ else
17
+ CartoDB.const_set('Settings', cartodb_settings)
18
+ end
19
+
20
+ CartoDB.const_set('Connection', CartoDB::Client::Connection::Base.new) unless CartoDB.const_defined?('Connection')
21
+
22
+
23
+ end
24
+
25
+ end
26
+
27
+ end
28
+ end
29
+
30
+
@@ -0,0 +1,2 @@
1
+ require 'cartodb-rb-client/cartodb/libs/string'
2
+ require 'cartodb-rb-client/cartodb/libs/object'
@@ -0,0 +1,15 @@
1
+ # coding: UTF-8
2
+ class Object
3
+ def needsQuotes?
4
+ return false unless self
5
+
6
+ case self
7
+ when ::String
8
+ true
9
+ when ::Date, ::DateTime, ::Time
10
+ true
11
+ else
12
+ false
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,116 @@
1
+ # coding: UTF-8
2
+
3
+ class String
4
+ def self.random(length=10)
5
+ ('a'..'z').sort_by {rand}[0,length].join
6
+ end
7
+
8
+ def normalize
9
+ str = self.downcase
10
+ return '' if str.blank?
11
+ n = str.force_encoding("UTF-8")
12
+ n.gsub!(/[àáâãäåāă]/, 'a')
13
+ n.gsub!(/æ/, 'ae')
14
+ n.gsub!(/[ďđ]/, 'd')
15
+ n.gsub!(/[çćčĉċ]/, 'c')
16
+ n.gsub!(/[èéêëēęěĕė]/, 'e')
17
+ n.gsub!(/ƒ/, 'f')
18
+ n.gsub!(/[ĝğġģ]/, 'g')
19
+ n.gsub!(/[ĥħ]/, 'h')
20
+ n.gsub!(/[ììíîïīĩĭ]/, 'i')
21
+ n.gsub!(/[įıijĵ]/, 'j')
22
+ n.gsub!(/[ķĸ]/, 'k')
23
+ n.gsub!(/[łľĺļŀ]/, 'l')
24
+ n.gsub!(/[ñńňņʼnŋ]/, 'n')
25
+ n.gsub!(/[òóôõöøōőŏŏ]/, 'o')
26
+ n.gsub!(/œ/, 'oe')
27
+ n.gsub!(/ą/, 'q')
28
+ n.gsub!(/[ŕřŗ]/, 'r')
29
+ n.gsub!(/[śšşŝș]/, 's')
30
+ n.gsub!(/[ťţŧț]/, 't')
31
+ n.gsub!(/[ùúûüūůűŭũų]/, 'u')
32
+ n.gsub!(/ŵ/, 'w')
33
+ n.gsub!(/[ýÿŷ]/, 'y')
34
+ n.gsub!(/[žżź]/, 'z')
35
+ n.gsub!(/[ÀÁÂÃÄÅĀĂ]/i, 'A')
36
+ n.gsub!(/Æ/i, 'AE')
37
+ n.gsub!(/[ĎĐ]/i, 'D')
38
+ n.gsub!(/[ÇĆČĈĊ]/i, 'C')
39
+ n.gsub!(/[ÈÉÊËĒĘĚĔĖ]/i, 'E')
40
+ n.gsub!(/Ƒ/i, 'F')
41
+ n.gsub!(/[ĜĞĠĢ]/i, 'G')
42
+ n.gsub!(/[ĤĦ]/i, 'H')
43
+ n.gsub!(/[ÌÌÍÎÏĪĨĬ]/i, 'I')
44
+ n.gsub!(/[IJĴ]/i, 'J')
45
+ n.gsub!(/[Ķĸ]/i, 'J')
46
+ n.gsub!(/[ŁĽĹĻĿ]/i, 'L')
47
+ n.gsub!(/[ÑŃŇŅʼnŊ]/i, 'M')
48
+ n.gsub!(/[ÒÓÔÕÖØŌŐŎŎ]/i, 'N')
49
+ n.gsub!(/Œ/i, 'OE')
50
+ n.gsub!(/Ą/i, 'Q')
51
+ n.gsub!(/[ŔŘŖ]/i, 'R')
52
+ n.gsub!(/[ŚŠŞŜȘ]/i, 'S')
53
+ n.gsub!(/[ŤŢŦȚ]/i, 'T')
54
+ n.gsub!(/[ÙÚÛÜŪŮŰŬŨŲ]/i, 'U')
55
+ n.gsub!(/Ŵ/i, 'W')
56
+ n.gsub!(/[ÝŸŶ]/i, 'Y')
57
+ n.gsub!(/[ŽŻŹ]/i, 'Z')
58
+ n
59
+ end
60
+
61
+ def sanitize
62
+ return if self.blank?
63
+ self.gsub(/<[^>]+>/m,'').normalize.downcase.gsub(/&.+?;/,'-').
64
+ gsub(/[^a-z0-9 _-]/,'-').strip.gsub(/\s+/,'-').gsub(/-+/,'-').
65
+ gsub(/-/,' ').strip.gsub(/ /,'-').gsub(/-/,'_')
66
+ end
67
+
68
+ def strip_tags
69
+ self.gsub(/<[^>]+>/m,'').strip
70
+ end
71
+
72
+ def convert_to_db_type
73
+ if CartoDB::TYPES.keys.include?(self.downcase)
74
+ if self.downcase == "number"
75
+ "double precision"
76
+ else
77
+ CartoDB::TYPES[self.downcase].first
78
+ end
79
+ else
80
+ self.downcase
81
+ end
82
+ end
83
+
84
+ # {"integer"=>:number, "real"=>:number, "varchar"=>:string, "text"=>:string, "timestamp"=>:date, "boolean"=>:boolean}
85
+ def convert_to_cartodb_type
86
+ inverse_types = CartoDB::TYPES.invert.inject({}){ |h, e| e.first.each{ |k| h[k] = e.last }; h}
87
+ if inverse_types.keys.include?(self.downcase)
88
+ inverse_types[self.downcase]
89
+ else
90
+ inverse_types.keys.select{ |t| !t.is_a?(String) }.each do |re|
91
+ if self.downcase.match(re)
92
+ return inverse_types[re]
93
+ end
94
+ end
95
+ self.downcase
96
+ end
97
+ end
98
+
99
+ def sanitize_sql
100
+ self.gsub(/\\/, '\&\&').gsub(/'/, "''")
101
+ end
102
+
103
+ def host
104
+ self.split('/')[2]
105
+ end
106
+
107
+ def sanitize_column_name
108
+ temporal_name = self.sanitize
109
+ if temporal_name !~ /^[a-zA-Z_]/ || CartoDB::POSTGRESQL_RESERVED_WORDS.include?(self.upcase)
110
+ return '_' + temporal_name
111
+ else
112
+ temporal_name
113
+ end
114
+ end
115
+
116
+ end