activerecord-utils 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a972ada88d58d419b8cbe37ffd2a8f759ed71317
4
- data.tar.gz: 35bbf160a49f76616d701fb52d6aebff58ee4698
3
+ metadata.gz: 0170989d89e7f272711aa9fb84b0deec2b1c51f3
4
+ data.tar.gz: d0b7a914857f0a9a8f98a73b8cc93069188fde30
5
5
  SHA512:
6
- metadata.gz: 85725b37c1121e4c61eb56e9f917408526ce676f19ec3742894bbfa1a89bef5f35fb1e6fda6e101ca77b33559e56d489c88312350e9df36a24828d5e4baef6c9
7
- data.tar.gz: b161fed850886f04ae9056cdf28253cf831a1390237c1594c7b7b62ec60527ceeef5c3aebb673aaa30e133ccfe3242576d18404cd614cb1779038e18440ff457
6
+ metadata.gz: 5589fde05b548766683fbe697cef2ae9850a771aa79d6ea6745e8a29f489edbbab059ef0d09952cd05c0a230c4c3a44a9ace9d4f7422a5f94eb2ffd2e218ad36
7
+ data.tar.gz: f988280ea2755298f2372db81478307754b4a873df33e2ce9e6a4519808ef2eaca24c333014b1d79d819b8817a7ee2b427e300e1dd310d8c7f3b1f983531fb8f
data/Manifest.txt CHANGED
@@ -4,10 +4,12 @@ README.md
4
4
  Rakefile
5
5
  lib/activerecord/utils.rb
6
6
  lib/activerecord/utils/alias.rb
7
+ lib/activerecord/utils/browser.rb
7
8
  lib/activerecord/utils/comp3.rb
8
9
  lib/activerecord/utils/random.rb
9
10
  lib/activerecord/utils/version.rb
10
11
  test/helper.rb
12
+ test/test_browser.rb
11
13
  test/test_finders.rb
12
14
  test/test_random.rb
13
15
  test/test_readers.rb
data/Rakefile CHANGED
@@ -3,7 +3,7 @@ require './lib/activerecord/utils/version.rb'
3
3
 
4
4
  Hoe.spec 'activerecord-utils' do
5
5
 
6
- self.version = ActiveRecord::Utils::VERSION
6
+ self.version = ActiveRecordUtils::VERSION
7
7
 
8
8
  self.summary = 'activerecord-utils - utilities (e.g. random, alias_attr, etc.) for activerecord'
9
9
  self.description = summary
@@ -18,7 +18,8 @@ Hoe.spec 'activerecord-utils' do
18
18
  self.history_file = 'History.md'
19
19
 
20
20
  self.extra_deps = [
21
- ['logutils']
21
+ ['logutils'],
22
+ ['activerecord']
22
23
  ]
23
24
 
24
25
  self.licenses = ['Public Domain']
@@ -28,4 +29,4 @@ Hoe.spec 'activerecord-utils' do
28
29
  }
29
30
 
30
31
 
31
- end
32
+ end
@@ -1,10 +1,10 @@
1
+ # encoding: utf-8
1
2
 
2
- require 'activerecord/utils/version' # let version always go first
3
3
 
4
+ require 'activerecord/utils/version' # let version always go first
4
5
 
5
- module ActiveRecord
6
6
 
7
- module Utils
7
+ module ActiveRecordUtils
8
8
 
9
9
  def self.banner
10
10
  ## add ar PRE too? how?
@@ -16,9 +16,7 @@ module Utils
16
16
  "#{File.expand_path( File.dirname(File.dirname(File.dirname(__FILE__))) )}"
17
17
  end
18
18
 
19
- end # module Utils
20
-
21
- end # module ActiveRecord
19
+ end # module ActiveRecordUtils
22
20
 
23
21
 
24
22
  ########################
@@ -31,9 +29,10 @@ end
31
29
 
32
30
  require 'activerecord/utils/alias'
33
31
  require 'activerecord/utils/random'
32
+ require 'activerecord/utils/browser'
34
33
 
35
34
 
36
- puts ActiveRecord::Utils.banner # say hello
35
+ puts ActiveRecordUtils.banner # say hello
37
36
 
