ghazel-slim-attributes 0.6.3.1 → 0.7.6.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README +26 -9
- data/Rakefile +8 -0
- data/VERSION.yml +3 -2
- data/ext/extconf.rb +18 -3
- data/ext/slim_attrib_ext.c +40 -12
- data/lib/slim-attributes.rb +1 -0
- data/lib/slim_attributes.rb +5 -3
- data/test/slim_attributes_test.rb +12 -4
- metadata +32 -12
data/README
CHANGED
@@ -11,15 +11,16 @@ Measuring with just ActiveRecord code - fetching stuff from the database - we se
|
|
11
11
|
Installation
|
12
12
|
============
|
13
13
|
|
14
|
-
|
14
|
+
Slim attributes works with Rails and Ruby 1.8.x. Ruby 1.9 is also supported with Rails version 2.3.5 and above.
|
15
15
|
|
16
16
|
Try:
|
17
|
-
gem install slim-attributes
|
17
|
+
sudo gem install slim-attributes
|
18
18
|
or:
|
19
|
-
gem install slim-attributes
|
19
|
+
sudo gem install slim-attributes -- --with-mysql-config
|
20
20
|
|
21
|
-
then add this to environment.rb:
|
22
|
-
|
21
|
+
then add this to environment.rb in the Rails::Initializer.run section:
|
22
|
+
|
23
|
+
config.gem 'slim-attributes'
|
23
24
|
|
24
25
|
|
25
26
|
Description
|
@@ -36,9 +37,25 @@ So this is an alternative implementation of all_hashes that returns a 'fake hash
|
|
36
37
|
The field contents are then instantiated into Ruby strings on demand - ruby strings are only made if you need them. Note that if you always look at all the columns when you fetch data from the database then this won't necessarily be faster that the unpatched mysql adapter. But it won't be much slower either, and we do expect that most times not all the columns from a result set are accessed.
|
37
38
|
|
38
39
|
|
39
|
-
|
40
|
+
Bugs
|
41
|
+
====
|
42
|
+
|
43
|
+
Slim attributes will not work correctly with ruby 1.9.x with versions lower than Rails 2.3.5
|
44
|
+
|
45
|
+
|
46
|
+
Warranty
|
47
|
+
========
|
48
|
+
|
49
|
+
No warranty - this gem has been extensively tested, but not in all environments.
|
50
|
+
We are using it in our production environment with very good results.
|
51
|
+
Please report bugs to sdsykes at symbol gmail pip com or via the github issue tracking system.
|
52
|
+
|
53
|
+
|
54
|
+
Credits
|
55
|
+
=======
|
40
56
|
|
41
|
-
|
42
|
-
|
57
|
+
Thanks to IronDigital for the initial port for ruby 1.9.
|
58
|
+
Thanks to Greg Hazel (ghazel) for fixing compilation for windows.
|
59
|
+
Thanks to Nando Vieira (fnando) for adding slim-attributes.rb to avoid the underscore dash confusion.
|
43
60
|
|
44
|
-
Copyright (c) 2008 Stephen Sykes, released under the MIT license
|
61
|
+
Copyright (c) 2008-2010 Stephen Sykes, released under the MIT license
|
data/Rakefile
CHANGED
@@ -12,8 +12,16 @@ begin
|
|
12
12
|
s.authors = ["Stephen Sykes"]
|
13
13
|
s.files = FileList["[A-Z]*", "{ext,lib,test}/**/*"]
|
14
14
|
s.extensions = "ext/extconf.rb"
|
15
|
+
s.rubyforge_project = 'slim-attributes'
|
15
16
|
end
|
17
|
+
Jeweler::GemcutterTasks.new
|
18
|
+
Jeweler::RubyforgeTasks.new
|
16
19
|
rescue LoadError
|
17
20
|
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://
|
18
21
|
gems.github.com"
|
19
22
|
end
|
23
|
+
|
24
|
+
task :rdoc do
|
25
|
+
`mkdir rdoc`
|
26
|
+
`echo documentation is at http://github.com/sdsykes/slim-attributes > rdoc/README.rdoc`
|
27
|
+
end
|
data/VERSION.yml
CHANGED
data/ext/extconf.rb
CHANGED
@@ -1,12 +1,27 @@
|
|
1
|
-
# this code
|
1
|
+
# this code was originally borrowed from Mysql/Ruby, credit to TOMITA Masahiro
|
2
2
|
# it works for me under OS X and Fedora, hope it works for you also
|
3
3
|
|
4
4
|
require 'mkmf'
|
5
5
|
|
6
|
-
|
6
|
+
# Improved detection of mysql_config
|
7
|
+
# Code from DataObjects do_mysql adapter
|
8
|
+
# All instances of mysql_config on PATH ...
|
9
|
+
def mysql_config_paths
|
10
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).collect do |path|
|
11
|
+
[ "#{path}/mysql_config", "#{path}/mysql_config5" ].
|
12
|
+
detect { |bin| File.exist?(bin) }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# The first mysql_config binary on PATH ...
|
17
|
+
def default_mysql_config_path
|
18
|
+
mysql_config_paths.compact.first
|
19
|
+
end
|
20
|
+
|
21
|
+
if RUBY_PLATFORM =~ /mswin|mingw/
|
7
22
|
inc, lib = dir_config('mysql')
|
8
23
|
exit 1 unless have_library("libmysql")
|
9
|
-
elsif mc = with_config('mysql-config') then
|
24
|
+
elsif mc = with_config('mysql-config', default_mysql_config_path) then
|
10
25
|
mc = 'mysql_config' if mc == true
|
11
26
|
cflags = `#{mc} --cflags`.chomp
|
12
27
|
exit 1 if $? != 0
|
data/ext/slim_attrib_ext.c
CHANGED
@@ -2,7 +2,12 @@
|
|
2
2
|
// http://pennysmalls.com
|
3
3
|
|
4
4
|
#include "ruby.h"
|
5
|
+
|
6
|
+
#ifdef HAVE_RUBY_ST_H
|
7
|
+
#include "ruby/st.h"
|
8
|
+
#else
|
5
9
|
#include "st.h"
|
10
|
+
#endif
|
6
11
|
|
7
12
|
#include <mysql.h>
|
8
13
|
#include <errmsg.h>
|
@@ -13,7 +18,8 @@
|
|
13
18
|
#define GetCharStarPtr(obj) (Check_Type(obj, T_DATA), (char**)DATA_PTR(obj))
|
14
19
|
|
15
20
|
VALUE cRowHash, cClass;
|
16
|
-
ID pointers_id, row_info_id, field_indexes_id, real_hash_id, to_hash_id
|
21
|
+
ID pointers_id, row_info_id, field_indexes_id, real_hash_id, to_hash_id, sq_parens_id,
|
22
|
+
sq_parens_equal_id, has_key_id;
|
17
23
|
|
18
24
|
#define MAX_CACHED_COLUMN_IDS 40
|
19
25
|
ID column_ids[MAX_CACHED_COLUMN_IDS];
|
@@ -25,8 +31,8 @@ struct mysql_res {
|
|
25
31
|
};
|
26
32
|
|
27
33
|
// row info
|
28
|
-
#define SLIM_IS_NULL
|
29
|
-
#define SLIM_IS_SET
|
34
|
+
#define SLIM_IS_NULL 0x01
|
35
|
+
#define SLIM_IS_SET 0x02
|
30
36
|
|
31
37
|
#define GET_COL_IV_ID(str, cnum) (cnum < MAX_CACHED_COLUMN_IDS ? column_ids[cnum] : (sprintf(str, "@col_%ld", cnum), rb_intern(str)))
|
32
38
|
|
@@ -98,7 +104,7 @@ static VALUE fetch_by_index(VALUE obj, VALUE index) {
|
|
98
104
|
long col_number = FIX2LONG(index);
|
99
105
|
unsigned int length;
|
100
106
|
row_info = GetCharPtr(rb_ivar_get(obj, row_info_id)) + col_number; // flags for this column
|
101
|
-
if (*row_info
|
107
|
+
if (*row_info & SLIM_IS_NULL) return Qnil; // return nil if null from db
|
102
108
|
col_id = GET_COL_IV_ID(col_name, col_number);
|
103
109
|
if (*row_info == SLIM_IS_SET) return rb_ivar_get(obj, col_id); // was made to a string already
|
104
110
|
pointers = GetCharStarPtr(rb_ivar_get(obj, pointers_id)); // find the data and make ruby string
|
@@ -113,12 +119,16 @@ static VALUE fetch_by_index(VALUE obj, VALUE index) {
|
|
113
119
|
// This is the [] method of the row data object.
|
114
120
|
// It checks for a real hash, but if none exists it will call fetch_by_index
|
115
121
|
static VALUE slim_fetch(VALUE obj, VALUE name) {
|
116
|
-
VALUE field_indexes, hash_lookup;
|
122
|
+
VALUE field_indexes, hash_lookup, real_hash;
|
117
123
|
|
118
|
-
if (REAL_HASH_EXISTS) return
|
124
|
+
if (REAL_HASH_EXISTS) return rb_funcall(rb_ivar_get(obj, real_hash_id), sq_parens_id, 1, name);
|
119
125
|
|
120
126
|
hash_lookup = rb_hash_aref(field_indexes, name);
|
121
|
-
if (NIL_P(hash_lookup))
|
127
|
+
if (NIL_P(hash_lookup)) {
|
128
|
+
real_hash = rb_ivar_get(obj, real_hash_id);
|
129
|
+
if (NIL_P(real_hash)) return Qnil;
|
130
|
+
return rb_funcall(real_hash, sq_parens_id, 1, name);
|
131
|
+
}
|
122
132
|
return fetch_by_index(obj, hash_lookup);
|
123
133
|
}
|
124
134
|
|
@@ -131,10 +141,10 @@ static VALUE set_element(VALUE obj, VALUE name, VALUE val) {
|
|
131
141
|
char col_name[16];
|
132
142
|
ID col_id;
|
133
143
|
|
134
|
-
if (REAL_HASH_EXISTS) return
|
144
|
+
if (REAL_HASH_EXISTS) return rb_funcall(rb_ivar_get(obj, real_hash_id), sq_parens_equal_id, 2, name, val);
|
135
145
|
|
136
146
|
hash_lookup = rb_hash_aref(field_indexes, name);
|
137
|
-
if (NIL_P(hash_lookup)) return
|
147
|
+
if (NIL_P(hash_lookup)) return rb_funcall(rb_funcall(obj, to_hash_id, 0), sq_parens_equal_id, 2, name, val);
|
138
148
|
col_number = FIX2LONG(hash_lookup);
|
139
149
|
col_id = GET_COL_IV_ID(col_name, col_number);
|
140
150
|
rb_ivar_set(obj, col_id, val);
|
@@ -159,7 +169,11 @@ static VALUE slim_dup(VALUE obj) {
|
|
159
169
|
|
160
170
|
if (REAL_HASH_EXISTS) return rb_obj_dup(rb_ivar_get(obj, real_hash_id));
|
161
171
|
|
172
|
+
#ifdef RHASH_SIZE
|
173
|
+
nf = RHASH_SIZE(field_indexes);
|
174
|
+
#else
|
162
175
|
nf = RHASH(field_indexes)->tbl->num_entries;
|
176
|
+
#endif
|
163
177
|
row_info_space = ruby_xmalloc(nf); // dup needs its own set of flags
|
164
178
|
if (!row_info_space) rb_raise(rb_eNoMemError, "out of memory");
|
165
179
|
memcpy(row_info_space, GetCharPtr(rb_ivar_get(obj, row_info_id)), nf);
|
@@ -175,10 +189,20 @@ static VALUE slim_dup(VALUE obj) {
|
|
175
189
|
// Calls to model property methods in AR cause a call to has_key?, so it
|
176
190
|
// is implemented here in C for speed.
|
177
191
|
static VALUE has_key(VALUE obj, VALUE name) {
|
178
|
-
VALUE field_indexes;
|
192
|
+
VALUE field_indexes, real_hash;
|
179
193
|
|
194
|
+
#ifdef RHASH_TBL
|
195
|
+
if (REAL_HASH_EXISTS) return (st_lookup(RHASH_TBL(rb_ivar_get(obj, real_hash_id)), name, 0) ? Qtrue : Qfalse);
|
196
|
+
else if (st_lookup(RHASH_TBL(field_indexes), name, 0)) return Qtrue;
|
197
|
+
#else
|
180
198
|
if (REAL_HASH_EXISTS) return (st_lookup(RHASH(rb_ivar_get(obj, real_hash_id))->tbl, name, 0) ? Qtrue : Qfalse);
|
181
|
-
else
|
199
|
+
else if (st_lookup(RHASH(field_indexes)->tbl, name, 0)) return Qtrue;
|
200
|
+
#endif
|
201
|
+
else {
|
202
|
+
real_hash = rb_ivar_get(obj, real_hash_id);
|
203
|
+
if (NIL_P(real_hash)) return Qfalse;
|
204
|
+
return rb_funcall(real_hash, has_key_id, 1, name);
|
205
|
+
}
|
182
206
|
}
|
183
207
|
|
184
208
|
void Init_slim_attrib_ext() {
|
@@ -196,13 +220,17 @@ void Init_slim_attrib_ext() {
|
|
196
220
|
rb_define_method(cRowHash, "[]", (VALUE(*)(ANYARGS))slim_fetch, 1);
|
197
221
|
rb_define_method(cRowHash, "[]=", (VALUE(*)(ANYARGS))set_element, 2);
|
198
222
|
rb_define_method(cRowHash, "dup", (VALUE(*)(ANYARGS))slim_dup, 0);
|
199
|
-
rb_define_method(cRowHash, "has_key?", (VALUE(*)(ANYARGS))has_key, 1);
|
223
|
+
rb_define_method(cRowHash, "has_key?", (VALUE(*)(ANYARGS))has_key, 1);
|
224
|
+
|
200
225
|
// set up some symbols that we will need
|
201
226
|
pointers_id = rb_intern("@pointers");
|
202
227
|
row_info_id = rb_intern("@row_info");
|
203
228
|
field_indexes_id = rb_intern("@field_indexes");
|
204
229
|
real_hash_id = rb_intern("@real_hash");
|
205
230
|
to_hash_id = rb_intern("to_hash");
|
231
|
+
sq_parens_id = rb_intern("[]");
|
232
|
+
sq_parens_equal_id = rb_intern("[]=");
|
233
|
+
has_key_id = rb_intern("has_key?");
|
206
234
|
for(i=0; i < MAX_CACHED_COLUMN_IDS; i++) {
|
207
235
|
sprintf(col_name, "@col_%d", i);
|
208
236
|
column_ids[i] = rb_intern(col_name);
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'slim_attributes'
|
data/lib/slim_attributes.rb
CHANGED
@@ -9,6 +9,8 @@ require 'slim_attrib_ext'
|
|
9
9
|
|
10
10
|
class Mysql::Result
|
11
11
|
class RowHash
|
12
|
+
attr_accessor :real_hash
|
13
|
+
|
12
14
|
def marshal_dump
|
13
15
|
to_hash
|
14
16
|
end
|
@@ -28,8 +30,8 @@ class Mysql::Result
|
|
28
30
|
# This should be the exception though, and the efficiencies of using slim-attributes
|
29
31
|
# are lost when this happens.
|
30
32
|
def to_hash
|
31
|
-
return @real_hash
|
32
|
-
@real_hash
|
33
|
+
return @real_hash unless @field_indexes
|
34
|
+
@real_hash ||= {}
|
33
35
|
@field_indexes.each_pair {|name, index| @real_hash[name] = fetch_by_index(index)}
|
34
36
|
@field_indexes = nil
|
35
37
|
@real_hash
|
@@ -46,7 +48,7 @@ class Mysql::Result
|
|
46
48
|
to_hash.freeze
|
47
49
|
regular_freeze
|
48
50
|
end
|
49
|
-
|
51
|
+
|
50
52
|
def method_missing(name, *args, &block)
|
51
53
|
to_hash.send(name, *args, &block)
|
52
54
|
end
|
@@ -4,7 +4,7 @@
|
|
4
4
|
require 'rubygems'
|
5
5
|
require 'active_record'
|
6
6
|
require 'active_record/version'
|
7
|
-
require 'slim_attributes'
|
7
|
+
require File.dirname(__FILE__) + '/../lib/slim_attributes'
|
8
8
|
require 'test/unit'
|
9
9
|
require File.dirname(__FILE__) + "/products"
|
10
10
|
require File.dirname(__FILE__) + "/slim_db_test_utils"
|
@@ -16,6 +16,11 @@ class SlimAttributesTest < Test::Unit::TestCase
|
|
16
16
|
Product.make_some_products
|
17
17
|
end
|
18
18
|
|
19
|
+
def test_slim_attributes_is_proxying_results
|
20
|
+
x = Product.find(:first)
|
21
|
+
assert_equal Mysql::Result::RowHash, x.instance_variable_get(:@attributes).class
|
22
|
+
end
|
23
|
+
|
19
24
|
def test_finds_all
|
20
25
|
items = Product.find(:all)
|
21
26
|
assert items.size == 100, "must find all 100 items"
|
@@ -138,7 +143,10 @@ class SlimAttributesTest < Test::Unit::TestCase
|
|
138
143
|
item1.name = "bar"
|
139
144
|
assert_equal "product_0", item3.name, "name must be original from cached query"
|
140
145
|
item2.name << "_test"
|
141
|
-
# unmodified rails fails this test
|
146
|
+
# unmodified rails fails this test because the attributes are not dupped, only the
|
147
|
+
# hash containing them is
|
148
|
+
# but this test is useful - it shows that the rowhash has not been made
|
149
|
+
# into a real hash before dup in called in the query cache code
|
142
150
|
check_attributes_for(item3, 0)
|
143
151
|
end
|
144
152
|
end
|
@@ -149,7 +157,7 @@ class SlimAttributesTest < Test::Unit::TestCase
|
|
149
157
|
item1.destroy # object is frozen
|
150
158
|
assert_equal true, item1.frozen?
|
151
159
|
check_attributes_for(item1, 0)
|
152
|
-
assert_raises(TypeError) {item1.name = "another product"}
|
160
|
+
assert_raises(RUBY_VERSION >= "1.9" ? RuntimeError : TypeError) {item1.name = "another product"}
|
153
161
|
end
|
154
162
|
|
155
163
|
def teardown
|
@@ -163,7 +171,7 @@ class SlimAttributesTest < Test::Unit::TestCase
|
|
163
171
|
assert_equal i, item.number, "item number must be right"
|
164
172
|
assert_equal i + 1, item.id, "item id must be right"
|
165
173
|
assert_equal "Made by the test suite", item.comment, "item comment must be right"
|
166
|
-
assert
|
174
|
+
assert item.created_at <= Time.now && item.created_at > Time.now - 30, "item created_at must be reasonable"
|
167
175
|
assert_nil item.nil_test, "nil_test must be nil"
|
168
176
|
end
|
169
177
|
end
|
metadata
CHANGED
@@ -1,7 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ghazel-slim-attributes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 109
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 7
|
9
|
+
- 6
|
10
|
+
- 1
|
11
|
+
version: 0.7.6.1
|
5
12
|
platform: ruby
|
6
13
|
authors:
|
7
14
|
- Stephen Sykes
|
@@ -9,11 +16,13 @@ autorequire:
|
|
9
16
|
bindir: bin
|
10
17
|
cert_chain: []
|
11
18
|
|
12
|
-
date: 2009-
|
19
|
+
date: 2009-12-23 00:00:00 -08:00
|
13
20
|
default_executable:
|
14
21
|
dependencies: []
|
15
22
|
|
16
|
-
description:
|
23
|
+
description: |-
|
24
|
+
Slim attributes boosts speed in Rails/Mysql ActiveRecord Models by avoiding
|
25
|
+
instantiating Hashes for each result row, and lazily instantiating attributes as needed.
|
17
26
|
email: sdsykes@gmail.com
|
18
27
|
executables: []
|
19
28
|
|
@@ -23,11 +32,12 @@ extra_rdoc_files:
|
|
23
32
|
- README
|
24
33
|
files:
|
25
34
|
- MIT_LICENCE
|
26
|
-
- Rakefile
|
27
35
|
- README
|
36
|
+
- Rakefile
|
28
37
|
- VERSION.yml
|
29
38
|
- ext/extconf.rb
|
30
39
|
- ext/slim_attrib_ext.c
|
40
|
+
- lib/slim-attributes.rb
|
31
41
|
- lib/slim_attributes.rb
|
32
42
|
- test/benchmark.rb
|
33
43
|
- test/database.yml
|
@@ -36,30 +46,40 @@ files:
|
|
36
46
|
- test/slim_db_test_utils.rb
|
37
47
|
has_rdoc: true
|
38
48
|
homepage: http://github.com/sdsykes/slim-attributes
|
49
|
+
licenses: []
|
50
|
+
|
39
51
|
post_install_message:
|
40
52
|
rdoc_options:
|
41
|
-
- --inline-source
|
42
53
|
- --charset=UTF-8
|
43
54
|
require_paths:
|
44
55
|
- lib
|
45
56
|
required_ruby_version: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
46
58
|
requirements:
|
47
59
|
- - ">="
|
48
60
|
- !ruby/object:Gem::Version
|
61
|
+
hash: 3
|
62
|
+
segments:
|
63
|
+
- 0
|
49
64
|
version: "0"
|
50
|
-
version:
|
51
65
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
52
67
|
requirements:
|
53
68
|
- - ">="
|
54
69
|
- !ruby/object:Gem::Version
|
70
|
+
hash: 3
|
71
|
+
segments:
|
72
|
+
- 0
|
55
73
|
version: "0"
|
56
|
-
version:
|
57
74
|
requirements: []
|
58
75
|
|
59
|
-
rubyforge_project:
|
60
|
-
rubygems_version: 1.
|
76
|
+
rubyforge_project: slim-attributes
|
77
|
+
rubygems_version: 1.3.7
|
61
78
|
signing_key:
|
62
|
-
specification_version:
|
79
|
+
specification_version: 3
|
63
80
|
summary: Slim-attributes - lazy instantiation of attributes for ActiveRecord
|
64
|
-
test_files:
|
65
|
-
|
81
|
+
test_files:
|
82
|
+
- test/benchmark.rb
|
83
|
+
- test/products.rb
|
84
|
+
- test/slim_attributes_test.rb
|
85
|
+
- test/slim_db_test_utils.rb
|