valium 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +19 -0
- data/README.md +101 -0
- data/Rakefile +17 -0
- data/lib/valium.rb +105 -0
- data/lib/valium/version.rb +3 -0
- data/spec/console.rb +7 -0
- data/spec/helpers/valium_helper.rb +9 -0
- data/spec/spec_helper.rb +42 -0
- data/spec/support/schema.rb +50 -0
- data/spec/valium/valium_spec.rb +167 -0
- data/valium.gemspec +30 -0
- metadata +97 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
gemspec
|
3
|
+
|
4
|
+
rails = ENV['RAILS'] || 'master'
|
5
|
+
|
6
|
+
case rails
|
7
|
+
when /\// # A path
|
8
|
+
path rails do
|
9
|
+
gem 'activerecord'
|
10
|
+
end
|
11
|
+
when /^v/ # A tagged version
|
12
|
+
git 'git://github.com/rails/rails.git', :tag => rails do
|
13
|
+
gem 'activerecord'
|
14
|
+
end
|
15
|
+
else
|
16
|
+
git 'git://github.com/rails/rails.git', :branch => rails do
|
17
|
+
gem 'activerecord'
|
18
|
+
end
|
19
|
+
end
|
data/README.md
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
# Valium
|
2
|
+
|
3
|
+
Suffering from ActiveRecord instantiation anxiety? Try Valium. It
|
4
|
+
saves your CPU and memory for more important things, retrieving
|
5
|
+
just the values you're interested in seeing.
|
6
|
+
|
7
|
+
## Usage
|
8
|
+
|
9
|
+
### In your Gemfile:
|
10
|
+
|
11
|
+
gem 'valium'
|
12
|
+
|
13
|
+
### In your code:
|
14
|
+
|
15
|
+
You can select a single value...
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
Post.where(:published => true)[:title]
|
19
|
+
# - OR -
|
20
|
+
Post.where(:published => true).value_of :title
|
21
|
+
# => ["First Post", "Another Awesome Post", ...]
|
22
|
+
```
|
23
|
+
|
24
|
+
... or several ...
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
Employee.where(:title => 'Sr. Monkey Wrangler')[:first_name, :last_name, :hired_at]
|
28
|
+
# - OR -
|
29
|
+
Employee.where(:title => 'Sr. Monkey Wrangler').value_of :first_name, :last_name, :hired_at
|
30
|
+
# => [["Ernie", "Miller", 2009-09-21 08:00:00 -0400],
|
31
|
+
["Herb", "Myers", 2002-02-13 09:00:00 -0400], ...]
|
32
|
+
```
|
33
|
+
|
34
|
+
Values returned by Valium will be the data types you'd expect, just
|
35
|
+
as though you instantiated the ActiveRecord object and used the
|
36
|
+
accessor. This includes serialized attributes:
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
class Animal < ActiveRecord::Base
|
40
|
+
serialize :extra_info
|
41
|
+
end
|
42
|
+
|
43
|
+
Animal.where(:genus => 'felis')[:species, :extra_info]
|
44
|
+
# => [["catus", {:domestic => true}], ["lolcatus", {:can_has_cheezburger => true}], ...]
|
45
|
+
```
|
46
|
+
|
47
|
+
## Why would I use this?
|
48
|
+
|
49
|
+
It's not uncommon for Rails apps to need only one or two attributes
|
50
|
+
from a bunch of ActiveRecord objects. They'll have code like this:
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
MyModel.some_scope.map(&:id)
|
54
|
+
```
|
55
|
+
|
56
|
+
Or, if the developer is a bit more clever about saving memory, he
|
57
|
+
might use code like this:
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
MyModel.some_scope.select(:id).map(&:id)
|
61
|
+
```
|
62
|
+
|
63
|
+
This helps a good deal with memory usage, but even if we cut down
|
64
|
+
on the memory usage a bit, the truth is that no matter what we try,
|
65
|
+
**instantiating ActiveRecord objects is slow.**
|
66
|
+
|
67
|
+
This is because ActiveRecord provides all kinds of awesome stuff,
|
68
|
+
none of which we need, if we're just looking to grab one or two
|
69
|
+
values and print them out, or perform a quick calculation, or
|
70
|
+
something.
|
71
|
+
|
72
|
+
Check out [this gist of a benchmark script and results](https://gist.github.com/1166964)
|
73
|
+
to see just how much it can hurt when you're instantiating
|
74
|
+
unnecessary ActiveRecord objects.
|
75
|
+
|
76
|
+
TL;DR: It hurts *a lot*. For retrieving a single value, using Valium
|
77
|
+
is nearly 10x faster than mapping over ActiveRecord objects.
|
78
|
+
For multiple values, it's about 5x faster. Even if you're
|
79
|
+
deserializing attributes, where more time, proportionally, gets
|
80
|
+
spent in the deserialization process than with normal attributes,
|
81
|
+
Valium can be up to twice as fast as mapping over ActiveRecord
|
82
|
+
objects, in my tests.
|
83
|
+
|
84
|
+
## Conclusion
|
85
|
+
|
86
|
+
You knew everything I mentioned above, already. In fact,
|
87
|
+
you're probably mocking me right now:
|
88
|
+
|
89
|
+
"ZOMG OBJECTS USE MEMORY AND INSTANTIATION TAKES CPU CYCLES!
|
90
|
+
I R GENIUS!"
|
91
|
+
|
92
|
+
Yeah. It's not rocket science. This is just a quick little
|
93
|
+
(seriously, around 100 LOC) gem that provides some intuitive
|
94
|
+
syntax around a common pattern and doesn't stomp on any
|
95
|
+
existing ActiveRecord functionality. It "just works."
|
96
|
+
|
97
|
+
Give it a try. Your code will thank you for it.
|
98
|
+
|
99
|
+
## Copyright
|
100
|
+
|
101
|
+
Copyright © 2011 [Ernie Miller](http://twitter.com/erniemiller)
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
|
4
|
+
RSpec::Core::RakeTask.new(:spec) do |rspec|
|
5
|
+
rspec.rspec_opts = ['--backtrace']
|
6
|
+
end
|
7
|
+
|
8
|
+
task :default => :spec
|
9
|
+
|
10
|
+
desc "Open an irb session with Valium and the sample data used in specs"
|
11
|
+
task :console do
|
12
|
+
require 'irb'
|
13
|
+
require 'irb/completion'
|
14
|
+
require 'console'
|
15
|
+
ARGV.clear
|
16
|
+
IRB.start
|
17
|
+
end
|
data/lib/valium.rb
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
require "valium/version"
|
2
|
+
require 'active_record'
|
3
|
+
|
4
|
+
module Valium
|
5
|
+
if ActiveRecord::VERSION::MAJOR == 3
|
6
|
+
|
7
|
+
if ActiveRecord::VERSION::MINOR == 0 # We need to use the old deserialize code
|
8
|
+
|
9
|
+
def valium_deserialize(value, klass)
|
10
|
+
if value.is_a?(String) && value =~ /^---/
|
11
|
+
result = YAML::load(value) rescue value
|
12
|
+
if result.nil? || result.is_a?(klass)
|
13
|
+
result
|
14
|
+
else
|
15
|
+
raise SerializationTypeMismatch,
|
16
|
+
"Expected a #{klass}, but was a #{result.class}"
|
17
|
+
end
|
18
|
+
else
|
19
|
+
value
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
else # we're on 3.1+, yay for coder.load!
|
24
|
+
|
25
|
+
def valium_deserialize(value, coder)
|
26
|
+
coder.load(value)
|
27
|
+
end
|
28
|
+
|
29
|
+
end # Minor version check
|
30
|
+
|
31
|
+
def value_of(*attr_names)
|
32
|
+
attr_names.map! do |attr_name|
|
33
|
+
attr_name = attr_name.to_s
|
34
|
+
attr_name == 'id' ? primary_key : attr_name
|
35
|
+
end
|
36
|
+
|
37
|
+
if attr_names.size > 1
|
38
|
+
valium_select_multiple(attr_names)
|
39
|
+
else
|
40
|
+
valium_select_one(attr_names.first)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
alias :[] :value_of
|
45
|
+
|
46
|
+
def valium_select_multiple(attr_names)
|
47
|
+
columns = attr_names.map {|n| columns_hash[n]}
|
48
|
+
coders = attr_names.map {|n| serialized_attributes[n]}
|
49
|
+
|
50
|
+
connection.select_rows(
|
51
|
+
except(:select).select(attr_names.map {|n| arel_table[n]}).to_sql
|
52
|
+
).map! do |values|
|
53
|
+
values.each_with_index do |value, index|
|
54
|
+
values[index] = valium_cast(value, columns[index], coders[index])
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def valium_select_one(attr_name)
|
60
|
+
column = columns_hash[attr_name]
|
61
|
+
coder = serialized_attributes[attr_name]
|
62
|
+
|
63
|
+
connection.select_rows(
|
64
|
+
except(:select).select(arel_table[attr_name]).to_sql
|
65
|
+
).map! do |values|
|
66
|
+
valium_cast(values[0], column, coder)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def valium_cast(value, column, coder_or_klass)
|
71
|
+
if value.nil? || !column
|
72
|
+
value
|
73
|
+
elsif coder_or_klass
|
74
|
+
valium_deserialize(value, coder_or_klass)
|
75
|
+
else
|
76
|
+
column.type_cast(value)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
module Relation
|
81
|
+
def value_of(*args)
|
82
|
+
if args.size > 0 && args.all? {|a| String === a || Symbol === a}
|
83
|
+
args.map! do |attr_name|
|
84
|
+
attr_name = attr_name.to_s
|
85
|
+
attr_name == 'id' ? @klass.primary_key : attr_name
|
86
|
+
end
|
87
|
+
|
88
|
+
if loaded? && (empty? || args.all? {|a| first.attributes.has_key? a})
|
89
|
+
to_a.map {|record| args.map {|a| record[a]}}
|
90
|
+
else
|
91
|
+
scoping { @klass[*args] }
|
92
|
+
end
|
93
|
+
else
|
94
|
+
to_a[*args]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
alias :[] :value_of
|
99
|
+
end
|
100
|
+
|
101
|
+
end # Major version check
|
102
|
+
end
|
103
|
+
|
104
|
+
ActiveRecord::Base.extend Valium
|
105
|
+
ActiveRecord::Relation.send :include, Valium::Relation
|
data/spec/console.rb
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
class SQLCounter
|
5
|
+
IGNORED_SQL = [/^PRAGMA /, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/, /^SELECT @@ROWCOUNT/, /^SAVEPOINT/, /^ROLLBACK TO SAVEPOINT/, /^RELEASE SAVEPOINT/, /^SHOW max_identifier_length/,
|
6
|
+
/SELECT name\s+FROM sqlite_master\s+WHERE type = 'table' AND NOT name = 'sqlite_sequence'/]
|
7
|
+
|
8
|
+
# FIXME: this needs to be refactored so specific database can add their own
|
9
|
+
# ignored SQL. This ignored SQL is for Oracle.
|
10
|
+
IGNORED_SQL.concat [/^select .*nextval/i, /^SAVEPOINT/, /^ROLLBACK TO/, /^\s*select .* from all_triggers/im]
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
$queries_executed = []
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(name, start, finish, message_id, values)
|
17
|
+
sql = values[:sql]
|
18
|
+
|
19
|
+
unless 'CACHE' == values[:name]
|
20
|
+
$queries_executed << sql unless IGNORED_SQL.any? { |r| sql =~ r }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
ActiveSupport::Notifications.subscribe('sql.active_record', SQLCounter.new)
|
25
|
+
end
|
26
|
+
|
27
|
+
Dir[File.expand_path('../{helpers,support}/*.rb', __FILE__)].each do |f|
|
28
|
+
require f
|
29
|
+
end
|
30
|
+
|
31
|
+
RSpec.configure do |config|
|
32
|
+
config.before(:suite) do
|
33
|
+
puts '=' * 80
|
34
|
+
puts "Running specs against ActiveRecord #{ActiveRecord::VERSION::STRING}..."
|
35
|
+
puts '=' * 80
|
36
|
+
Schema.create
|
37
|
+
end
|
38
|
+
|
39
|
+
config.include ValiumHelper
|
40
|
+
end
|
41
|
+
|
42
|
+
require 'valium'
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
ActiveRecord::Base.establish_connection(
|
4
|
+
:adapter => 'sqlite3',
|
5
|
+
:database => ':memory:'
|
6
|
+
)
|
7
|
+
|
8
|
+
class Person < ActiveRecord::Base
|
9
|
+
serialize :extra_info
|
10
|
+
end
|
11
|
+
|
12
|
+
class Widget < ActiveRecord::Base
|
13
|
+
serialize :extra_info
|
14
|
+
set_primary_key :widget_id
|
15
|
+
end
|
16
|
+
|
17
|
+
module Schema
|
18
|
+
def self.create
|
19
|
+
ActiveRecord::Base.silence do
|
20
|
+
ActiveRecord::Migration.verbose = false
|
21
|
+
|
22
|
+
ActiveRecord::Schema.define do
|
23
|
+
create_table :people, :force => true do |t|
|
24
|
+
t.string :first_name
|
25
|
+
t.string :last_name
|
26
|
+
t.integer :age
|
27
|
+
t.text :extra_info
|
28
|
+
t.timestamps
|
29
|
+
end
|
30
|
+
|
31
|
+
create_table :widgets, :force => true, :primary_key => :widget_id do |t|
|
32
|
+
t.string :name
|
33
|
+
t.text :extra_info
|
34
|
+
t.timestamps
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
1.upto(100) do |num|
|
40
|
+
Person.create! :first_name => "Person", :last_name => "Number#{num}", :age => num % 99,
|
41
|
+
:extra_info => {:a_key => "Value Number #{num}"}
|
42
|
+
end
|
43
|
+
|
44
|
+
1.upto(100) do |num|
|
45
|
+
Widget.create! :name => "Widget #{num}",
|
46
|
+
:extra_info => {:a_key => "Value Number #{num}"}
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,167 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Valium do
|
4
|
+
|
5
|
+
context 'with a symbol key' do
|
6
|
+
subject { Person[:id] }
|
7
|
+
it { should have(100).ids }
|
8
|
+
it { should eq((1..100).to_a) }
|
9
|
+
end
|
10
|
+
|
11
|
+
context 'with value_of syntax' do
|
12
|
+
subject { Person.value_of :id }
|
13
|
+
it { should have(100).ids }
|
14
|
+
it { should eq((1..100).to_a) }
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'with a string key' do
|
18
|
+
subject { Person['id'] }
|
19
|
+
it { should have(100).ids }
|
20
|
+
it { should eq((1..100).to_a) }
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'with multiple keys' do
|
24
|
+
subject { Person[:id, :last_name] }
|
25
|
+
it { should have(100).elements }
|
26
|
+
it { should eq((1..100).map {|n| [n, "Number#{n}"]})}
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'with a datetime column' do
|
30
|
+
subject { Person[:created_at] }
|
31
|
+
it { should have(100).datetimes }
|
32
|
+
it { should be_all {|d| Time === d}}
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'with a serialized column' do
|
36
|
+
subject { Person[:extra_info] }
|
37
|
+
it { should have(100).hashes }
|
38
|
+
it { should eq 1.upto(100).map {|n| {:a_key => "Value Number #{n}"} }}
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'with an alternate primary key and an :id select' do
|
42
|
+
subject { Widget[:id] }
|
43
|
+
it { should have(100).ids }
|
44
|
+
it { should eq (1..100).to_a}
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'with an alternate primary key and an alternate primary key select' do
|
48
|
+
subject { Widget[:widget_id] }
|
49
|
+
it { should have(100).ids }
|
50
|
+
it { should eq (1..100).to_a}
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'with a scope' do
|
54
|
+
subject { Person.where(:id => [1,50,100])[:last_name] }
|
55
|
+
it { should have(3).last_names }
|
56
|
+
it { should eq ['Number1', 'Number50', 'Number100'] }
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'with a scope and value_of syntax' do
|
60
|
+
subject { Person.where(:id => [1,50,100]).value_of :id }
|
61
|
+
it { should have(3).ids }
|
62
|
+
it { should eq [1,50,100] }
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'with a scope, an alternate primary key, and an :id select' do
|
66
|
+
subject {Widget.where(:widget_id => [1,50,100])[:id] }
|
67
|
+
it { should have(3).ids }
|
68
|
+
it { should eq [1,50,100]}
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'with a scope, an alternate primary key, and an alternate primary key select' do
|
72
|
+
subject { Widget.where(:widget_id => [1,50,100])[:widget_id] }
|
73
|
+
it { should have(3).widget_ids }
|
74
|
+
it { should eq [1,50,100]}
|
75
|
+
end
|
76
|
+
|
77
|
+
context 'with a loaded scope' do
|
78
|
+
subject do
|
79
|
+
Person.where(:id => [1,50,100]).tap do |relation|
|
80
|
+
relation.all
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# We'll generate the first query when we call "subject", but won't
|
85
|
+
# need another query
|
86
|
+
specify { queries_for { subject[:id] }.should have(1).query }
|
87
|
+
|
88
|
+
specify { subject[:id, :created_at, :extra_info].
|
89
|
+
should eq Person.where(:id => [1,50,100])[:id, :created_at, :extra_info] }
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'with a loaded scope, an alternate primary key, and an :id select' do
|
93
|
+
subject do
|
94
|
+
Widget.where(:widget_id => [1,50,100]).tap do |relation|
|
95
|
+
relation.all
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# We'll generate the first query when we call "subject", but won't
|
100
|
+
# need another query
|
101
|
+
specify { queries_for { subject[:id] }.should have(1).query }
|
102
|
+
|
103
|
+
specify { subject[:id, :created_at, :extra_info].
|
104
|
+
should eq Widget.where(:widget_id => [1,50,100])[:id, :created_at, :extra_info] }
|
105
|
+
end
|
106
|
+
|
107
|
+
context 'with a loaded scope but missing attributes' do
|
108
|
+
subject do
|
109
|
+
Person.select(:id).where(:id => [1,50,100]).tap do |relation|
|
110
|
+
relation.all
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# We'll generate the first query when we call "subject", but won't
|
115
|
+
# need another query
|
116
|
+
specify { queries_for { subject[:id] }.should have(1).query }
|
117
|
+
|
118
|
+
# We'll need to run our own query for the attributes
|
119
|
+
specify { queries_for { subject[:first_name] }.should have(2).queries }
|
120
|
+
|
121
|
+
specify { subject[:id, :created_at, :extra_info].
|
122
|
+
should eq Person.where(:id => [1,50,100])[:id, :created_at, :extra_info] }
|
123
|
+
end
|
124
|
+
|
125
|
+
context 'with a loaded scope, an alternate primary key, and missing attributes' do
|
126
|
+
subject do
|
127
|
+
Widget.select(:widget_id).where(:widget_id => [1,50,100]).tap do |relation|
|
128
|
+
relation.all
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# We'll generate the first query when we call "subject", but won't
|
133
|
+
# need another query
|
134
|
+
specify { queries_for { subject[:id] }.should have(1).query }
|
135
|
+
specify { queries_for { subject[:widget_id] }.should have(1).query }
|
136
|
+
|
137
|
+
# We'll need to run our own query for the attributes
|
138
|
+
specify { queries_for { subject[:name] }.should have(2).queries }
|
139
|
+
|
140
|
+
specify { subject[:id, :created_at, :extra_info].
|
141
|
+
should eq Widget.where(:widget_id => [1,50,100])[:id, :created_at, :extra_info] }
|
142
|
+
end
|
143
|
+
|
144
|
+
context 'with a scope and multiple keys' do
|
145
|
+
subject { Person.where(:id => [1,50,100])[:last_name, :id, :extra_info] }
|
146
|
+
it { should have(3).elements }
|
147
|
+
it { should eq [1,50,100].map {|n| ["Number#{n}", n, {:a_key => "Value Number #{n}"}]}}
|
148
|
+
end
|
149
|
+
|
150
|
+
context 'with a relation array index' do
|
151
|
+
subject { Person.where(:id => [1,50,100])[1] }
|
152
|
+
it { should eq Person.find(50) }
|
153
|
+
end
|
154
|
+
|
155
|
+
context 'with a relation array start and length' do
|
156
|
+
subject { Person.where(:id => 1..20)[10,3] }
|
157
|
+
it { should have(3).people }
|
158
|
+
it { should eq Person.offset(10).limit(3) }
|
159
|
+
end
|
160
|
+
|
161
|
+
context 'with a relation array range' do
|
162
|
+
subject { Person.where(:id => 1..20)[0..9] }
|
163
|
+
it { should have(10).people }
|
164
|
+
it { should eq Person.first(10) }
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
data/valium.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "valium/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "valium"
|
7
|
+
s.version = Valium::VERSION
|
8
|
+
s.authors = ["Ernie Miller"]
|
9
|
+
s.email = ["ernie@metautonomo.us"]
|
10
|
+
s.homepage = "http://github.com/ernie/valium"
|
11
|
+
s.summary = %q{
|
12
|
+
Access attribute values directly, without instantiating ActiveRecord objects.
|
13
|
+
}
|
14
|
+
s.description = %q{
|
15
|
+
Suffering from ActiveRecord instantiation anxiety? Try Valium. It
|
16
|
+
saves your CPU and memory for more important things, retrieving
|
17
|
+
just the values you're interested in seeing.
|
18
|
+
}
|
19
|
+
|
20
|
+
s.rubyforge_project = "valium"
|
21
|
+
|
22
|
+
s.add_dependency 'activerecord', '>= 3.0.2'
|
23
|
+
s.add_development_dependency 'rspec', '~> 2.6.0'
|
24
|
+
s.add_development_dependency 'sqlite3', '~> 1.3.3'
|
25
|
+
|
26
|
+
s.files = `git ls-files`.split("\n")
|
27
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
28
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
29
|
+
s.require_paths = ["lib"]
|
30
|
+
end
|
metadata
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: valium
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Ernie Miller
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-08-25 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activerecord
|
16
|
+
requirement: &70159201437300 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 3.0.2
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70159201437300
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rspec
|
27
|
+
requirement: &70159201401980 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 2.6.0
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70159201401980
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: sqlite3
|
38
|
+
requirement: &70159201388400 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.3.3
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70159201388400
|
47
|
+
description: ! "\n Suffering from ActiveRecord instantiation anxiety? Try Valium.
|
48
|
+
It\n saves your CPU and memory for more important things, retrieving\n just
|
49
|
+
the values you're interested in seeing.\n "
|
50
|
+
email:
|
51
|
+
- ernie@metautonomo.us
|
52
|
+
executables: []
|
53
|
+
extensions: []
|
54
|
+
extra_rdoc_files: []
|
55
|
+
files:
|
56
|
+
- .gitignore
|
57
|
+
- Gemfile
|
58
|
+
- README.md
|
59
|
+
- Rakefile
|
60
|
+
- lib/valium.rb
|
61
|
+
- lib/valium/version.rb
|
62
|
+
- spec/console.rb
|
63
|
+
- spec/helpers/valium_helper.rb
|
64
|
+
- spec/spec_helper.rb
|
65
|
+
- spec/support/schema.rb
|
66
|
+
- spec/valium/valium_spec.rb
|
67
|
+
- valium.gemspec
|
68
|
+
homepage: http://github.com/ernie/valium
|
69
|
+
licenses: []
|
70
|
+
post_install_message:
|
71
|
+
rdoc_options: []
|
72
|
+
require_paths:
|
73
|
+
- lib
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ! '>='
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '0'
|
80
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
requirements: []
|
87
|
+
rubyforge_project: valium
|
88
|
+
rubygems_version: 1.8.6
|
89
|
+
signing_key:
|
90
|
+
specification_version: 3
|
91
|
+
summary: Access attribute values directly, without instantiating ActiveRecord objects.
|
92
|
+
test_files:
|
93
|
+
- spec/console.rb
|
94
|
+
- spec/helpers/valium_helper.rb
|
95
|
+
- spec/spec_helper.rb
|
96
|
+
- spec/support/schema.rb
|
97
|
+
- spec/valium/valium_spec.rb
|