38
- ### puts "root: >#{ActiveRecord::Utils.root}<" # check root path (remove later)
37
+ ### puts "root: >#{ActiveRecordUtils.root}<" # check root path (remove later)
39
38
 
@@ -1,3 +1,4 @@
1
+ # encoding: utf-8
1
2
 
2
3
  module ActiveRecord
3
4
  class Base
@@ -0,0 +1,282 @@
1
+ # encoding: utf-8
2
+
3
+ module ActiveRecordUtils
4
+
5
+ ####
6
+ # simple (generic) database browser - no models required
7
+
8
+
9
+ class Browser # also (formerly) known as connection manager
10
+
11
+ # get connection names
12
+ # def connection_names
13
+ # ActiveRecord::Base.configurations.keys
14
+ # end
15
+
16
+ CONNECTS = {} # cache connections
17
+
18
+ def connection_for( key )
19
+ # cache connections - needed? why? why not??
20
+
21
+ # hack: for now only use cached connection if still active
22
+ # if not; get a new one to avoid connection closed errors in rails
23
+ con = CONNECTS[ key ]
24
+ if con
25
+ puts "[Browser] cached connection found; con.active? #{con.active?}"
26
+ unless con.active?
27
+ puts "[Browser] *** reset cached connection (reason: connection stale/closed/not active)"
28
+ con = CONNECTS[ key ] = nil
29
+ end
30
+ end
31
+
32
+ if con.nil?
33
+ con = CONNECTS[ key ] = AbstractModel.connection_for( key )
34
+ end
35
+
36
+ # note: make sure connection is active?
37
+ # use verify! - will try active? followed by reconnect!
38
+ # - todo: check ourselves if active? - why? why not??
39
+ # -- not working w/ rails - after verify! still getting error w/ closed connection
40
+ # -- con.verify!
41
+
42
+ # wrap ActiveRecord connection in our own connection class
43
+ Connection.new( con, key )
44
+ end
45
+
46
+
47
+ class AbstractModel < ActiveRecord::Base
48
+ self.abstract_class = true # no table; class just used for getting db connection
49
+
50
+ def self.connection_for( key )
51
+ establish_connection( key )
52
+ connection
53
+ end
54
+
55
+ end # class AbstractModel
56
+
57
+
58
+ class Connection
59
+
60
+ def initialize( connection, key )
61
+ @connection = connection
62
+ @key = key
63
+ end
64
+
65
+ attr_reader :connection
66
+ attr_reader :key
67
+
68
+ delegate :select_value, :select_all, :adapter_name,
69
+ :to => :connection
70
+
71
+ def class_name
72
+ @connection.class.name
73
+ end
74
+
75
+ # delegate :quote_table_name, :quote_column_name, :quote,
76
+ # :update, :insert, :delete,
77
+ # :add_limit_offset!,
78
+ # :to => :connection
79
+
80
+ def tables
81
+ @tables ||= fetch_table_defs
82
+ end
83
+
84
+ def table( name )
85
+ tables.find { |t| t.name.downcase == name.downcase }
86
+ end
87
+
88
+ # getting list of column definitions
89
+ # and order them to be more human readable
90
+ def table_columns( name )
91
+ cols = fetch_table_column_defs( name )
92
+ ### fix/to be done
93
+ # cols.sort_by{|col|
94
+ # [
95
+ # fields_to_head.index(col.name) || 1e6,
96
+ # -(fields_to_tail.index(col.name) || 1e6),
97
+ # col.name
98
+ # ]
99
+ # }
100
+ cols
101
+ end
102
+
103
+ def fetch_table_defs
104
+ @connection.tables.sort.map do |name|
105
+ Table.new( self, name )
106
+ end
107
+ end
108
+
109
+ def fetch_table_column_defs( name )
110
+ ### fix/todo: add reference to table_def
111
+ @connection.columns( name ).map do |col|
112
+ Column.new( col.name, col.sql_type, col.default, col.null )
113
+ end
114
+ end
115
+
116
+
117
+ def fetch_table_select_all( name, opts={} )
118
+ limit = (opts[:limit] || 33).to_i # 33 records limit/per page (for now default)
119
+ limit = 33 if limit == 0 # use default page size if limit 0 (from not a number para)
120
+
121
+ offset = (opts[:offset] || 0).to_i
122
+
123
+ sql = "select * from #{name} limit #{limit}"
124
+
125
+ sql << " offset #{offset}" if offset > 0 # add offset if present (e.g greater zero)
126
+
127
+ # page = (opts[:page] || 1 ).try(:to_i)
128
+ # fields = opts[:fields] || nil
129
+
130
+ # rez = { :fields => fields }
131
+ # if sql =~ /\s*select/i && per_page > 0
132
+ # rez[:count] = select_value("select count(*) from (#{sql}) as t").to_i
133
+ # rez[:pages] = (rez[:count].to_f / per_page).ceil
134
+ # sql = "select * from (#{sql}) as t"
135
+ # add_limit_offset!( sql,
136
+ # :limit => per_page,
137
+ # :offset => per_page * (page - 1))
138
+ # end
139
+
140
+ result = {}
141
+ result[ :sql ] = sql # note: lets also always add sql query to result too
142
+ result[ :rows ] = select_all( sql )
143
+
144
+ # unless rez[:rows].blank?
145
+ # rez[:fields] ||= []
146
+ # rez[:fields].concat( self.sort_fields(rez[:rows].first.keys) - rez[:fields] )
147
+ # end
148
+
149
+ Result.new( result )
150
+ rescue StandardError => ex
151
+ Result.new( error: ex )
152
+ end # fetch_table
153
+
154
+
155
+ =begin
156
+ def column_names(table)
157
+ columns(table).map{|c| c.name}
158
+ end
159
+
160
+ # fields to see first
161
+ def fields_to_head
162
+ @fields_to_head ||= %w{id name login value}
163
+ end
164
+
165
+ # fields to see last
166
+ def fields_to_tail
167
+ @fields_to_tail ||= %w{created_at created_on updated_at updated_on}
168
+ end
169
+
170
+ attr_writer :fields_to_head, :fields_to_tail
171
+
172
+ # sort field names in a rezult
173
+ def sort_fields(fields)
174
+ fields = (fields_to_head & fields) | (fields - fields_to_head)
175
+ fields = (fields - fields_to_tail) | (fields_to_tail & fields)
176
+ fields
177
+ end
178
+
179
+ # performs query with appropriate method
180
+ def query(sql, opts={})
181
+ per_page = (opts[:perpage] || nil).to_i
182
+ page = (opts[:page] || 1 ).try(:to_i)
183
+ fields = opts[:fields] || nil
184
+ case sql
185
+ when /\s*select/i , /\s*(update|insert|delete).+returning/im
186
+ rez = {:fields => fields}
187
+ if sql =~ /\s*select/i && per_page > 0
188
+ rez[:count] = select_value("select count(*) from (#{sql}) as t").to_i
189
+ rez[:pages] = (rez[:count].to_f / per_page).ceil
190
+ sql = "select * from (#{sql}) as t"
191
+ add_limit_offset!( sql,
192
+ :limit => per_page,
193
+ :offset => per_page * (page - 1))
194
+ end
195
+
196
+ rez[:rows] = select_all( sql )
197
+
198
+ unless rez[:rows].blank?
199
+ rez[:fields] ||= []
200
+ rez[:fields].concat( self.sort_fields(rez[:rows].first.keys) - rez[:fields] )
201
+ end
202
+
203
+ Result.new(rez)
204
+ when /\s*update/i
205
+ Result.new :value => update( sql )
206
+ when /\s*insert/i
207
+ Result.new :value => insert( sql )
208
+ when /\s*delete/i
209
+ Result.new :value => delete( sql )
210
+ end
211
+ rescue StandardError => e
212
+ Result.new :error => e
213
+ end
214
+
215
+ =end
216
+
217
+ end # class Connection
218
+
219
+
220
+ class Table
221
+
222
+ def initialize(connection, name)
223
+ @connection = connection
224
+ @name = name
225
+ end
226
+
227
+ attr_reader :connection
228
+ attr_reader :name
229
+
230
+ def count
231
+ @connection.select_value( "select count(*) from #{name}").to_i
232
+ end
233
+
234
+ def columns
235
+ # load columns on demand for now (cache on first lookup)
236
+ @columns ||= @connection.table_columns( @name )
237
+ end
238
+
239
+ def query( opts={})
240
+ @connection.fetch_table_select_all( @name, opts )
241
+ end
242
+
243
+ end # class Table
244
+
245
+
246
+ class Column
247
+ def initialize(name, type, default, null)
248
+ @name = name
249
+ @type = type # note: is sql_type
250
+ @default = default
251
+ @null = null # note: true|false depending if NOT NULL or not
252
+ end
253
+
254
+ attr_reader :name, :type, :default, :null
255
+ end # class Column
256
+
257
+
258
+ class Result
259
+ def initialize( opts={} )
260
+ @sql = opts[:sql] # sql statement as a string
261
+
262
+ if opts[:error]
263
+ @error = opts[:error]
264
+ else
265
+ @rows = opts[:rows]
266
+ # @count = opts[:count] || @rows.size
267
+ # @pages = opts[:pages] || 1
268
+ # @fields = opts[:fields]
269
+ end
270
+ end
271
+
272
+ attr_reader :sql, :rows, :error ### to be done :count, :pages, :fields,
273
+
274
+ def error?() @error.present?; end
275
+ def rows?() @rows != nil; end
276
+ end # class Result
277
+
278
+
279
+ end # class Browser
280
+
281
+ end # module ActiveRecordUtils
282
+
@@ -1,4 +1,4 @@
1
- # encoding: UTF-8
1
+ # encoding: utf-8
2
2
 
