baza 0.0.20 → 0.0.21
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +84 -0
- data/.rubocop_todo.yml +17 -135
- data/.travis.yml +21 -0
- data/Gemfile +10 -7
- data/Gemfile.lock +39 -44
- data/README.md +61 -3
- data/VERSION +1 -1
- data/baza.gemspec +146 -98
- data/config/best_project_practice_rubocop.yml +8 -0
- data/config/best_project_practice_rubocop_todo.yml +6 -0
- data/lib/baza.rb +8 -12
- data/lib/baza/base_sql_driver.rb +198 -52
- data/lib/baza/cloner.rb +1 -0
- data/lib/baza/column.rb +26 -0
- data/lib/baza/database.rb +19 -3
- data/lib/baza/db.rb +69 -271
- data/lib/baza/driver.rb +1 -6
- data/lib/baza/{drivers → driver}/active_record.rb +65 -21
- data/lib/baza/{drivers → driver}/active_record/columns.rb +0 -0
- data/lib/baza/driver/active_record/commands.rb +10 -0
- data/lib/baza/driver/active_record/databases.rb +10 -0
- data/lib/baza/{drivers → driver}/active_record/indexes.rb +0 -0
- data/lib/baza/{drivers → driver}/active_record/result.rb +3 -1
- data/lib/baza/{drivers → driver}/active_record/tables.rb +0 -0
- data/lib/baza/driver/active_record/users.rb +12 -0
- data/lib/baza/{drivers → driver}/mysql.rb +9 -26
- data/lib/baza/{drivers → driver}/mysql/column.rb +14 -35
- data/lib/baza/{drivers → driver}/mysql/columns.rb +9 -12
- data/lib/baza/driver/mysql/commands.rb +39 -0
- data/lib/baza/driver/mysql/database.rb +64 -0
- data/lib/baza/driver/mysql/databases.rb +63 -0
- data/lib/baza/{drivers → driver}/mysql/index.rb +0 -0
- data/lib/baza/{drivers → driver}/mysql/indexes.rb +0 -0
- data/lib/baza/{drivers → driver}/mysql/result.rb +15 -7
- data/lib/baza/{drivers → driver}/mysql/sqlspecs.rb +0 -0
- data/lib/baza/{drivers → driver}/mysql/table.rb +27 -43
- data/lib/baza/{drivers → driver}/mysql/tables.rb +5 -34
- data/lib/baza/{drivers → driver}/mysql/unbuffered_result.rb +8 -2
- data/lib/baza/driver/mysql/user.rb +22 -0
- data/lib/baza/driver/mysql/users.rb +39 -0
- data/lib/baza/{drivers → driver}/mysql2.rb +19 -49
- data/lib/baza/{drivers → driver}/mysql2/column.rb +0 -0
- data/lib/baza/{drivers → driver}/mysql2/columns.rb +0 -0
- data/lib/baza/driver/mysql2/commands.rb +2 -0
- data/lib/baza/{drivers → driver}/mysql2/database.rb +0 -0
- data/lib/baza/{drivers → driver}/mysql2/databases.rb +0 -0
- data/lib/baza/{drivers → driver}/mysql2/index.rb +0 -0
- data/lib/baza/{drivers → driver}/mysql2/indexes.rb +0 -0
- data/lib/baza/{drivers → driver}/mysql2/result.rb +3 -1
- data/lib/baza/{drivers → driver}/mysql2/table.rb +0 -0
- data/lib/baza/{drivers → driver}/mysql2/tables.rb +0 -0
- data/lib/baza/driver/mysql2/user.rb +2 -0
- data/lib/baza/driver/mysql2/users.rb +2 -0
- data/lib/baza/{drivers → driver}/mysql_java.rb +60 -38
- data/lib/baza/{drivers → driver}/mysql_java/column.rb +0 -0
- data/lib/baza/{drivers → driver}/mysql_java/columns.rb +0 -0
- data/lib/baza/driver/mysql_java/commands.rb +2 -0
- data/lib/baza/driver/mysql_java/database.rb +2 -0
- data/lib/baza/driver/mysql_java/databases.rb +2 -0
- data/lib/baza/{drivers → driver}/mysql_java/index.rb +0 -0
- data/lib/baza/{drivers → driver}/mysql_java/indexes.rb +0 -0
- data/lib/baza/{drivers → driver}/mysql_java/table.rb +0 -0
- data/lib/baza/{drivers → driver}/mysql_java/tables.rb +0 -0
- data/lib/baza/driver/mysql_java/user.rb +2 -0
- data/lib/baza/driver/mysql_java/users.rb +2 -0
- data/lib/baza/driver/pg.rb +80 -0
- data/lib/baza/driver/pg/column.rb +125 -0
- data/lib/baza/driver/pg/columns.rb +37 -0
- data/lib/baza/driver/pg/commands.rb +35 -0
- data/lib/baza/driver/pg/create_index_sql_creator.rb +51 -0
- data/lib/baza/driver/pg/database.rb +89 -0
- data/lib/baza/driver/pg/databases.rb +79 -0
- data/lib/baza/driver/pg/index.rb +35 -0
- data/lib/baza/driver/pg/indexes.rb +5 -0
- data/lib/baza/driver/pg/result.rb +139 -0
- data/lib/baza/driver/pg/table.rb +184 -0
- data/lib/baza/driver/pg/tables.rb +45 -0
- data/lib/baza/{drivers → driver}/sqlite3.rb +6 -24
- data/lib/baza/{drivers → driver}/sqlite3/column.rb +22 -24
- data/lib/baza/{drivers → driver}/sqlite3/columns.rb +6 -6
- data/lib/baza/driver/sqlite3/commands.rb +28 -0
- data/lib/baza/{drivers → driver}/sqlite3/database.rb +0 -0
- data/lib/baza/{drivers → driver}/sqlite3/databases.rb +0 -1
- data/lib/baza/{drivers → driver}/sqlite3/index.rb +0 -0
- data/lib/baza/{drivers → driver}/sqlite3/indexes.rb +0 -0
- data/lib/baza/{drivers → driver}/sqlite3/result.rb +14 -6
- data/lib/baza/{drivers → driver}/sqlite3/sqlspecs.rb +0 -0
- data/lib/baza/{drivers → driver}/sqlite3/table.rb +25 -16
- data/lib/baza/{drivers → driver}/sqlite3/tables.rb +5 -6
- data/lib/baza/{drivers → driver}/sqlite3/unbuffered_result.rb +8 -2
- data/lib/baza/{drivers → driver}/sqlite3_java.rb +13 -23
- data/lib/baza/{drivers → driver}/sqlite3_java/column.rb +0 -0
- data/lib/baza/{drivers → driver}/sqlite3_java/columns.rb +0 -0
- data/lib/baza/driver/sqlite3_java/commands.rb +2 -0
- data/lib/baza/{drivers → driver}/sqlite3_java/database.rb +0 -0
- data/lib/baza/{drivers → driver}/sqlite3_java/index.rb +0 -0
- data/lib/baza/{drivers → driver}/sqlite3_java/indexes.rb +0 -0
- data/lib/baza/{drivers → driver}/sqlite3_java/table.rb +0 -0
- data/lib/baza/{drivers → driver}/sqlite3_java/tables.rb +0 -0
- data/lib/baza/{drivers → driver}/sqlite3_java/unbuffered_result.rb +14 -9
- data/lib/baza/{drivers → driver}/sqlite3_rhodes.rb +6 -24
- data/lib/baza/errors.rb +2 -0
- data/lib/baza/idquery.rb +15 -8
- data/lib/baza/index.rb +7 -0
- data/lib/baza/jdbc_driver.rb +4 -16
- data/lib/baza/jdbc_result.rb +20 -12
- data/lib/baza/mysql_base_driver.rb +7 -7
- data/lib/baza/query_buffer.rb +20 -19
- data/lib/baza/row.rb +16 -16
- data/lib/baza/sql_queries.rb +3 -0
- data/lib/baza/sql_queries/generic_insert.rb +81 -0
- data/lib/baza/sql_queries/generic_update.rb +31 -0
- data/lib/baza/sql_queries/mysql_upsert.rb +52 -0
- data/lib/baza/sql_queries/mysql_upsert_duplicate_key.rb +57 -0
- data/lib/baza/sql_queries/non_atomic_upsert.rb +25 -0
- data/lib/baza/sql_queries/postgres_upsert_duplicate_key.rb +118 -0
- data/lib/baza/sql_queries/select.rb +170 -0
- data/lib/baza/sql_queries/sqlite_upsert_duplicate_key.rb +99 -0
- data/lib/baza/table.rb +35 -8
- data/spec/active_record/models/user.rb +3 -0
- data/spec/{cloner_spec.rb → baza/cloner_spec.rb} +0 -0
- data/spec/drivers/active_record_mysql2_spec.rb +5 -3
- data/spec/drivers/active_record_mysql_spec.rb +2 -1
- data/spec/drivers/active_record_pg_spec.rb +20 -0
- data/spec/drivers/active_record_sqlite3_spec.rb +2 -1
- data/spec/drivers/mysql2_spec.rb +1 -1
- data/spec/drivers/mysql_spec.rb +10 -10
- data/spec/drivers/pg_spec.rb +18 -0
- data/spec/drivers/sqlite3_spec.rb +7 -8
- data/spec/info_active_record_example.rb +1 -1
- data/spec/{info_active_record_mysql2.rb → info_active_record_mysql2_example.rb} +3 -2
- data/spec/info_active_record_mysql2_travis.rb +35 -0
- data/spec/{info_active_record_mysql.rb → info_active_record_mysql_example.rb} +5 -4
- data/spec/info_active_record_mysql_travis.rb +36 -0
- data/spec/info_active_record_pg_example.rb +36 -0
- data/spec/info_active_record_pg_travis.rb +34 -0
- data/spec/info_active_record_sqlite3.rb +1 -1
- data/spec/info_mysql2_example.rb +1 -3
- data/spec/{info_mysql2_shippable.rb → info_mysql2_travis.rb} +2 -4
- data/spec/info_mysql_example.rb +1 -3
- data/spec/{info_mysql_shippable.rb → info_mysql_travis.rb} +2 -4
- data/spec/info_pg_example.rb +22 -0
- data/spec/info_pg_travis.rb +20 -0
- data/spec/info_sqlite3.rb +1 -3
- data/spec/spec_helper.rb +1 -1
- data/spec/support/driver_active_record_collection.rb +62 -0
- data/spec/support/driver_collection.rb +136 -121
- data/spec/support/driver_columns_collection.rb +19 -10
- data/spec/support/driver_databases_collection.rb +23 -1
- data/spec/support/driver_indexes_collection.rb +2 -2
- data/spec/support/driver_tables_collection.rb +24 -4
- data/spec/support/driver_users_collection.rb +53 -0
- metadata +185 -104
- data/lib/baza/drivers/mysql/database.rb +0 -28
- data/lib/baza/drivers/mysql/databases.rb +0 -35
- data/lib/baza/drivers/mysql_java/database.rb +0 -2
- data/lib/baza/drivers/mysql_java/databases.rb +0 -2
- data/lib/baza/model.rb +0 -875
- data/lib/baza/model_custom.rb +0 -155
- data/lib/baza/model_handler.rb +0 -910
- data/lib/baza/model_handler_sqlhelper.rb +0 -484
- data/lib/baza/revision.rb +0 -383
- data/shippable.yml +0 -17
- data/spec/info_active_record_mysql2_shippable.rb +0 -34
- data/spec/info_active_record_mysql_shippable.rb +0 -34
- data/spec/model_handler_spec.rb +0 -431
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
class Baza::Driver::Mysql::Database < Baza::Database
|
|
2
|
-
def save!
|
|
3
|
-
rename(name) unless name.to_s == name_was
|
|
4
|
-
self
|
|
5
|
-
end
|
|
6
|
-
|
|
7
|
-
def drop
|
|
8
|
-
sql = "DROP DATABASE `#{@db.escape_database(name)}`"
|
|
9
|
-
@db.query(sql)
|
|
10
|
-
self
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
private
|
|
14
|
-
|
|
15
|
-
def rename(new_name)
|
|
16
|
-
new_name = new_name.to_s
|
|
17
|
-
@db.databases.create(name: new_name)
|
|
18
|
-
|
|
19
|
-
tables.each do |table|
|
|
20
|
-
@db.query("ALTER TABLE `#{@db.escape_database(name_was)}`.`#{@db.escape_table(table.name)}` RENAME `#{@db.escape_database(name)}`.`#{@db.escape_table(table.name)}`")
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
@db.query("DROP DATABASE `#{@db.escape_database(name_was)}`")
|
|
24
|
-
|
|
25
|
-
@name = new_name
|
|
26
|
-
@name_was = new_name
|
|
27
|
-
end
|
|
28
|
-
end
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
class Baza::Driver::Mysql::Databases
|
|
2
|
-
def initialize(args)
|
|
3
|
-
@db = args.fetch(:db)
|
|
4
|
-
end
|
|
5
|
-
|
|
6
|
-
def create(args)
|
|
7
|
-
sql = "CREATE DATABASE"
|
|
8
|
-
sql << " IF NOT EXISTS" if args[:if_not_exists]
|
|
9
|
-
sql << " `#{@db.escape_table(args.fetch(:name))}`"
|
|
10
|
-
|
|
11
|
-
@db.query(sql)
|
|
12
|
-
true
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def [](name)
|
|
16
|
-
name = name.to_s
|
|
17
|
-
list.each do |database|
|
|
18
|
-
return database if database.name == name
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
raise Baza::Errors::DatabaseNotFound
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def list
|
|
25
|
-
ArrayEnumerator.new do |yielder|
|
|
26
|
-
@db.query("SHOW DATABASES") do |data|
|
|
27
|
-
yielder << Baza::Driver::Mysql::Database.new(
|
|
28
|
-
name: data.fetch(:Database),
|
|
29
|
-
driver: self,
|
|
30
|
-
db: @db
|
|
31
|
-
)
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
data/lib/baza/model.rb
DELETED
|
@@ -1,875 +0,0 @@
|
|
|
1
|
-
# This class helps create models in a framework with Baza::Db and Baza::ModelHandler.
|
|
2
|
-
#===Examples
|
|
3
|
-
# db = Baza::Db.new(type: :sqlite3, path: "somepath.sqlite3")
|
|
4
|
-
# ob = Baza::ModelHandler.new(db: db, datarow: true, path: "path_of_model_class_files")
|
|
5
|
-
# user = ob.get(:User, 1) #=> <Models::User> that extends <Baza::Datarow>
|
|
6
|
-
class Baza::Model
|
|
7
|
-
@@refs = {}
|
|
8
|
-
|
|
9
|
-
# Returns the Baza::ModelHandler which handels this model.
|
|
10
|
-
def ob
|
|
11
|
-
self.class.ob
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
# Returns the Baza::Db which handels this model.
|
|
15
|
-
def db
|
|
16
|
-
self.class.db
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
# Returns the 'Baza::ModelHandler'-object that handels this class.
|
|
20
|
-
class << self
|
|
21
|
-
attr_reader :ob
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
# Returns the 'Baza::Db'-object that handels this class.
|
|
25
|
-
class << self
|
|
26
|
-
attr_reader :db
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
# This is used by 'Baza::ModelHandler' to find out what data is required for this class. Returns the array that tells about required data.
|
|
30
|
-
#===Examples
|
|
31
|
-
# When adding a new user, this can fail if the ':group_id' is not given, or the ':group_id' doesnt refer to a valid group-row in the db.
|
|
32
|
-
# class Models::User < Baza::Datarow
|
|
33
|
-
# has_one [
|
|
34
|
-
# {class: :Group, col: :group_id, method: :group, required: true}
|
|
35
|
-
# ]
|
|
36
|
-
# end
|
|
37
|
-
def self.required_data
|
|
38
|
-
@required_data = [] unless @required_data
|
|
39
|
-
@required_data
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
# This is used by 'Baza::ModelHandler' to find out what other objects this class depends on. Returns the array that tells about depending data.
|
|
43
|
-
#===Examples
|
|
44
|
-
# This will tell Baza::ModelHandler that files depends on users. It can prevent the user from being deleted, if any files depend on it.
|
|
45
|
-
# class Models::User < Baza::Datarow
|
|
46
|
-
# has_many [
|
|
47
|
-
# {class: :File, col: :user_id, method: :files, depends: true}
|
|
48
|
-
# ]
|
|
49
|
-
# end
|
|
50
|
-
class << self
|
|
51
|
-
attr_reader :depending_data
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
# Returns true if this class has been initialized.
|
|
55
|
-
def self.initialized?
|
|
56
|
-
false unless @columns_sqlhelper_args
|
|
57
|
-
true
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
# This is used by 'Baza::ModelHandler' to find out which other objects should be deleted when an object of this class is deleted automatically. Returns the array that tells about autodelete data.
|
|
61
|
-
#===Examples
|
|
62
|
-
# This will trigger Baza::ModelHandler to automatically delete all the users pictures, when deleting the current user.
|
|
63
|
-
# class Models::User < Baza::Datarow
|
|
64
|
-
# has_many [
|
|
65
|
-
# {class: :Picture, col: :user_id, method: :pictures, autodelete: true}
|
|
66
|
-
# ]
|
|
67
|
-
# end
|
|
68
|
-
class << self
|
|
69
|
-
attr_reader :autodelete_data
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
# Returns the autozero-data (if any).
|
|
73
|
-
class << self
|
|
74
|
-
attr_reader :autozero_data
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
class << self
|
|
78
|
-
attr_accessor :classname
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
# This helps various parts of the framework determine if this is a datarow class without requiring it.
|
|
82
|
-
#===Examples
|
|
83
|
-
# print "This is a knj-object." if obj.respond_to?("is_knj?")
|
|
84
|
-
def knj?
|
|
85
|
-
true
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
# This tests if a certain string is a date-null-stamp.
|
|
89
|
-
#===Examples
|
|
90
|
-
# time_str = dbrow[:date]
|
|
91
|
-
# print "No valid date on the row." if Baza::Datarow.is_nullstamp?(time_str)
|
|
92
|
-
def self.nullstamp?(stamp)
|
|
93
|
-
return true if !stamp || stamp == "0000-00-00 00:00:00" || stamp == "0000-00-00"
|
|
94
|
-
false
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
# This is used to define datarows that this object can have a lot of.
|
|
98
|
-
#===Examples
|
|
99
|
-
# This will define the method "pictures" on 'Models::User' that will return all pictures for the users and take possible Objects-sql-arguments. It will also enabling joining pictures when doing Objects-sql-lookups.
|
|
100
|
-
# class Models::User < Baza::Datarow
|
|
101
|
-
# has_many [
|
|
102
|
-
# [:Picture, :user_id, :pictures],
|
|
103
|
-
# {class: :File, col: :user_id, method: :files}
|
|
104
|
-
# ]
|
|
105
|
-
# end
|
|
106
|
-
def self.has_many(arr)
|
|
107
|
-
arr.each do |val|
|
|
108
|
-
if val.is_a?(Array)
|
|
109
|
-
classname, colname, methodname = *val
|
|
110
|
-
elsif val.is_a?(Hash)
|
|
111
|
-
classname = nil
|
|
112
|
-
colname = nil
|
|
113
|
-
methodname = nil
|
|
114
|
-
|
|
115
|
-
val.each do |hkey, hval|
|
|
116
|
-
case hkey
|
|
117
|
-
when :class
|
|
118
|
-
classname = hval
|
|
119
|
-
when :col
|
|
120
|
-
colname = hval
|
|
121
|
-
when :method
|
|
122
|
-
methodname = hval
|
|
123
|
-
when :depends, :autodelete, :autozero, :where
|
|
124
|
-
# Ignore
|
|
125
|
-
else
|
|
126
|
-
raise "Invalid key for 'has_many': '#{hkey}'."
|
|
127
|
-
end
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
colname = "#{name.to_s.split("::").last.to_s.downcase}_id" if colname.to_s.empty?
|
|
131
|
-
|
|
132
|
-
if val[:depends]
|
|
133
|
-
@depending_data = [] unless @depending_data
|
|
134
|
-
@depending_data << {
|
|
135
|
-
colname: colname,
|
|
136
|
-
classname: classname
|
|
137
|
-
}
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
if val[:autodelete]
|
|
141
|
-
@autodelete_data = [] unless @autodelete_data
|
|
142
|
-
@autodelete_data << {
|
|
143
|
-
colname: colname,
|
|
144
|
-
classname: classname
|
|
145
|
-
}
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
if val[:autozero]
|
|
149
|
-
@autozero_data = [] unless @autozero_data
|
|
150
|
-
@autozero_data << {
|
|
151
|
-
colname: colname,
|
|
152
|
-
classname: classname
|
|
153
|
-
}
|
|
154
|
-
end
|
|
155
|
-
else
|
|
156
|
-
raise "Unknown argument: '#{val.class.name}'."
|
|
157
|
-
end
|
|
158
|
-
|
|
159
|
-
raise "No classname given." unless classname
|
|
160
|
-
methodname = "#{StringCases.camel_to_snake(classname)}s" unless methodname
|
|
161
|
-
raise "No column was given for '#{name}' regarding has-many-class: '#{classname}'." unless colname
|
|
162
|
-
|
|
163
|
-
if val.is_a?(Hash) && val.key?(:where)
|
|
164
|
-
where_args = val[:where]
|
|
165
|
-
else
|
|
166
|
-
where_args = nil
|
|
167
|
-
end
|
|
168
|
-
|
|
169
|
-
define_many_methods(classname, methodname, colname, where_args)
|
|
170
|
-
|
|
171
|
-
joined_tables(
|
|
172
|
-
classname => {
|
|
173
|
-
where: {
|
|
174
|
-
colname.to_s => {type: :col, name: :id}
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
)
|
|
178
|
-
end
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
# This define is this object has one element of another datarow-class. It define various methods and joins based on that.
|
|
182
|
-
#===Examples
|
|
183
|
-
# class Models::User < Baza::Datarow
|
|
184
|
-
# has_one [
|
|
185
|
-
# #Defines the method 'group', which returns a 'Group'-object by the column 'group_id'.
|
|
186
|
-
# :Group,
|
|
187
|
-
#
|
|
188
|
-
# #Defines the method 'type', which returns a 'Type'-object by the column 'type_id'.
|
|
189
|
-
# {class: :Type, col: :type_id, method: :type}
|
|
190
|
-
# ]
|
|
191
|
-
# end
|
|
192
|
-
def self.has_one(arr)
|
|
193
|
-
arr = [arr] if arr.is_a?(Symbol)
|
|
194
|
-
|
|
195
|
-
arr.each do |val|
|
|
196
|
-
methodname = nil
|
|
197
|
-
colname = nil
|
|
198
|
-
classname = nil
|
|
199
|
-
|
|
200
|
-
if val.is_a?(Symbol)
|
|
201
|
-
classname = val
|
|
202
|
-
methodname = val.to_s.downcase.to_sym
|
|
203
|
-
colname = "#{val.to_s.downcase}_id".to_sym
|
|
204
|
-
elsif val.is_a?(Array)
|
|
205
|
-
classname, colname, methodname = *val
|
|
206
|
-
elsif val.is_a?(Hash)
|
|
207
|
-
classname = nil
|
|
208
|
-
colname = nil
|
|
209
|
-
methodname = nil
|
|
210
|
-
|
|
211
|
-
val.each do |hkey, hval|
|
|
212
|
-
case hkey
|
|
213
|
-
when :class
|
|
214
|
-
classname = hval
|
|
215
|
-
when :col
|
|
216
|
-
colname = hval
|
|
217
|
-
when :method
|
|
218
|
-
methodname = hval
|
|
219
|
-
when :required
|
|
220
|
-
# Ignore
|
|
221
|
-
else
|
|
222
|
-
raise "Invalid key for class '#{name}' functionality 'has_many': '#{hkey}'."
|
|
223
|
-
end
|
|
224
|
-
end
|
|
225
|
-
|
|
226
|
-
if val[:required]
|
|
227
|
-
colname = "#{classname.to_s.downcase}_id".to_sym unless colname
|
|
228
|
-
required_data << {
|
|
229
|
-
col: colname,
|
|
230
|
-
class: classname
|
|
231
|
-
}
|
|
232
|
-
end
|
|
233
|
-
else
|
|
234
|
-
raise "Unknown argument-type: '#{arr.class.name}'."
|
|
235
|
-
end
|
|
236
|
-
|
|
237
|
-
methodname = StringCases.camel_to_snake(classname) unless methodname
|
|
238
|
-
colname = "#{classname.to_s.downcase}_id".to_sym unless colname
|
|
239
|
-
define_one_methods(classname, methodname, colname)
|
|
240
|
-
|
|
241
|
-
joined_tables(
|
|
242
|
-
classname => {
|
|
243
|
-
where: {
|
|
244
|
-
"id" => {type: :col, name: colname}
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
)
|
|
248
|
-
end
|
|
249
|
-
end
|
|
250
|
-
|
|
251
|
-
# This method initializes joins, sets methods to update translations and makes the translations automatically be deleted when the object is deleted.
|
|
252
|
-
#===Examples
|
|
253
|
-
# class Models::Article < Baza::Datarow
|
|
254
|
-
# #Defines methods such as: 'title', 'title=', 'content', 'content='. When used with Knjappserver these methods will change what they return and set based on the current language of the session.
|
|
255
|
-
# has_translation [:title, :content]
|
|
256
|
-
# end
|
|
257
|
-
#
|
|
258
|
-
# article = ob.get(:Article, 1)
|
|
259
|
-
# print "The title in the current language is: '#{article.title}'."
|
|
260
|
-
#
|
|
261
|
-
# article.title = 'Title in english if the language is english'
|
|
262
|
-
def self.has_translation(arr)
|
|
263
|
-
@translations = [] unless @translations
|
|
264
|
-
|
|
265
|
-
arr.each do |val|
|
|
266
|
-
@translations << val
|
|
267
|
-
|
|
268
|
-
val_dc = val.to_s.downcase
|
|
269
|
-
table_name = "Translation_#{val_dc}".to_sym
|
|
270
|
-
|
|
271
|
-
joined_tables(
|
|
272
|
-
table_name => {
|
|
273
|
-
where: {
|
|
274
|
-
"object_class" => name,
|
|
275
|
-
"object_id" => {type: :col, name: :id},
|
|
276
|
-
"key" => val.to_s,
|
|
277
|
-
"locale" => proc { |_d| _session[:locale] }
|
|
278
|
-
},
|
|
279
|
-
parent_table: :Translation,
|
|
280
|
-
datarow: Knj::Translations::Translation,
|
|
281
|
-
ob: @ob
|
|
282
|
-
}
|
|
283
|
-
)
|
|
284
|
-
|
|
285
|
-
define_translation_methods(val: val, val_dc: val_dc)
|
|
286
|
-
end
|
|
287
|
-
end
|
|
288
|
-
|
|
289
|
-
# This returns all translations for this datarow-class.
|
|
290
|
-
class << self
|
|
291
|
-
attr_reader :translations
|
|
292
|
-
end
|
|
293
|
-
|
|
294
|
-
# Returns data about joined tables for this class.
|
|
295
|
-
def self.joined_tables(hash)
|
|
296
|
-
@columns_joined_tables = {} unless @columns_joined_tables
|
|
297
|
-
@columns_joined_tables.merge!(hash)
|
|
298
|
-
end
|
|
299
|
-
|
|
300
|
-
# Returns various data for the objects-sql-helper. This can be used to view various informations about the columns and more.
|
|
301
|
-
def self.columns_sqlhelper_args
|
|
302
|
-
raise "No SQLHelper arguments has been spawned yet." unless @columns_sqlhelper_args
|
|
303
|
-
@columns_sqlhelper_args
|
|
304
|
-
end
|
|
305
|
-
|
|
306
|
-
# Called by Baza::ModelHandler to initialize the model and load column-data on-the-fly.
|
|
307
|
-
def self.load_columns(d)
|
|
308
|
-
@ob = d.ob
|
|
309
|
-
@db = d.db
|
|
310
|
-
|
|
311
|
-
@classname = name.split("::").last.to_sym unless @classname
|
|
312
|
-
@table = @classname unless @table
|
|
313
|
-
@mutex = Monitor.new unless @mutex
|
|
314
|
-
|
|
315
|
-
# Cache these to avoid method-lookups.
|
|
316
|
-
@sep_col = @db.sep_col
|
|
317
|
-
@sep_table = @db.sep_table
|
|
318
|
-
@table_str = "#{@sep_table}#{@db.escape_table(@table)}#{@sep_table}"
|
|
319
|
-
|
|
320
|
-
@mutex.synchronize do
|
|
321
|
-
inst_methods = instance_methods(false)
|
|
322
|
-
|
|
323
|
-
sqlhelper_args = {
|
|
324
|
-
db: @db,
|
|
325
|
-
table: @table,
|
|
326
|
-
cols_bools: [],
|
|
327
|
-
cols_date: [],
|
|
328
|
-
cols_dbrows: [],
|
|
329
|
-
cols_num: [],
|
|
330
|
-
cols_str: [],
|
|
331
|
-
cols: {}
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
sqlhelper_args[:table] = @table
|
|
335
|
-
|
|
336
|
-
@db.tables[table].columns do |col_obj|
|
|
337
|
-
col_name = col_obj.name.to_s
|
|
338
|
-
col_name_sym = col_name.to_sym
|
|
339
|
-
col_type = col_obj.type
|
|
340
|
-
col_type = :int if col_type == :bigint || col_type == :tinyint || col_type == :mediumint || col_type == :smallint
|
|
341
|
-
sqlhelper_args[:cols][col_name] = true
|
|
342
|
-
|
|
343
|
-
define_bool_methods(inst_methods, col_name)
|
|
344
|
-
|
|
345
|
-
if col_type == :enum && col_obj.maxlength == "'0','1'"
|
|
346
|
-
sqlhelper_args[:cols_bools] << col_name
|
|
347
|
-
elsif col_type == :int && col_name.slice(-3, 3) == "_id"
|
|
348
|
-
sqlhelper_args[:cols_dbrows] << col_name
|
|
349
|
-
elsif col_type == :int || col_type == :decimal
|
|
350
|
-
sqlhelper_args[:cols_num] << col_name
|
|
351
|
-
elsif col_type == :varchar || col_type == :text || col_type == :enum
|
|
352
|
-
sqlhelper_args[:cols_str] << col_name
|
|
353
|
-
elsif col_type == :date || col_type == :datetime
|
|
354
|
-
sqlhelper_args[:cols_date] << col_name
|
|
355
|
-
define_date_methods(inst_methods, col_name_sym)
|
|
356
|
-
end
|
|
357
|
-
|
|
358
|
-
if col_type == :int || col_type == :decimal
|
|
359
|
-
define_numeric_methods(inst_methods, col_name_sym)
|
|
360
|
-
end
|
|
361
|
-
|
|
362
|
-
if col_type == :int || col_type == :varchar
|
|
363
|
-
define_text_methods(inst_methods, col_name_sym)
|
|
364
|
-
end
|
|
365
|
-
|
|
366
|
-
define_time_methods(inst_methods, col_name_sym) if col_type == :time
|
|
367
|
-
end
|
|
368
|
-
|
|
369
|
-
if @columns_joined_tables
|
|
370
|
-
@columns_joined_tables.each do |table_name, table_data|
|
|
371
|
-
table_data[:where].each do |_key, val|
|
|
372
|
-
val[:table] = @table if val.is_a?(Hash) && !val.key?(:table) && val[:type].to_sym == :col
|
|
373
|
-
end
|
|
374
|
-
|
|
375
|
-
table_data[:datarow] = @ob.args[:module].const_get(table_name.to_sym) unless table_data.key?(:datarow)
|
|
376
|
-
end
|
|
377
|
-
|
|
378
|
-
sqlhelper_args[:joined_tables] = @columns_joined_tables
|
|
379
|
-
end
|
|
380
|
-
|
|
381
|
-
@columns_sqlhelper_args = sqlhelper_args
|
|
382
|
-
end
|
|
383
|
-
|
|
384
|
-
init_class(d) if self.respond_to?(:init_class)
|
|
385
|
-
end
|
|
386
|
-
|
|
387
|
-
# This method helps returning objects and supports various arguments. It should be called by Object#list.
|
|
388
|
-
#===Examples
|
|
389
|
-
# ob.list(:User, {"username_lower" => "john doe"}) do |user|
|
|
390
|
-
# print user.id
|
|
391
|
-
# end
|
|
392
|
-
#
|
|
393
|
-
# array = ob.list(:User, {"id" => 1})
|
|
394
|
-
# print array.length
|
|
395
|
-
def self.list(d, &block)
|
|
396
|
-
args = d.args
|
|
397
|
-
|
|
398
|
-
if args["count"]
|
|
399
|
-
count = true
|
|
400
|
-
args.delete("count")
|
|
401
|
-
sql = "SELECT COUNT(#{@table_str}.#{@sep_col}id#{@sep_col}) AS count"
|
|
402
|
-
elsif args["select_col_as_array"]
|
|
403
|
-
select_col_as_array = true
|
|
404
|
-
sql = "SELECT #{@table_str}.#{@sep_col}#{args["select_col_as_array"]}#{@sep_col} AS id"
|
|
405
|
-
args.delete("select_col_as_array")
|
|
406
|
-
else
|
|
407
|
-
sql = "SELECT #{@table_str}.*"
|
|
408
|
-
end
|
|
409
|
-
|
|
410
|
-
qargs = nil
|
|
411
|
-
ret = list_helper(d)
|
|
412
|
-
|
|
413
|
-
sql << " FROM #{@table_str}"
|
|
414
|
-
sql << ret[:sql_joins]
|
|
415
|
-
sql << " WHERE 1=1"
|
|
416
|
-
sql << ret[:sql_where]
|
|
417
|
-
|
|
418
|
-
args.each_key do |key|
|
|
419
|
-
case key
|
|
420
|
-
when "return_sql"
|
|
421
|
-
# Ignore
|
|
422
|
-
when :cloned_ubuf
|
|
423
|
-
qargs = {cloned_ubuf: true}
|
|
424
|
-
else
|
|
425
|
-
raise "Invalid key: '#{key}' for '#{name}'. Valid keys are: '#{@columns_sqlhelper_args[:cols].keys.sort}'. Date-keys: '#{@columns_sqlhelper_args[:cols_date]}'."
|
|
426
|
-
end
|
|
427
|
-
end
|
|
428
|
-
|
|
429
|
-
# The count will bug if there is a group-by-statement.
|
|
430
|
-
grp_shown = false
|
|
431
|
-
if !count && !ret[:sql_groupby]
|
|
432
|
-
sql << " GROUP BY #{@table_str}.#{@sep_col}id#{@sep_col}"
|
|
433
|
-
grp_shown = true
|
|
434
|
-
end
|
|
435
|
-
|
|
436
|
-
if ret[:sql_groupby]
|
|
437
|
-
if !grp_shown
|
|
438
|
-
sql << " GROUP BY"
|
|
439
|
-
else
|
|
440
|
-
sql << ", "
|
|
441
|
-
end
|
|
442
|
-
|
|
443
|
-
sql << ret[:sql_groupby]
|
|
444
|
-
end
|
|
445
|
-
|
|
446
|
-
sql << ret[:sql_order]
|
|
447
|
-
sql << ret[:sql_limit]
|
|
448
|
-
|
|
449
|
-
return sql.to_s if args["return_sql"]
|
|
450
|
-
|
|
451
|
-
if select_col_as_array
|
|
452
|
-
enum = Enumerator.new do |yielder|
|
|
453
|
-
@db.q(sql, qargs) do |data|
|
|
454
|
-
yielder << data[:id]
|
|
455
|
-
end
|
|
456
|
-
end
|
|
457
|
-
|
|
458
|
-
if block
|
|
459
|
-
enum.each(&block)
|
|
460
|
-
return nil
|
|
461
|
-
elsif @ob.args[:array_enum]
|
|
462
|
-
return ArrayEnumerator.new(enum)
|
|
463
|
-
else
|
|
464
|
-
return enum.to_a
|
|
465
|
-
end
|
|
466
|
-
elsif count
|
|
467
|
-
ret = @db.query(sql).fetch
|
|
468
|
-
return ret[:count].to_i if ret
|
|
469
|
-
return 0
|
|
470
|
-
end
|
|
471
|
-
|
|
472
|
-
@ob.list_bysql(classname, sql, qargs, &block)
|
|
473
|
-
end
|
|
474
|
-
|
|
475
|
-
# Helps call 'sqlhelper' on Baza::ModelHandler to generate SQL-strings.
|
|
476
|
-
def self.list_helper(d)
|
|
477
|
-
load_columns(d) unless @columns_sqlhelper_args
|
|
478
|
-
@columns_sqlhelper_args[:table] = @table
|
|
479
|
-
@ob.sqlhelper(d.args, @columns_sqlhelper_args)
|
|
480
|
-
end
|
|
481
|
-
|
|
482
|
-
# Returns the table-name that should be used for this datarow.
|
|
483
|
-
#===Examples
|
|
484
|
-
# db.query("SELECT * FROM `#{Models::User.table}` WHERE username = 'John Doe'") do |data|
|
|
485
|
-
# print data[:id]
|
|
486
|
-
# end
|
|
487
|
-
class << self
|
|
488
|
-
attr_reader :table
|
|
489
|
-
end
|
|
490
|
-
|
|
491
|
-
# This can be used to manually set the table-name. Useful when meta-programming classes that extends the datarow-class.
|
|
492
|
-
#===Examples
|
|
493
|
-
# Models::User.table = "prefix_User"
|
|
494
|
-
def self.table=(newtable)
|
|
495
|
-
@table = newtable
|
|
496
|
-
@columns_sqlhelper_args[:table] = @table if @columns_sqlhelper_args.is_a?(Hash)
|
|
497
|
-
end
|
|
498
|
-
|
|
499
|
-
# Returns the class-name but without having to call the class-table-method. To make code look shorter.
|
|
500
|
-
#===Examples
|
|
501
|
-
# user = ob.get_by(:User, {username: 'John Doe'})
|
|
502
|
-
# db.query("SELECT * FROM `#{user.table}` WHERE username = 'John Doe'") do |data|
|
|
503
|
-
# print data[:id]
|
|
504
|
-
# end
|
|
505
|
-
def table
|
|
506
|
-
self.class.table
|
|
507
|
-
end
|
|
508
|
-
|
|
509
|
-
# Initializes the object. This should be called from 'Baza::ModelHandler' and not manually.
|
|
510
|
-
#===Examples
|
|
511
|
-
# user = ob.get(:User, 3)
|
|
512
|
-
def initialize(data, args = nil)
|
|
513
|
-
if data.is_a?(Hash) && data.key?(:id)
|
|
514
|
-
@data = data
|
|
515
|
-
@id = @data[:id].to_i
|
|
516
|
-
elsif data
|
|
517
|
-
@id = data.to_i
|
|
518
|
-
|
|
519
|
-
classname = self.class.classname.to_sym
|
|
520
|
-
if self.class.ob.ids_cache_should.key?(classname)
|
|
521
|
-
# ID caching is enabled for this model - dont reload until first use.
|
|
522
|
-
raise Errno::ENOENT, "ID was not found in cache: '#{id}'." unless self.class.ob.ids_cache[classname].key?(@id)
|
|
523
|
-
@should_reload = true
|
|
524
|
-
else
|
|
525
|
-
# ID caching is not enabled - reload now to check if row exists. Else set 'should_reload'-variable if 'skip_reload' is set.
|
|
526
|
-
if !args || !args[:skip_reload]
|
|
527
|
-
reload
|
|
528
|
-
else
|
|
529
|
-
@should_reload = true
|
|
530
|
-
end
|
|
531
|
-
end
|
|
532
|
-
else
|
|
533
|
-
raise ArgumentError, "Could not figure out the data from '#{data.class.name}'."
|
|
534
|
-
end
|
|
535
|
-
|
|
536
|
-
return unless @id.to_i <= 0
|
|
537
|
-
|
|
538
|
-
raise "Invalid ID: '#{@id}' from '#{@data}'." if @data
|
|
539
|
-
raise "Invalid ID: '#{@id}'."
|
|
540
|
-
end
|
|
541
|
-
|
|
542
|
-
# Reloads the data from the database.
|
|
543
|
-
#===Examples
|
|
544
|
-
# old_username = user[:username]
|
|
545
|
-
# user.reload
|
|
546
|
-
# print "The username changed in the database!" if user[:username] != old_username
|
|
547
|
-
def reload
|
|
548
|
-
@data = self.class.db.single(self.class.table, id: @id)
|
|
549
|
-
raise Errno::ENOENT, "Could not find any data for the object with ID: '#{@id}' in the table '#{self.class.table}'." unless @data
|
|
550
|
-
@should_reload = false
|
|
551
|
-
end
|
|
552
|
-
|
|
553
|
-
# Tells the object that it should reloads its data because it has changed. It wont reload before it is required though, which may save you a couple of SQL-calls.
|
|
554
|
-
#===Examples
|
|
555
|
-
# obj = _ob.get(:User, 5)
|
|
556
|
-
# obj.should_reload
|
|
557
|
-
def should_reload
|
|
558
|
-
@should_reload = true
|
|
559
|
-
@data = nil
|
|
560
|
-
end
|
|
561
|
-
|
|
562
|
-
# Returns the data-hash that contains all the data from the database.
|
|
563
|
-
def data
|
|
564
|
-
reload if @should_reload
|
|
565
|
-
@data
|
|
566
|
-
end
|
|
567
|
-
|
|
568
|
-
# Writes/updates new data for the object.
|
|
569
|
-
#===Examples
|
|
570
|
-
# user.update(username: 'New username', date_changed: Time.now)
|
|
571
|
-
def update(newdata)
|
|
572
|
-
self.class.db.update(self.class.table, newdata, id: @id)
|
|
573
|
-
should_reload
|
|
574
|
-
self.class.ob.call("object" => self, "signal" => "update")
|
|
575
|
-
end
|
|
576
|
-
|
|
577
|
-
# Forcefully destroys the object. This is done after deleting it and should not be called manually.
|
|
578
|
-
def destroy
|
|
579
|
-
@id = nil
|
|
580
|
-
@data = nil
|
|
581
|
-
@should_reload = nil
|
|
582
|
-
end
|
|
583
|
-
|
|
584
|
-
# Returns true if that key exists on the object.
|
|
585
|
-
#===Examples
|
|
586
|
-
# print "Looks like the user has a name." if user.key?(:name)
|
|
587
|
-
def key?(key)
|
|
588
|
-
reload if @should_reload
|
|
589
|
-
@data.key?(key.to_sym)
|
|
590
|
-
end
|
|
591
|
-
alias_method :has_key?, :key?
|
|
592
|
-
|
|
593
|
-
# Returns true if the object has been deleted.
|
|
594
|
-
#===Examples
|
|
595
|
-
# print "That user is deleted." if user.deleted?
|
|
596
|
-
def deleted?
|
|
597
|
-
return true if !@data && !@id
|
|
598
|
-
false
|
|
599
|
-
end
|
|
600
|
-
|
|
601
|
-
# Returns true if the given object no longer exists in the database. Also destroys the data on the object and sets it to deleted-status, if it no longer exists.
|
|
602
|
-
#===Examples
|
|
603
|
-
# print "That user is deleted." if user.deleted_from_db?
|
|
604
|
-
def deleted_from_db?
|
|
605
|
-
# Try to avoid db-query if object is already deleted.
|
|
606
|
-
return true if self.deleted?
|
|
607
|
-
|
|
608
|
-
# Try to reload data. Destroy object and return true if the row is gone from the database.
|
|
609
|
-
begin
|
|
610
|
-
reload
|
|
611
|
-
return false
|
|
612
|
-
rescue Errno::ENOENT
|
|
613
|
-
destroy
|
|
614
|
-
return true
|
|
615
|
-
end
|
|
616
|
-
end
|
|
617
|
-
|
|
618
|
-
# Returns a specific data from the object by key.
|
|
619
|
-
# print "Username: #{user[:username]}\n"
|
|
620
|
-
# print "ID: #{user[:id]}\n"
|
|
621
|
-
# print "ID again: #{user.id}\n"
|
|
622
|
-
def [](key)
|
|
623
|
-
raise "Key was not a symbol: '#{key.class.name}'." unless key.is_a?(Symbol)
|
|
624
|
-
return @id if !@data && key == :id && @id
|
|
625
|
-
reload if @should_reload
|
|
626
|
-
raise "No data was loaded on the object? Maybe you are trying to call a deleted object? (#{self.class.classname}(#{@id}), #{@should_reload})" unless @data
|
|
627
|
-
return @data[key] if @data.key?(key)
|
|
628
|
-
raise "No such key: '#{key}' on '#{self.class.name}' (#{@data.keys.join(", ")}) (#{@should_reload})."
|
|
629
|
-
end
|
|
630
|
-
|
|
631
|
-
# Writes/updates a keys value on the object.
|
|
632
|
-
# user = ob.get_by(:User, {"username" => "John Doe"})
|
|
633
|
-
# user[:username] = 'New username'
|
|
634
|
-
def []=(key, value)
|
|
635
|
-
update(key.to_sym => value)
|
|
636
|
-
should_reload
|
|
637
|
-
end
|
|
638
|
-
|
|
639
|
-
# Returns the objects ID.
|
|
640
|
-
def id
|
|
641
|
-
raise Errno::ENOENT, "This object has been deleted." if deleted?
|
|
642
|
-
raise "No ID on object." unless @id
|
|
643
|
-
@id
|
|
644
|
-
end
|
|
645
|
-
|
|
646
|
-
# This enable Wref to not return the wrong object.
|
|
647
|
-
def __object_unique_id__
|
|
648
|
-
return 0 if self.deleted?
|
|
649
|
-
id
|
|
650
|
-
end
|
|
651
|
-
|
|
652
|
-
# Tries to figure out, and returns, the possible name or title for the object.
|
|
653
|
-
def name
|
|
654
|
-
reload if @should_reload
|
|
655
|
-
|
|
656
|
-
if @data.key?(:title)
|
|
657
|
-
return @data[:title]
|
|
658
|
-
elsif @data.key?(:name)
|
|
659
|
-
return @data[:name]
|
|
660
|
-
end
|
|
661
|
-
|
|
662
|
-
obj_methods = self.class.instance_methods(false)
|
|
663
|
-
[:name, :title].each do |method_name|
|
|
664
|
-
return method(method_name).call if obj_methods.index(method_name)
|
|
665
|
-
end
|
|
666
|
-
|
|
667
|
-
raise "Couldnt figure out the title/name of the object on class #{self.class.name}."
|
|
668
|
-
end
|
|
669
|
-
|
|
670
|
-
# Calls the name-method and returns a HTML-escaped value. Also "[no name]" if the name is empty.
|
|
671
|
-
def name_html
|
|
672
|
-
name_str = name.to_s
|
|
673
|
-
name_str = "[no name]" if name_str.empty?
|
|
674
|
-
name_str
|
|
675
|
-
end
|
|
676
|
-
|
|
677
|
-
alias_method :title, :name
|
|
678
|
-
|
|
679
|
-
# Loops through the data on the object.
|
|
680
|
-
#===Examples
|
|
681
|
-
# user = ob.get(:User, 1)
|
|
682
|
-
# user.each do |key, val|
|
|
683
|
-
# print "#{key}: #{val}\n" #=> username: John Doe
|
|
684
|
-
# end
|
|
685
|
-
def each(*args, &block)
|
|
686
|
-
reload if @should_reload
|
|
687
|
-
@data.each(*args, &block)
|
|
688
|
-
end
|
|
689
|
-
|
|
690
|
-
# Hash-compatible.
|
|
691
|
-
def to_hash
|
|
692
|
-
reload if @should_reload
|
|
693
|
-
@data.clone
|
|
694
|
-
end
|
|
695
|
-
|
|
696
|
-
# Returns a default-URL to show the object.
|
|
697
|
-
def url
|
|
698
|
-
cname = self.class.classname.to_s.downcase
|
|
699
|
-
"?show=#{cname}_show&#{cname}_id=#{id}"
|
|
700
|
-
end
|
|
701
|
-
|
|
702
|
-
# Returns the URL for editting the object.
|
|
703
|
-
def url_edit
|
|
704
|
-
cname = self.class.classname.to_s.downcase
|
|
705
|
-
"?show=#{cname}_edit&#{cname}_id=#{id}"
|
|
706
|
-
end
|
|
707
|
-
|
|
708
|
-
# Returns the HTML for making a link to the object.
|
|
709
|
-
def html(args = nil)
|
|
710
|
-
if args && args[:edit]
|
|
711
|
-
url = url_edit
|
|
712
|
-
else
|
|
713
|
-
url = self.url
|
|
714
|
-
end
|
|
715
|
-
|
|
716
|
-
"<a href=\"#{Knj::Web.ahref_parse(url)}\">#{name_html}</a>"
|
|
717
|
-
end
|
|
718
|
-
|
|
719
|
-
private
|
|
720
|
-
|
|
721
|
-
# Various methods to define methods based on the columns for the datarow.
|
|
722
|
-
def self.define_translation_methods(args)
|
|
723
|
-
define_method("#{args[:val_dc]}=") do |newtransval|
|
|
724
|
-
begin
|
|
725
|
-
_hb.trans_set(self, args[:val] => newtransval)
|
|
726
|
-
rescue NameError
|
|
727
|
-
_kas.trans_set(self, args[:val] => newtransval)
|
|
728
|
-
end
|
|
729
|
-
end
|
|
730
|
-
|
|
731
|
-
define_method("#{args[:val_dc]}") do
|
|
732
|
-
begin
|
|
733
|
-
return _hb.trans(self, args[:val])
|
|
734
|
-
rescue NameError
|
|
735
|
-
return _kas.trans(self, args[:val])
|
|
736
|
-
end
|
|
737
|
-
end
|
|
738
|
-
|
|
739
|
-
define_method("#{args[:val_dc]}_html") do
|
|
740
|
-
begin
|
|
741
|
-
str = _hb.trans(self, args[:val])
|
|
742
|
-
rescue NameError
|
|
743
|
-
str = _kas.trans(self, args[:val])
|
|
744
|
-
end
|
|
745
|
-
|
|
746
|
-
return "[no translation for #{args[:val]}]" if str.to_s.strip.empty?
|
|
747
|
-
|
|
748
|
-
return str
|
|
749
|
-
end
|
|
750
|
-
end
|
|
751
|
-
|
|
752
|
-
# Defines the boolean-methods based on enum-columns.
|
|
753
|
-
def self.define_bool_methods(inst_methods, col_name)
|
|
754
|
-
# Spawns a method on the class which returns true if the data is 1.
|
|
755
|
-
return if inst_methods.include?("#{col_name}?".to_sym)
|
|
756
|
-
|
|
757
|
-
define_method("#{col_name}?") do
|
|
758
|
-
return true if self[col_name.to_sym].to_s == "1"
|
|
759
|
-
return false
|
|
760
|
-
end
|
|
761
|
-
end
|
|
762
|
-
|
|
763
|
-
# Defines date- and time-columns based on datetime- and date-columns.
|
|
764
|
-
def self.define_date_methods(inst_methods, col_name)
|
|
765
|
-
return if inst_methods.include?("#{col_name}_str".to_sym)
|
|
766
|
-
|
|
767
|
-
define_method("#{col_name}_str") do |*method_args|
|
|
768
|
-
if Datet.is_nullstamp?(self[col_name])
|
|
769
|
-
return self.class.ob.events.call(:no_date, self.class.name)
|
|
770
|
-
end
|
|
771
|
-
|
|
772
|
-
return Datet.in(self[col_name]).out(*method_args)
|
|
773
|
-
end
|
|
774
|
-
|
|
775
|
-
return if inst_methods.include?(col_name)
|
|
776
|
-
|
|
777
|
-
define_method(col_name) do |*_method_args|
|
|
778
|
-
return false if Datet.is_nullstamp?(self[col_name])
|
|
779
|
-
return Datet.in(self[col_name])
|
|
780
|
-
end
|
|
781
|
-
end
|
|
782
|
-
|
|
783
|
-
# Define various methods based on integer-columns.
|
|
784
|
-
def self.define_numeric_methods(inst_methods, col_name)
|
|
785
|
-
return if inst_methods.include?("#{col_name}_format".to_sym)
|
|
786
|
-
|
|
787
|
-
define_method("#{col_name}_format") do |*method_args|
|
|
788
|
-
return Knj::Locales.number_out(self[col_name], *method_args)
|
|
789
|
-
end
|
|
790
|
-
end
|
|
791
|
-
|
|
792
|
-
# Define methods to look up objects directly.
|
|
793
|
-
#===Examples
|
|
794
|
-
# user = Models::User.by_username('John Doe')
|
|
795
|
-
# print user.id
|
|
796
|
-
def self.define_text_methods(inst_methods, col_name)
|
|
797
|
-
return if inst_methods.include?("by_#{col_name}".to_sym) && RUBY_VERSION.to_s.slice(0, 3) != "1.8"
|
|
798
|
-
|
|
799
|
-
define_singleton_method("by_#{col_name}") do |arg|
|
|
800
|
-
return self.class.ob.get_by(self.class.table, col_name.to_s => arg)
|
|
801
|
-
end
|
|
802
|
-
end
|
|
803
|
-
|
|
804
|
-
# Defines dbtime-methods based on time-columns.
|
|
805
|
-
def self.define_time_methods(inst_methods, col_name)
|
|
806
|
-
return if inst_methods.include?("#{col_name}_dbt".to_sym)
|
|
807
|
-
|
|
808
|
-
define_method("#{col_name}_dbt") do
|
|
809
|
-
return Baza::Db::Dbtime.new(self[col_name.to_sym])
|
|
810
|
-
end
|
|
811
|
-
end
|
|
812
|
-
|
|
813
|
-
# Memory friendly helper method that defines methods for 'has_many'.
|
|
814
|
-
def self.define_many_methods(classname, methodname, colname, where_args)
|
|
815
|
-
define_method(methodname) do |*args, &block|
|
|
816
|
-
if args && args[0]
|
|
817
|
-
list_args = args[0]
|
|
818
|
-
else
|
|
819
|
-
list_args = {}
|
|
820
|
-
end
|
|
821
|
-
|
|
822
|
-
list_args.merge!(where_args) if where_args
|
|
823
|
-
list_args[colname.to_s] = id
|
|
824
|
-
|
|
825
|
-
self.class.ob.list(classname, list_args, &block)
|
|
826
|
-
end
|
|
827
|
-
|
|
828
|
-
define_method("#{methodname}_count".to_sym) do |*args|
|
|
829
|
-
list_args = args[0] if args && args[0]
|
|
830
|
-
list_args = {} unless list_args
|
|
831
|
-
list_args[colname.to_s] = id
|
|
832
|
-
list_args["count"] = true
|
|
833
|
-
|
|
834
|
-
self.class.ob.list(classname, list_args)
|
|
835
|
-
end
|
|
836
|
-
|
|
837
|
-
define_method("#{methodname}_last".to_sym) do |args|
|
|
838
|
-
args = {} unless args
|
|
839
|
-
self.class.ob.list(classname, {"orderby" => [["id", "desc"]], "limit" => 1}.merge(args))
|
|
840
|
-
end
|
|
841
|
-
end
|
|
842
|
-
|
|
843
|
-
# Memory friendly helper method that defines methods for 'has_one'.
|
|
844
|
-
def self.define_one_methods(classname, methodname, colname)
|
|
845
|
-
define_method(methodname) do
|
|
846
|
-
self.class.ob.get_try(self, colname, classname)
|
|
847
|
-
end
|
|
848
|
-
|
|
849
|
-
methodname_html = "#{methodname}_html".to_sym
|
|
850
|
-
define_method(methodname_html) do |*args|
|
|
851
|
-
obj = __send__(methodname)
|
|
852
|
-
return self.class.ob.events.call(:no_html, classname) unless obj
|
|
853
|
-
|
|
854
|
-
raise "Class '#{classname}' does not have a 'html'-method." unless obj.respond_to?(:html)
|
|
855
|
-
obj.html(*args)
|
|
856
|
-
end
|
|
857
|
-
|
|
858
|
-
methodname_name = "#{methodname}_name".to_sym
|
|
859
|
-
define_method(methodname_name) do |*args|
|
|
860
|
-
obj = __send__(methodname)
|
|
861
|
-
return self.class.ob.events.call(:no_name, classname) unless obj
|
|
862
|
-
obj.name(*args)
|
|
863
|
-
end
|
|
864
|
-
end
|
|
865
|
-
|
|
866
|
-
# Returns a hash reflection the current ActiveRecord model and its current values (not like .attributes which reflects the old values).
|
|
867
|
-
def self.activerecord_to_hash(model)
|
|
868
|
-
attrs = {}
|
|
869
|
-
model.attribute_names.each do |name|
|
|
870
|
-
attrs[name] = model.__send__(name)
|
|
871
|
-
end
|
|
872
|
-
|
|
873
|
-
attrs
|
|
874
|
-
end
|
|
875
|
-
end
|