activerecord-jdbc-adapter 0.6 → 0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +46 -27
- data/Manifest.txt +7 -4
- data/Rakefile +6 -5
- data/lib/active_record/connection_adapters/jdbc_adapter.rb +93 -108
- data/lib/jdbc_adapter/jdbc_adapter_internal.jar +0 -0
- data/lib/jdbc_adapter/jdbc_derby.rb +1 -0
- data/lib/jdbc_adapter/jdbc_hsqldb.rb +1 -1
- data/lib/jdbc_adapter/jdbc_mysql.rb +55 -13
- data/lib/jdbc_adapter/version.rb +1 -1
- data/src/java/jdbc_adapter/JdbcAdapterInternalService.java +1113 -0
- data/src/java/jdbc_adapter/JdbcConnectionFactory.java +36 -0
- data/src/java/{JDBCDerbySpec.java → jdbc_adapter/JdbcDerbySpec.java} +95 -91
- data/src/java/{JDBCMySQLSpec.java → jdbc_adapter/JdbcMySQLSpec.java} +24 -27
- data/src/java/jdbc_adapter/SQLBlock.java +18 -0
- data/test/has_many_through.rb +72 -0
- data/test/jdbc_common.rb +1 -0
- data/test/mysql_simple_test.rb +4 -0
- data/test/simple.rb +36 -1
- metadata +9 -6
- data/lib/jdbc_adapter_internal.jar +0 -0
- data/src/java/JdbcAdapterInternalService.java +0 -953
@@ -0,0 +1,36 @@
|
|
1
|
+
/***** BEGIN LICENSE BLOCK *****
|
2
|
+
* Copyright (c) 2006-2007 Nick Sieger <nick@nicksieger.com>
|
3
|
+
* Copyright (c) 2006-2007 Ola Bini <ola.bini@gmail.com>
|
4
|
+
*
|
5
|
+
* Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
* a copy of this software and associated documentation files (the
|
7
|
+
* "Software"), to deal in the Software without restriction, including
|
8
|
+
* without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
* distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
* permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
* the following conditions:
|
12
|
+
*
|
13
|
+
* The above copyright notice and this permission notice shall be
|
14
|
+
* included in all copies or substantial portions of the Software.
|
15
|
+
*
|
16
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
***** END LICENSE BLOCK *****/
|
24
|
+
|
25
|
+
package jdbc_adapter;
|
26
|
+
|
27
|
+
import java.sql.Connection;
|
28
|
+
|
29
|
+
/**
|
30
|
+
* Interface to be implemented in Ruby for retrieving a new connection
|
31
|
+
*
|
32
|
+
* @author nicksieger
|
33
|
+
*/
|
34
|
+
public interface JdbcConnectionFactory {
|
35
|
+
Connection newConnection();
|
36
|
+
}
|
@@ -1,31 +1,29 @@
|
|
1
1
|
/***** BEGIN LICENSE BLOCK *****
|
2
|
-
*
|
3
|
-
*
|
4
|
-
* The contents of this file are subject to the Common Public
|
5
|
-
* License Version 1.0 (the "License"); you may not use this file
|
6
|
-
* except in compliance with the License. You may obtain a copy of
|
7
|
-
* the License at http://www.eclipse.org/legal/cpl-v10.html
|
8
|
-
*
|
9
|
-
* Software distributed under the License is distributed on an "AS
|
10
|
-
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
11
|
-
* implied. See the License for the specific language governing
|
12
|
-
* rights and limitations under the License.
|
13
|
-
*
|
14
|
-
* Copyright (C) 2007 Ola Bini <ola.bini@gmail.com>
|
2
|
+
* Copyright (c) 2006-2007 Nick Sieger <nick@nicksieger.com>
|
3
|
+
* Copyright (c) 2006-2007 Ola Bini <ola.bini@gmail.com>
|
15
4
|
*
|
16
|
-
*
|
17
|
-
*
|
18
|
-
*
|
19
|
-
*
|
20
|
-
*
|
21
|
-
*
|
22
|
-
*
|
23
|
-
*
|
24
|
-
*
|
25
|
-
*
|
26
|
-
*
|
5
|
+
* Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
* a copy of this software and associated documentation files (the
|
7
|
+
* "Software"), to deal in the Software without restriction, including
|
8
|
+
* without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
* distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
* permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
* the following conditions:
|
12
|
+
*
|
13
|
+
* The above copyright notice and this permission notice shall be
|
14
|
+
* included in all copies or substantial portions of the Software.
|
15
|
+
*
|
16
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
27
23
|
***** END LICENSE BLOCK *****/
|
28
24
|
|
25
|
+
package jdbc_adapter;
|
26
|
+
|
29
27
|
import org.jruby.Ruby;
|
30
28
|
import org.jruby.RubyModule;
|
31
29
|
import org.jruby.RubyString;
|
@@ -40,17 +38,18 @@ import org.jruby.RubyNumeric;
|
|
40
38
|
import org.jruby.runtime.Arity;
|
41
39
|
import org.jruby.runtime.CallbackFactory;
|
42
40
|
import org.jruby.runtime.MethodIndex;
|
43
|
-
import org.jruby.runtime.ThreadContext;
|
44
41
|
import org.jruby.runtime.builtin.IRubyObject;
|
45
42
|
|
46
43
|
import org.jruby.util.ByteList;
|
47
44
|
|
48
45
|
import java.sql.SQLException;
|
46
|
+
import org.jruby.RubyObjectAdapter;
|
49
47
|
|
50
|
-
public class
|
51
|
-
|
48
|
+
public class JdbcDerbySpec {
|
49
|
+
private static RubyObjectAdapter rubyApi;
|
50
|
+
public static void load(Ruby runtime, RubyModule jdbcSpec, RubyObjectAdapter adapter) {
|
52
51
|
RubyModule derby = jdbcSpec.defineModuleUnder("Derby");
|
53
|
-
CallbackFactory cf = runtime.callbackFactory(
|
52
|
+
CallbackFactory cf = runtime.callbackFactory(JdbcDerbySpec.class);
|
54
53
|
derby.defineFastMethod("quote_string",cf.getFastSingletonMethod("quote_string",IRubyObject.class));
|
55
54
|
derby.defineFastMethod("quote",cf.getFastOptSingletonMethod("quote"));
|
56
55
|
derby.defineFastMethod("_execute",cf.getFastOptSingletonMethod("_execute"));
|
@@ -59,6 +58,7 @@ public class JDBCDerbySpec {
|
|
59
58
|
derby.defineFastMethod("select_one",cf.getFastOptSingletonMethod("select_one"));
|
60
59
|
RubyModule col = derby.defineModuleUnder("Column");
|
61
60
|
col.defineFastMethod("type_cast",cf.getFastSingletonMethod("type_cast", IRubyObject.class));
|
61
|
+
rubyApi = adapter;
|
62
62
|
}
|
63
63
|
|
64
64
|
/*
|
@@ -67,11 +67,11 @@ public class JDBCDerbySpec {
|
|
67
67
|
public static IRubyObject type_cast(IRubyObject recv, IRubyObject value) {
|
68
68
|
Ruby runtime = recv.getRuntime();
|
69
69
|
|
70
|
-
if(value.isNil() || ((value instanceof RubyString) && value.toString().trim().equalsIgnoreCase("null"))) {
|
70
|
+
if (value.isNil() || ((value instanceof RubyString) && value.toString().trim().equalsIgnoreCase("null"))) {
|
71
71
|
return runtime.getNil();
|
72
72
|
}
|
73
73
|
|
74
|
-
String type =
|
74
|
+
String type = rubyApi.getInstanceVariable(recv,"@type").toString();
|
75
75
|
|
76
76
|
switch(type.charAt(0)) {
|
77
77
|
case 's': //string
|
@@ -80,30 +80,30 @@ public class JDBCDerbySpec {
|
|
80
80
|
if(type.equals("text")) {
|
81
81
|
return value;
|
82
82
|
} else {
|
83
|
-
return
|
83
|
+
return rubyApi.callMethod(recv, "cast_to_time", value);
|
84
84
|
}
|
85
85
|
case 'i': //integer
|
86
86
|
case 'p': //primary key
|
87
|
-
if(value.respondsTo("to_i")) {
|
88
|
-
return
|
87
|
+
if (value.respondsTo("to_i")) {
|
88
|
+
return rubyApi.callMethod(value, "to_i");
|
89
89
|
} else {
|
90
|
-
return runtime.newFixnum(
|
90
|
+
return runtime.newFixnum(value.isTrue() ? 1 : 0 );
|
91
91
|
}
|
92
92
|
case 'd': //decimal, datetime, date
|
93
93
|
if(type.equals("datetime")) {
|
94
|
-
return
|
94
|
+
return rubyApi.callMethod(recv, "cast_to_date_or_time", value);
|
95
95
|
} else if(type.equals("date")) {
|
96
|
-
return
|
96
|
+
return rubyApi.callMethod(recv.getMetaClass(), "string_to_date", value);
|
97
97
|
} else {
|
98
|
-
return
|
98
|
+
return rubyApi.callMethod(recv.getMetaClass(), "value_to_decimal", value);
|
99
99
|
}
|
100
100
|
case 'f': //float
|
101
|
-
return
|
101
|
+
return rubyApi.callMethod(value,"to_f");
|
102
102
|
case 'b': //binary, boolean
|
103
|
-
if(type.equals("binary")) {
|
104
|
-
return
|
103
|
+
if (type.equals("binary")) {
|
104
|
+
return rubyApi.callMethod(recv, "value_to_binary", value);
|
105
105
|
} else {
|
106
|
-
return
|
106
|
+
return rubyApi.callMethod(recv.getMetaClass(), "value_to_boolean", value);
|
107
107
|
}
|
108
108
|
}
|
109
109
|
return value;
|
@@ -113,26 +113,26 @@ public class JDBCDerbySpec {
|
|
113
113
|
Ruby runtime = recv.getRuntime();
|
114
114
|
Arity.checkArgumentCount(runtime, args, 1, 2);
|
115
115
|
IRubyObject value = args[0];
|
116
|
-
if(args.length > 1) {
|
116
|
+
if (args.length > 1) {
|
117
117
|
IRubyObject col = args[1];
|
118
|
-
IRubyObject type =
|
119
|
-
if(value instanceof RubyString) {
|
120
|
-
if(type == runtime.newSymbol("string")) {
|
118
|
+
IRubyObject type = rubyApi.callMethod(col, "type");
|
119
|
+
if (value instanceof RubyString) {
|
120
|
+
if (type == runtime.newSymbol("string")) {
|
121
121
|
return quote_string_with_surround(runtime, "'", (RubyString)value, "'");
|
122
|
-
} else if(type == runtime.newSymbol("text")) {
|
122
|
+
} else if (type == runtime.newSymbol("text")) {
|
123
123
|
return quote_string_with_surround(runtime, "CAST('", (RubyString)value, "' AS CLOB)");
|
124
|
-
} else if(type == runtime.newSymbol("binary")) {
|
124
|
+
} else if (type == runtime.newSymbol("binary")) {
|
125
125
|
return hexquote_string_with_surround(runtime, "CAST('", (RubyString)value, "' AS BLOB)");
|
126
126
|
} else {
|
127
127
|
// column type :integer or other numeric or date version
|
128
|
-
if(only_digits((RubyString)value)) {
|
128
|
+
if (only_digits((RubyString)value)) {
|
129
129
|
return value;
|
130
130
|
} else {
|
131
131
|
return super_quote(recv, runtime, value, col);
|
132
132
|
}
|
133
133
|
}
|
134
|
-
} else if((value instanceof RubyFloat) || (value instanceof RubyFixnum) || (value instanceof RubyBignum)) {
|
135
|
-
if(type == runtime.newSymbol("string")) {
|
134
|
+
} else if ((value instanceof RubyFloat) || (value instanceof RubyFixnum) || (value instanceof RubyBignum)) {
|
135
|
+
if (type == runtime.newSymbol("string")) {
|
136
136
|
return quote_string_with_surround(runtime, "'", RubyString.objAsString(value), "'");
|
137
137
|
}
|
138
138
|
}
|
@@ -143,39 +143,40 @@ public class JDBCDerbySpec {
|
|
143
143
|
private final static ByteList NULL = new ByteList("NULL".getBytes());
|
144
144
|
|
145
145
|
public static IRubyObject super_quote(IRubyObject recv, Ruby runtime, IRubyObject value, IRubyObject col) {
|
146
|
-
if(value.respondsTo("quoted_id")) {
|
147
|
-
return
|
146
|
+
if (value.respondsTo("quoted_id")) {
|
147
|
+
return rubyApi.callMethod(value, "quoted_id");
|
148
148
|
}
|
149
149
|
|
150
|
-
IRubyObject type = (col.isNil()) ? col :
|
151
|
-
|
152
|
-
|
150
|
+
IRubyObject type = (col.isNil()) ? col : rubyApi.callMethod(col, "type");
|
151
|
+
RubyModule multibyteChars = (RubyModule)
|
152
|
+
((RubyModule) ((RubyModule) runtime.getModule("ActiveSupport")).getConstant("Multibyte")).getConstantAt("Chars");
|
153
|
+
if (value instanceof RubyString || rubyApi.isKindOf(value, multibyteChars)) {
|
153
154
|
RubyString svalue = RubyString.objAsString(value);
|
154
|
-
if(type == runtime.newSymbol("binary") && col.getType().respondsTo("string_to_binary")) {
|
155
|
-
return quote_string_with_surround(runtime, "'", (RubyString)(
|
156
|
-
} else if(type == runtime.newSymbol("integer") || type == runtime.newSymbol("float")) {
|
155
|
+
if (type == runtime.newSymbol("binary") && col.getType().respondsTo("string_to_binary")) {
|
156
|
+
return quote_string_with_surround(runtime, "'", (RubyString)(rubyApi.callMethod(col.getType(), "string_to_binary", svalue)), "'");
|
157
|
+
} else if (type == runtime.newSymbol("integer") || type == runtime.newSymbol("float")) {
|
157
158
|
return RubyString.objAsString(((type == runtime.newSymbol("integer")) ?
|
158
|
-
|
159
|
-
|
159
|
+
rubyApi.callMethod(svalue, "to_i") :
|
160
|
+
rubyApi.callMethod(svalue, "to_f")));
|
160
161
|
} else {
|
161
162
|
return quote_string_with_surround(runtime, "'", svalue, "'");
|
162
163
|
}
|
163
|
-
} else if(value.isNil()) {
|
164
|
+
} else if (value.isNil()) {
|
164
165
|
return runtime.newStringShared(NULL);
|
165
|
-
} else if(value instanceof RubyBoolean) {
|
166
|
+
} else if (value instanceof RubyBoolean) {
|
166
167
|
return (value.isTrue() ?
|
167
|
-
(type == runtime.newSymbol(":integer")) ? runtime.newString("1") :
|
168
|
-
(type == runtime.newSymbol(":integer")) ? runtime.newString("0") :
|
168
|
+
(type == runtime.newSymbol(":integer")) ? runtime.newString("1") : rubyApi.callMethod(recv, "quoted_true") :
|
169
|
+
(type == runtime.newSymbol(":integer")) ? runtime.newString("0") : rubyApi.callMethod(recv, "quoted_false"));
|
169
170
|
} else if((value instanceof RubyFloat) || (value instanceof RubyFixnum) || (value instanceof RubyBignum)) {
|
170
171
|
return RubyString.objAsString(value);
|
171
172
|
} else if(value instanceof RubyBigDecimal) {
|
172
|
-
return
|
173
|
-
} else if(
|
173
|
+
return rubyApi.callMethod(value, "to_s", runtime.newString("F"));
|
174
|
+
} else if (rubyApi.isKindOf(value, runtime.getModule("Date"))) {
|
174
175
|
return quote_string_with_surround(runtime, "'", RubyString.objAsString(value), "'");
|
175
|
-
} else if(
|
176
|
-
return quote_string_with_surround(runtime, "'", (RubyString)(
|
176
|
+
} else if (rubyApi.isKindOf(value, runtime.getModule("Time")) || rubyApi.isKindOf(value, runtime.getModule("DateTime"))) {
|
177
|
+
return quote_string_with_surround(runtime, "'", (RubyString)(rubyApi.callMethod(recv, "quoted_date", value)), "'");
|
177
178
|
} else {
|
178
|
-
return quote_string_with_surround(runtime, "'", (RubyString)(
|
179
|
+
return quote_string_with_surround(runtime, "'", (RubyString)(rubyApi.callMethod(value, "to_yaml")), "'");
|
179
180
|
}
|
180
181
|
}
|
181
182
|
|
@@ -259,55 +260,58 @@ public class JDBCDerbySpec {
|
|
259
260
|
}
|
260
261
|
|
261
262
|
public static IRubyObject select_all(IRubyObject recv, IRubyObject[] args) {
|
262
|
-
return
|
263
|
+
return rubyApi.callMethod(recv, "execute", args);
|
263
264
|
}
|
264
265
|
|
265
266
|
public static IRubyObject select_one(IRubyObject recv, IRubyObject[] args) {
|
266
|
-
IRubyObject limit =
|
267
|
-
if(limit == null || limit.isNil()) {
|
268
|
-
|
267
|
+
IRubyObject limit = rubyApi.getInstanceVariable(recv, "@limit");
|
268
|
+
if (limit == null || limit.isNil()) {
|
269
|
+
rubyApi.setInstanceVariable(recv, "@limit", recv.getRuntime().newFixnum(1));
|
269
270
|
}
|
270
271
|
try {
|
271
|
-
|
272
|
+
IRubyObject result = rubyApi.callMethod(recv, "execute", args);
|
273
|
+
return rubyApi.callMethod(result, "first");
|
272
274
|
} finally {
|
273
|
-
|
275
|
+
rubyApi.setInstanceVariable(recv, "@limit", recv.getRuntime().getNil());
|
274
276
|
}
|
275
277
|
}
|
276
278
|
|
277
279
|
public static IRubyObject add_limit_offset(IRubyObject recv, IRubyObject sql, IRubyObject options) {
|
278
|
-
|
279
|
-
|
280
|
+
IRubyObject limit = rubyApi.callMethod(options, "[]", recv.getRuntime().newSymbol("limit"));
|
281
|
+
rubyApi.setInstanceVariable(recv, "@limit",limit);
|
282
|
+
IRubyObject offset = rubyApi.callMethod(options, "[]", recv.getRuntime().newSymbol("offset"));
|
283
|
+
return rubyApi.setInstanceVariable(recv, "@offset",offset);
|
280
284
|
}
|
281
285
|
|
282
286
|
public static IRubyObject _execute(IRubyObject recv, IRubyObject[] args) throws SQLException, java.io.IOException {
|
283
287
|
Ruby runtime = recv.getRuntime();
|
284
288
|
try {
|
285
|
-
IRubyObject conn =
|
289
|
+
IRubyObject conn = rubyApi.getInstanceVariable(recv, "@connection");
|
286
290
|
String sql = args[0].toString().trim().toLowerCase();
|
287
|
-
if(sql.charAt(0) == '(') {
|
291
|
+
if (sql.charAt(0) == '(') {
|
288
292
|
sql = sql.substring(1).trim();
|
289
293
|
}
|
290
|
-
if(sql.startsWith("insert")) {
|
294
|
+
if (sql.startsWith("insert")) {
|
291
295
|
return JdbcAdapterInternalService.execute_insert(conn, args[0]);
|
292
|
-
} else if(sql.startsWith("select") || sql.startsWith("show")) {
|
293
|
-
IRubyObject offset =
|
296
|
+
} else if (sql.startsWith("select") || sql.startsWith("show")) {
|
297
|
+
IRubyObject offset = rubyApi.getInstanceVariable(recv, "@offset");
|
294
298
|
if(offset == null || offset.isNil()) {
|
295
299
|
offset = RubyFixnum.zero(runtime);
|
296
300
|
}
|
297
|
-
IRubyObject limit =
|
301
|
+
IRubyObject limit = rubyApi.getInstanceVariable(recv, "@limit");
|
298
302
|
IRubyObject range;
|
299
303
|
IRubyObject max;
|
300
|
-
if(limit == null || limit.isNil() || RubyNumeric.fix2int(limit) == -1) {
|
304
|
+
if (limit == null || limit.isNil() || RubyNumeric.fix2int(limit) == -1) {
|
301
305
|
range = RubyRange.newRange(runtime, offset, runtime.newFixnum(-1), false);
|
302
306
|
max = RubyFixnum.zero(runtime);
|
303
307
|
} else {
|
304
|
-
IRubyObject v1 =
|
308
|
+
IRubyObject v1 = rubyApi.callMethod(offset, "+", limit);
|
305
309
|
range = RubyRange.newRange(runtime, offset, v1, true);
|
306
|
-
max =
|
310
|
+
max = rubyApi.callMethod(v1, "+", RubyFixnum.one(runtime));
|
307
311
|
}
|
308
|
-
IRubyObject
|
309
|
-
|
310
|
-
if(ret.isNil()) {
|
312
|
+
IRubyObject result = JdbcAdapterInternalService.execute_query(conn, new IRubyObject[]{args[0], max});
|
313
|
+
IRubyObject ret = rubyApi.callMethod(result, "[]", range);
|
314
|
+
if (ret.isNil()) {
|
311
315
|
return runtime.newArray();
|
312
316
|
} else {
|
313
317
|
return ret;
|
@@ -316,8 +320,8 @@ public class JDBCDerbySpec {
|
|
316
320
|
return JdbcAdapterInternalService.execute_update(conn, args[0]);
|
317
321
|
}
|
318
322
|
} finally {
|
319
|
-
|
320
|
-
|
323
|
+
rubyApi.setInstanceVariable(recv, "@limit", runtime.getNil());
|
324
|
+
rubyApi.setInstanceVariable(recv, "@offset", runtime.getNil());
|
321
325
|
}
|
322
326
|
}
|
323
327
|
}
|
@@ -1,45 +1,42 @@
|
|
1
1
|
/***** BEGIN LICENSE BLOCK *****
|
2
|
-
*
|
3
|
-
*
|
4
|
-
* The contents of this file are subject to the Common Public
|
5
|
-
* License Version 1.0 (the "License"); you may not use this file
|
6
|
-
* except in compliance with the License. You may obtain a copy of
|
7
|
-
* the License at http://www.eclipse.org/legal/cpl-v10.html
|
8
|
-
*
|
9
|
-
* Software distributed under the License is distributed on an "AS
|
10
|
-
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
11
|
-
* implied. See the License for the specific language governing
|
12
|
-
* rights and limitations under the License.
|
13
|
-
*
|
14
|
-
* Copyright (C) 2007 Ola Bini <ola.bini@gmail.com>
|
2
|
+
* Copyright (c) 2006-2007 Nick Sieger <nick@nicksieger.com>
|
3
|
+
* Copyright (c) 2006-2007 Ola Bini <ola.bini@gmail.com>
|
15
4
|
*
|
16
|
-
*
|
17
|
-
*
|
18
|
-
*
|
19
|
-
*
|
20
|
-
*
|
21
|
-
*
|
22
|
-
*
|
23
|
-
*
|
24
|
-
*
|
25
|
-
*
|
26
|
-
*
|
5
|
+
* Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
* a copy of this software and associated documentation files (the
|
7
|
+
* "Software"), to deal in the Software without restriction, including
|
8
|
+
* without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
* distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
* permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
* the following conditions:
|
12
|
+
*
|
13
|
+
* The above copyright notice and this permission notice shall be
|
14
|
+
* included in all copies or substantial portions of the Software.
|
15
|
+
*
|
16
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
27
23
|
***** END LICENSE BLOCK *****/
|
28
24
|
|
25
|
+
package jdbc_adapter;
|
26
|
+
|
29
27
|
import org.jruby.Ruby;
|
30
28
|
import org.jruby.RubyModule;
|
31
29
|
import org.jruby.RubyString;
|
32
30
|
|
33
31
|
import org.jruby.runtime.CallbackFactory;
|
34
|
-
import org.jruby.runtime.ThreadContext;
|
35
32
|
import org.jruby.runtime.builtin.IRubyObject;
|
36
33
|
|
37
34
|
import org.jruby.util.ByteList;
|
38
35
|
|
39
|
-
public class
|
36
|
+
public class JdbcMySQLSpec {
|
40
37
|
public static void load(Ruby runtime, RubyModule jdbcSpec) {
|
41
38
|
RubyModule mysql = jdbcSpec.defineModuleUnder("MySQL");
|
42
|
-
CallbackFactory cf = runtime.callbackFactory(
|
39
|
+
CallbackFactory cf = runtime.callbackFactory(JdbcMySQLSpec.class);
|
43
40
|
mysql.defineFastMethod("quote_string",cf.getFastSingletonMethod("quote_string",IRubyObject.class));
|
44
41
|
}
|
45
42
|
|
@@ -0,0 +1,18 @@
|
|
1
|
+
/*
|
2
|
+
* To change this template, choose Tools | Templates
|
3
|
+
* and open the template in the editor.
|
4
|
+
*/
|
5
|
+
|
6
|
+
package jdbc_adapter;
|
7
|
+
|
8
|
+
import java.sql.Connection;
|
9
|
+
import java.sql.SQLException;
|
10
|
+
import org.jruby.runtime.builtin.IRubyObject;
|
11
|
+
|
12
|
+
/**
|
13
|
+
*
|
14
|
+
* @author nicksieger
|
15
|
+
*/
|
16
|
+
public interface SQLBlock {
|
17
|
+
IRubyObject call(Connection c) throws SQLException;
|
18
|
+
}
|
@@ -0,0 +1,72 @@
|
|
1
|
+
class CreateRbac < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :role_assignments do |t|
|
4
|
+
t.column :role_id, :integer
|
5
|
+
t.column :user_id, :integer
|
6
|
+
end
|
7
|
+
|
8
|
+
create_table :roles do |t|
|
9
|
+
t.column :name, :string
|
10
|
+
t.column :description, :string
|
11
|
+
end
|
12
|
+
|
13
|
+
create_table :permission_groups do |t|
|
14
|
+
t.column :right_id, :integer
|
15
|
+
t.column :role_id, :integer
|
16
|
+
end
|
17
|
+
|
18
|
+
create_table :rights do |t|
|
19
|
+
t.column :name, :string
|
20
|
+
t.column :controller_name, :string
|
21
|
+
t.column :actions, :string
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.down
|
26
|
+
drop_table :role_assignments
|
27
|
+
drop_table :roles
|
28
|
+
drop_table :permission_groups
|
29
|
+
drop_table :rights
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class Right < ActiveRecord::Base
|
34
|
+
has_many :permission_groups, :dependent => :destroy
|
35
|
+
has_many :roles, :through => :permission_groups
|
36
|
+
end
|
37
|
+
|
38
|
+
class Role < ActiveRecord::Base
|
39
|
+
has_many :permission_groups, :dependent => :destroy
|
40
|
+
has_many :rights, :through => :permission_groups
|
41
|
+
has_many :role_assignments, :dependent => :destroy
|
42
|
+
end
|
43
|
+
|
44
|
+
class PermissionGroup < ActiveRecord::Base
|
45
|
+
belongs_to :right
|
46
|
+
belongs_to :role
|
47
|
+
end
|
48
|
+
|
49
|
+
class RoleAssignment < ActiveRecord::Base
|
50
|
+
belongs_to :user
|
51
|
+
belongs_to :role
|
52
|
+
end
|
53
|
+
|
54
|
+
module HasManyThroughMethods
|
55
|
+
def setup
|
56
|
+
CreateRbac.up
|
57
|
+
end
|
58
|
+
|
59
|
+
def teardown
|
60
|
+
CreateRbac.down
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_has_many_through
|
64
|
+
role_rights = Right.create( {:name => "Administrator - Full Access To Roles", :actions => "*", :controller_name => "Admin::RolesController"} )
|
65
|
+
right_rights = Right.create( {:name => "Administrator - Full Access To Rights", :actions => "*", :controller_name => "Admin::RightsController"} )
|
66
|
+
|
67
|
+
admin_role = Role.create( {:name => "Administrator", :description => "System defined super user - access to right and role management."} )
|
68
|
+
admin_role.rights << role_rights
|
69
|
+
admin_role.rights << right_rights
|
70
|
+
admin_role.save
|
71
|
+
end
|
72
|
+
end
|