pampa_workers 0.0.38

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,128 @@
1
+ module BlackStack
2
+
3
+ # no maneja conexion a la base de datos.
4
+ # ejecuta un loop mientras el metodo canRun? retorne true.
5
+ class MyRemoteProcess < BlackStack::MyChildProcess
6
+ #
7
+ attr_accessor :worker
8
+
9
+ # update worker configuration in the division
10
+ def updateWorker()
11
+ #
12
+ self.worker = BlackStack::RemoteWorker.new
13
+ # me notifico a la central. obtengo asignacion si ya la tenia
14
+ url = "#{BlackStack::Pampa::api_url}/api1.3/pampa/get.json"
15
+ res = BlackStack::Netting::call_post(url, {
16
+ 'api_key' => BlackStack::Pampa::api_key,
17
+ 'name' => self.fullWorkerName }.merge( BlackStack::RemoteHost.new.poll )
18
+ )
19
+ parsed = JSON.parse(res.body)
20
+ if (parsed['status'] != BlackStack::Netting::SUCCESS)
21
+ raise parsed['status'].to_s
22
+ else
23
+ self.worker.id = parsed['id']
24
+ self.worker.assigned_process = parsed['assigned_process']
25
+ self.worker.id_object = parsed['id_object']
26
+ self.worker.id_division = parsed['id_division']
27
+ self.worker.division_name = parsed['division_name']
28
+ self.worker.ws_url = parsed['ws_url']
29
+ self.worker.ws_port = parsed['ws_port']
30
+ self.worker.division = BlackStack::RemoteDivision.new
31
+ self.worker.division.name = parsed['division_name']
32
+ end
33
+ end
34
+
35
+ #
36
+ def run()
37
+ super
38
+
39
+ # creo el objeto logger
40
+ self.logger = RemoteLogger.new(
41
+ "#{self.fullWorkerName}.log",
42
+ BlackStack::Pampa::api_protocol,
43
+ BlackStack::Pampa::api_domain,
44
+ BlackStack::Pampa::api_port,
45
+ BlackStack::Pampa::api_key
46
+ )
47
+
48
+ logger.log "Remote process is alive!"
49
+
50
+ # actualiza parametros de la central
51
+ logger.logs "Update from central (1)... "
52
+ self.get
53
+ logger.done
54
+
55
+ # actualizo los datos de este worker (parent process)
56
+ logger.logs "Update worker (1)... "
57
+ self.updateWorker
58
+ logger.done
59
+
60
+ while (self.canRun?)
61
+
62
+ # reseteo en contador nested del logger
63
+ self.logger.reset()
64
+
65
+ # announcing my in the log
66
+ logger.log "Going to Run Remote"
67
+ logger.log "Process: #{self.assigned_process.to_s}."
68
+ logger.log "Object: #{(self.id_object.to_s.size==0)? 'n/a' : self.id_object.to_s}."
69
+
70
+ # obtengo la hora de inicio
71
+ start_time = Time.now
72
+
73
+ begin
74
+ # libero recursos
75
+ logger.logs "Release resources... "
76
+ GC.start
77
+ #DB.disconnect
78
+ logger.done
79
+
80
+ # envia senial a la central.
81
+ # si tiene asignada una division, envia senial a la division.
82
+ logger.logs "Ping... "
83
+ self.ping()
84
+ logger.done
85
+
86
+ # envia senial a la central.
87
+ # si tiene asignada una division, envia senial a la division.
88
+ logger.logs "Notify to Division... "
89
+ self.notify()
90
+ logger.done
91
+
92
+ # corro el procesamiento
93
+ self.process(ARGV)
94
+
95
+ rescue => e
96
+ puts ""
97
+ logger.log "Remote Process Error: " + e.to_s + "\r\n" + e.backtrace.join("\r\n").to_s
98
+ end
99
+
100
+ # actualiza parametros de la central
101
+ logger.logs "Update from central (2)... "
102
+ self.get
103
+ logger.done
104
+
105
+ # actualizo los datos de este worker (parent process)
106
+ logger.logs "Update worker (2)... "
107
+ self.updateWorker
108
+ logger.done
109
+
110
+ # sleep
111
+ logger.logs "Sleep... "
112
+ self.doSleep(start_time)
113
+ logger.done
114
+
115
+ logger.log "-------------------------------------------"
116
+
117
+ GC.start
118
+ #DB.disconnect
119
+
120
+ end # main while
121
+
122
+ #
123
+ logger.log self.whyCantRun()
124
+
125
+ end # run
126
+ end # class MyRemoteProcess
127
+
128
+ end # module BlackStack
@@ -0,0 +1,41 @@
1
+ require_relative './division'
2
+ require_relative './params'
3
+ require_relative './worker'
4
+ require_relative './client'
5
+ require_relative './timezone'
6
+ require_relative './user'
7
+ require_relative './login'
8
+ require_relative './role'
9
+ require_relative './userdivision'
10
+ require_relative './userrole'
11
+
12
+ # funciones auxiliares
13
+ def guid()
14
+ DB['SELECT NEWID() AS [id]'].map(:id)[0]
15
+ end
16
+
17
+ def now()
18
+ # La llamada a GETDATE() desde ODBC no retorna precision de milisegundos, que es necesaria para los registros de log.
19
+ # La llamada a SYSDATETIME() retorna un valor de alta precision que no es compatible para pegar en los campos del tipo DATATIME.
20
+ # La linea de abajo obtiene la hora en formato de SYSDATE y le trunca los ultimos digitos para hacer que el valor sea compatible con los campos DATETIME.
21
+ (DB['SELECT SYSDATETIME() AS [now]'].map(:now)[0]).to_s[0..22]
22
+ end
23
+
24
+ def diff(unit, t0, t1)
25
+ # La llamada a GETDATE() desde ODBC no retorna precision de milisegundos, que es necesaria para los registros de log.
26
+ # La llamada a SYSDATETIME() retorna un valor de alta precision que no es compatible para pegar en los campos del tipo DATATIME.
27
+ # La linea de abajo obtiene la hora en formato de SYSDATE y le trunca los ultimos digitos para hacer que el valor sea compatible con los campos DATETIME.
28
+ (DB["SELECT DATEDIFF(#{unit}, '#{t0.to_s}', '#{t1.to_s}') AS [diff]"].map(:diff)[0]).to_i
29
+ end
30
+
31
+ def before(n) # n minutes
32
+ DB["SELECT DATEADD(mi, -#{n.to_s}, GETDATE()) AS [now]"].map(:now).to_s[0]
33
+ end
34
+
35
+ def monthsFromNow(n) # n months
36
+ DB["SELECT DATEADD(mm, +#{n.to_s}, GETDATE()) AS [now]"].map(:now).to_s[0]
37
+ end
38
+
39
+ def daysFromNow(n) # n days
40
+ DB["SELECT DATEADD(dd, +#{n.to_s}, GETDATE()) AS [now]"].map(:now).to_s[0]
41
+ end
data/lib/pampa.rb ADDED
@@ -0,0 +1,261 @@
1
+ require 'blackstack_commons'
2
+ require 'simple_command_line_parser'
3
+ require 'simple_cloud_logging'
4
+ require 'simple_host_monitoring'
5
+ require 'socket'
6
+ require 'time'
7
+ require 'uri'
8
+ require 'net/http'
9
+ require 'json'
10
+ require 'openssl'
11
+ require 'tiny_tds'
12
+ require 'sequel'
13
+
14
+ #require './lib/base'
15
+ #require './config.rb'
16
+
17
+ require_relative './baseworker'
18
+ require_relative './basedivision'
19
+
20
+ require_relative './remoteworker'
21
+ require_relative './remotedivision'
22
+
23
+ require_relative './myprocess'
24
+ require_relative './mychildprocess'
25
+ require_relative './mylocalprocess'
26
+ require_relative './myparentprocess'
27
+ require_relative './myremoteprocess'
28
+ require_relative './mybotprocess'
29
+ require_relative './mycrawlprocess'
30
+ require_relative './remoteworker'
31
+ require_relative './remotedivision'
32
+
33
+ module BlackStack
34
+
35
+ module Pampa
36
+
37
+ #
38
+ @@division_name = nil
39
+
40
+ def self.division_name()
41
+ @@division_name
42
+ end
43
+
44
+ #
45
+ def self.set_division_name(s)
46
+ @@division_name = s
47
+ end
48
+
49
+ # Api-key of the client who will be the owner of a process.
50
+ @@api_key = nil
51
+
52
+ def self.api_key()
53
+ @@api_key
54
+ end
55
+
56
+ # Protocol, HTTP or HTTPS, of the BlackStack server where this process will be registered.
57
+ @@api_protocol = nil
58
+
59
+ #
60
+ def self.api_protocol
61
+ @@api_protocol
62
+ end
63
+
64
+ # Domain of the BlackStack server where this process will be registered.
65
+ @@api_domain = nil
66
+
67
+ #
68
+ def self.api_domain
69
+ @@api_domain
70
+ end
71
+
72
+ # Port of the BlackStack server where this process will be registered.
73
+ @@api_port = nil
74
+
75
+ #
76
+ def self.api_port
77
+ @@api_port
78
+ end
79
+
80
+ # get the full URL of the worker api server
81
+ def self.api_url()
82
+ "#{BlackStack::Pampa::api_protocol}://#{BlackStack::Pampa::api_domain}:#{BlackStack::Pampa::api_port}"
83
+ end
84
+
85
+ #
86
+ def self.set_api_key(s)
87
+ @@api_key = s
88
+ end
89
+
90
+ #
91
+ def self.set_api_url(h)
92
+ @@api_key = h[:api_key]
93
+ @@api_protocol = h[:api_protocol]
94
+ @@api_domain = h[:api_domain]
95
+ @@api_port = h[:api_port]
96
+ end
97
+
98
+ # path where you will store the data of each client
99
+ @@storage_folder = nil
100
+ @@storage_sub_folders = []
101
+
102
+ #
103
+ def self.storage_folder()
104
+ @@storage_folder
105
+ end
106
+ def self.storage_sub_folders(a)
107
+ @@storage_sub_folder = a
108
+ end
109
+
110
+ #
111
+ def self.set_storage_folder(path)
112
+ @@storage_folder = path
113
+ end
114
+ def self.set_storage_sub_folders(a)
115
+ @@storage_sub_folders = a
116
+ end
117
+
118
+
119
+ #
120
+ # default timezome for any new user
121
+ #
122
+ #
123
+ @@id_timezone_default = nil
124
+
125
+ #
126
+ def self.id_timezone_default()
127
+ @@id_timezone_default
128
+ end
129
+
130
+ #
131
+ def self.set_id_timezone_default(id)
132
+ @@id_timezone_default = id
133
+ end
134
+
135
+ # Array of external IP addresses of the servers where farms are running.
136
+ # If you have many servers running behind a NAT server, only add the IP
137
+ # of the external gateway here. This array is used to know if a worker
138
+ # is running inside your farm datacenter, or it is running in the computer
139
+ # of someone else.
140
+ @@farm_external_ip_addresses = []
141
+
142
+ #
143
+ def self.farm_external_ip_addresses()
144
+ @@farm_external_ip_addresses
145
+ end
146
+
147
+ #
148
+ def self.set_farm_external_ip_addresses(a)
149
+ @@farm_external_ip_addresses = a
150
+ end
151
+
152
+ #
153
+ def self.get_guid
154
+ res = BlackStack::Netting::call_post(
155
+ "#{self.api_url}/api1.4/get_guid.json",
156
+ {'api_key' => @@api_key}
157
+ )
158
+ parsed = JSON.parse(res.body)
159
+ parsed['value']
160
+ end
161
+
162
+ # Central database connection parameters
163
+ @@db_url = nil
164
+ @@db_port = nil
165
+ @@db_name = nil
166
+ @@db_user = nil
167
+ @@db_password = nil
168
+
169
+ #
170
+ def self.db_url
171
+ @@db_url
172
+ end
173
+
174
+ #
175
+ def self.db_port
176
+ @@db_port
177
+ end
178
+
179
+ #
180
+ def self.db_name
181
+ @@db_name
182
+ end
183
+
184
+ #
185
+ def self.db_user
186
+ @@db_user
187
+ end
188
+
189
+ #
190
+ def self.db_password
191
+ @@db_password
192
+ end
193
+
194
+ # Set connection params to the central database
195
+ def self.set_db_params(h)
196
+ @@db_url = h[:db_url]
197
+ @@db_port = h[:db_port]
198
+ @@db_name = h[:db_name]
199
+ @@db_user = h[:db_user]
200
+ @@db_password = h[:db_password]
201
+ end
202
+
203
+ # TODO: doc me!
204
+ def self.connection_descriptor()
205
+ ret = nil
206
+
207
+ # validar que el formato no sea nulo
208
+ if (self.division_name.to_s.length == 0)
209
+ raise "Division name expected."
210
+ end
211
+
212
+ if (self.division_name == "local")
213
+ ret = {
214
+ :adapter => 'tinytds',
215
+ :dataserver => BlackStack::Pampa::db_url, # IP or hostname
216
+ :port => BlackStack::Pampa::db_port, # Required when using other that 1433 (default)
217
+ :database => BlackStack::Pampa::db_name,
218
+ :user => BlackStack::Pampa::db_user,
219
+ :password => BlackStack::Pampa::db_password
220
+ }
221
+ else
222
+ url = "#{BlackStack::Pampa::api_url}/api1.2/division/get.json"
223
+ res = BlackStack::Netting::call_post(url, {
224
+ 'api_key' => BlackStack::Pampa::api_key,
225
+ 'dname' => "#{self.division_name}",
226
+ })
227
+ parsed = JSON.parse(res.body)
228
+
229
+ if (parsed["status"] != BlackStack::Netting::SUCCESS)
230
+ raise "Error getting connection string: #{parsed["status"]}"
231
+ else
232
+ wid = parsed["value"]
233
+
234
+ ret = {
235
+ :adapter => 'tinytds',
236
+ :dataserver => parsed["db_url"], # IP or hostname
237
+ :port => parsed["db_port"], # only required if port is different than 1433
238
+ :database => parsed["db_name"],
239
+ :user => parsed["db_user"],
240
+ :password => parsed["db_password"]
241
+ }
242
+ end
243
+ end
244
+
245
+ ret
246
+ end # connectionDescriptor
247
+
248
+ #
249
+ def self.db_connection()
250
+ Sequel.connect(BlackStack::Pampa::connection_descriptor)
251
+ end
252
+
253
+ #
254
+ def self.require_db_classes()
255
+ # You have to load all the Sinatra classes after connect the database.
256
+ require_relative '../lib/pampa-local.rb'
257
+ end
258
+
259
+ end # module Pampa
260
+
261
+ end # module BlackStack
data/lib/params.rb ADDED
@@ -0,0 +1,50 @@
1
+ module BlackStack
2
+
3
+ class Params < Sequel::Model(:params)
4
+ Params.dataset = Params.dataset.disable_insert_output
5
+
6
+ def self.getValue(s)
7
+ param = Params.where(:name=>s).first
8
+ if (param == nil)
9
+ raise "Unknown parameter name (#{s.to_s})"
10
+ else
11
+ if param.type == PARAM_TYPE_VARCHAR
12
+ return param.value_varchar.to_s
13
+ elsif param.type == PARAM_TYPE_NUMERIC
14
+ return param.value_numeric.to_i
15
+ elsif param.type == PARAM_TYPE_DATETIME
16
+ return param.value_datetime
17
+ elsif param.type == PARAM_TYPE_BIT
18
+ return param.value_bit
19
+ else
20
+ raise "Unknown parameter type (#{param.type.to_s})."
21
+ end # if param.type
22
+ end # if (param == nil)
23
+ end # def self.getValue
24
+
25
+ def self.setValue(s, v) # TODO: Testear este metodo
26
+ param = Params.where(:name=>s).first
27
+ if (param == nil)
28
+ raise "Unknown parameter name (#{s.to_s})"
29
+ else
30
+ if param.type == PARAM_TYPE_VARCHAR
31
+ param.value_varchar = v
32
+ param.save()
33
+ elsif param.type == PARAM_TYPE_NUMERIC
34
+ param.value_numeric = v
35
+ param.save()
36
+ elsif param.type == PARAM_TYPE_DATETIME
37
+ param.value_datetime = v
38
+ param.save()
39
+ elsif param.type == PARAM_TYPE_BIT
40
+ param.value_bit = v
41
+ param.save()
42
+ else
43
+ raise "Unknown parameter type (#{param.type.to_s})."
44
+ end # if param.type
45
+ end # if (param == nil)
46
+ end # def self.getValue
47
+
48
+ end # class
49
+
50
+ end # module BlackStack
@@ -0,0 +1,8 @@
1
+ module BlackStack
2
+
3
+ class RemoteDivision
4
+ attr_accessor :name
5
+ include BlackStack::BaseDivision
6
+ end # RemoteDivision
7
+
8
+ end # module BlackStack
@@ -0,0 +1,8 @@
1
+ module BlackStack
2
+
3
+ class RemoteWorker
4
+ attr_accessor :id, :process, :last_ping_time, :name, :active, :id_division, :assigned_process, :id_object, :division_name, :ws_url, :ws_port, :division
5
+ include BlackStack::BaseWorker
6
+ end # Remote Worker
7
+
8
+ end # module BlackStack
data/lib/role.rb ADDED
@@ -0,0 +1,8 @@
1
+ module BlackStack
2
+ class Role < Sequel::Model(:role)
3
+ BlackStack::Role.dataset = BlackStack::Role.dataset.disable_insert_output
4
+
5
+ ROLE_PRISMA_USER = "prisma.user"
6
+
7
+ end
8
+ end # module BlackStack
data/lib/timezone.rb ADDED
@@ -0,0 +1,151 @@
1
+ module BlackStack
2
+ class Timezone < Sequel::Model(:timezone)
3
+ BlackStack::Timezone.dataset = BlackStack::Timezone.dataset.disable_insert_output
4
+
5
+ # Recibe un string con formato "+HH:MM".
6
+ # Retorna la cantidad de horas como un numero real, con decimales.
7
+ def self.descToFloat(s)
8
+ sign = s[0]
9
+ if (sign=="+")
10
+ n = 1.0
11
+ else
12
+ n = -1.0
13
+ end
14
+ hours = s[1..2]
15
+ minutes = s[4..5]
16
+ int_part = hours.to_f
17
+ dec_part = minutes.to_f / 60.00
18
+ ret = n*(int_part + dec_part)
19
+ return ret.to_f
20
+ end
21
+
22
+ # Recibe la cantidad de horas como un numero real, con decimales.
23
+ # Retorna un string con formato "+HH:MM".
24
+ def self.floatToDesc(x)
25
+ int_part = x.to_i
26
+ dec_part = (x-int_part.to_f).round(2).abs
27
+ hours = int_part
28
+ minutes = (dec_part * 60.00).to_i
29
+ if (hours<0)
30
+ desc = "%03d" % hours
31
+ else
32
+ desc = "+" + "%02d" % hours
33
+ end
34
+ desc += ":" + "%02d" % minutes
35
+ return desc
36
+ end
37
+
38
+ # Example: '-03:00'
39
+ # Example: ' 08:00'
40
+ def self.getDatabaseOffset()
41
+ dbtime = DB["select SYSDATETIMEOFFSET() AS o"].first[:o].to_s
42
+ #puts ""
43
+ #puts ""
44
+ #puts "dbtime:#{dbtime.to_s}:."
45
+ #puts ""
46
+ #puts ""
47
+ ret = "#{dbtime[-5..-3]}:#{dbtime[-2..-1]}"
48
+ ret[0] = '+' if ret[0]!='-'
49
+ #puts ""
50
+ #puts ""
51
+ #puts "dbtime:#{ret.to_s}:."
52
+ #puts ""
53
+ #puts ""
54
+ return ret
55
+ end
56
+
57
+ # Convierte el atributo offset en un string con formato de hora.
58
+ # Ejemplos: 5.0 => 05:00, 5.5 => 05:30, -5.75 => -05:45
59
+ def offsetDescription()
60
+ return BlackStack::Timezone.floatToDesc(self.offset.to_f)
61
+ end
62
+
63
+ # Convierte una hora almacenada en el servidor de bases de datos, a la hora en esta zona horaria.
64
+ # Recibe un string con formato "+HH:MM".
65
+ # Retorna un string con formato "+HH:MM".
66
+ def convertFromThisTimeZoneToDatabaseTime(s_time_in_client_timezone)
67
+ f_time_in_client_timezone = BlackStack::Timezone.descToFloat(s_time_in_client_timezone)
68
+ s = BlackStack::Timezone.getDatabaseOffset()
69
+ x = BlackStack::Timezone.descToFloat(s) # database offset
70
+ y = self.offset # client offset
71
+ z = y - x
72
+ return BlackStack::Timezone.floatToDesc((f_time_in_client_timezone.to_f + z.to_f).modulo(24))
73
+ end
74
+
75
+ # Convierte una hora almacenada en el servidor de bases de datos, a la hora en esta zona horaria.
76
+ # Recibe un string con formato "+HH:MM".
77
+ # Retorna un string con formato "+HH:MM".
78
+ def convertFromDatabaseTimeToThisTimeZone(s_time_in_database)
79
+ f_time_in_database = BlackStack::Timezone.descToFloat(s_time_in_database)
80
+ s = BlackStack::Timezone.getDatabaseOffset()
81
+ x = BlackStack::Timezone.descToFloat(s) # database offset
82
+ y = self.offset # client offset
83
+ z = y - x
84
+ return BlackStack::Timezone.floatToDesc((f_time_in_database.to_f - z.to_f).modulo(24))
85
+ end
86
+
87
+ # Convierte una fecha-hora almacenada en el servidor de bases de datos, a la hora en esta zona horaria.
88
+ # Recibe un string con formato "YYYY-MM-DD HH:MM:SS".
89
+ # Retorna un string con formato "YYYY-MM-DD HH:MM:SS".
90
+ def convertFromDatabaseDateTimeToThisTimeZone(s_datetime_in_database)
91
+ s = BlackStack::Timezone.getDatabaseOffset() # Example: '-03:00'
92
+ #puts ""
93
+ #puts ""
94
+ #puts "s:#{s.to_s}:."
95
+ #puts ""
96
+ #puts ""
97
+ x = BlackStack::Timezone.descToFloat(s) # database offset. Number of hours, with decimals
98
+ #puts ""
99
+ #puts ""
100
+ #puts "x:#{x.to_s}:."
101
+ #puts ""
102
+ #puts ""
103
+ y = self.offset # client offset
104
+ #puts ""
105
+ #puts ""
106
+ #puts "y:#{y.to_s}:."
107
+ #puts ""
108
+ #puts ""
109
+ z = y - x
110
+ #puts ""
111
+ #puts ""
112
+ #puts "z:#{z.to_s}:."
113
+ #puts ""
114
+ #puts ""
115
+ ret = DB["SELECT DATEADD(HH, #{z.to_s}, '#{s_datetime_in_database}') AS o"].first[:o].to_s[0..18]
116
+ #puts ""
117
+ #puts ""
118
+ #puts "convertFromDatabaseDateTimeToThisTimeZone:#{ret}:."
119
+ #puts ""
120
+ #puts ""
121
+
122
+ return ret
123
+ end
124
+
125
+ #
126
+ def get_now()
127
+ datetime1 = DB["SELECT GETDATE() AS o"].first[:o].to_s[0..18]
128
+ datetime2 = self.convertFromDatabaseDateTimeToThisTimeZone(datetime1)
129
+ #puts ""
130
+ #puts ""
131
+ #puts "timezone:#{self.large_description}:."
132
+ #puts "datetime1:#{datetime1}:."
133
+ #puts "datetime2:#{datetime2}:."
134
+ #puts ""
135
+ #puts ""
136
+ yy = datetime2[0..3] # yyyy-mm-dd hh:mi:ss
137
+ mm = datetime2[5..6]
138
+ dd = datetime2[8..9]
139
+ hh = datetime2[11..12]
140
+ mi = datetime2[14..15]
141
+ ss = datetime2[17..18]
142
+ #puts ""
143
+ #puts ""
144
+ #puts "get_now:#{yy}-#{mm}-#{dd} #{hh}:#{mi}:#{ss}:."
145
+ #puts ""
146
+ #puts ""
147
+ return Time.new(yy,mm,dd,hh,mi,ss)
148
+ end
149
+
150
+ end
151
+ end # module BlackStack
data/lib/user.rb ADDED
@@ -0,0 +1,25 @@
1
+ module BlackStack
2
+ class User < Sequel::Model(:user)
3
+ BlackStack::User.dataset = BlackStack::User.dataset.disable_insert_output
4
+ many_to_one :client, :class=>:'BlackStack::Client', :key=>:id_client
5
+ one_to_many :user_roles, :class=>:'BlackStack::UserRole', :key=>:id_user
6
+
7
+ # TODO: agregar todos los arrays de un usuario
8
+ # => one_to_many :searches, :class=>:Search, :key=>:id_user
9
+ # => one_to_many :emlist, :class=>:EmList, :key=>:id_user
10
+ # => one_to_many :emlist, :class=>:EmList, :key=>:id_user
11
+ # => etc.
12
+
13
+ # retorna la primera division habilitada a la que pertenezca este usuario
14
+ def division
15
+ row = DB[
16
+ "SELECT d.id " +
17
+ "FROM division d WITH (NOLOCK) " +
18
+ "JOIN user_division ud WITH (NOLOCK) ON (d.id=ud.id_division AND ud.id_user='#{self.id}') " +
19
+ "WHERE ISNULL(d.available,0) = 1 "
20
+ ].first
21
+ return nil if row.nil?
22
+ return BlackStack::Division.where(:id=>row[:id]).first if !row.nil?
23
+ end
24
+ end # class User
25
+ end # module BlackStack
@@ -0,0 +1,5 @@
1
+ module BlackStack
2
+ class UserDivision < Sequel::Model(:user_division)
3
+ BlackStack::UserDivision.dataset = BlackStack::UserDivision.dataset.disable_insert_output
4
+ end
5
+ end # module BlackStack
data/lib/userrole.rb ADDED
@@ -0,0 +1,8 @@
1
+ module BlackStack
2
+ class UserRole < Sequel::Model(:user_role)
3
+ BlackStack::UserRole.dataset = BlackStack::UserRole.dataset.disable_insert_output
4
+ many_to_one :user, :class=>:'BlackStack::User', :key=>:id_user
5
+ many_to_one :role, :class=>:'BlackStack::Role', :key=>:id_role
6
+
7
+ end
8
+ end # module BlackStack