3
3
  module ActiveRecord
4
4
  class Base
@@ -1,4 +1,4 @@
1
- # encoding: UTF-8
1
+ # encoding: utf-8
2
2
 
3
3
  module ActiveRecord
4
4
  class Base
@@ -1,9 +1,8 @@
1
+ # encoding: utf-8
1
2
 
2
- module ActiveRecord
3
+ module ActiveRecordUtils
3
4
 
4
- module Utils
5
- VERSION = '0.3.0'
6
- end
5
+ VERSION = '0.4.0'
7
6
 
8
- end # module ActiveRecord
7
+ end # module ActiveRecordUtils
9
8
 
@@ -0,0 +1,36 @@
1
+ # encoding: utf-8
2
+
3
+ ###
4
+ # to run use
5
+ # ruby -I ./lib -I ./test test/test_browser.rb
6
+ # or better
7
+ # rake test
8
+
9
+
10
+ require 'helper'
11
+
12
+ class TestBrowser < MiniTest::Test
13
+
14
+ DB_CONFIG = {
15
+ adapter: 'sqlite3',
16
+ database: ':memory:'
17
+ }
18
+
19
+ def test_connect
20
+
21
+ browser = ActiveRecordUtils::Browser.new
22
+
23
+ ## Note: every connect will create a new empty in memory db
24
+ ## check - is it possible to reconnect to in memory db??
25
+ ## use (try) key instead of connection-spec ??
26
+
27
+ con = browser.connection_for( DB_CONFIG )
28
+ tables = con.tables
29
+
30
+ pp tables
31
+
32
+ assert true # for now if get here; assume it's working so far
33
+ end
34
+
35
+ end # class TestBrowser
36
+
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-utils
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-13 00:00:00.000000000 Z
11
+ date: 2015-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: logutils
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activerecord
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rdoc
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -68,10 +82,12 @@ files:
68
82
  - Rakefile
69
83
  - lib/activerecord/utils.rb
70
84
  - lib/activerecord/utils/alias.rb
85
+ - lib/activerecord/utils/browser.rb
71
86
  - lib/activerecord/utils/comp3.rb
72
87
  - lib/activerecord/utils/random.rb
73
88
  - lib/activerecord/utils/version.rb
74
89
  - test/helper.rb
90
+ - test/test_browser.rb
75
91
  - test/test_finders.rb
76
92
  - test/test_random.rb
77
93
  - test/test_readers.rb
@@ -102,6 +118,7 @@ signing_key:
102
118
  specification_version: 4
103
119
  summary: activerecord-utils - utilities (e.g. random, alias_attr, etc.) for activerecord
104
120
  test_files:
121
+ - test/test_browser.rb
105
122
  - test/test_readers.rb
106
123
  - test/test_finders.rb
107
124
  - test/test_random.rb