sql_record 0.1.2 → 0.2.0
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.
- data/Gemfile +1 -0
- data/Gemfile.lock +2 -0
- data/LICENSE.txt +1 -1
- data/README.rdoc +7 -5
- data/Rakefile +1 -6
- data/VERSION +1 -1
- data/lib/sql_record/attributes/mapper.rb +68 -0
- data/lib/sql_record/base.rb +19 -0
- data/lib/sql_record/sanitized_query.rb +31 -0
- data/lib/sql_record.rb +3 -65
- data/spec/spec_helper.rb +2 -2
- data/sql_record.gemspec +9 -8
- metadata +32 -21
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -9,6 +9,7 @@ GEM
|
|
9
9
|
rake
|
10
10
|
rake (0.8.7)
|
11
11
|
rcov (0.9.9)
|
12
|
+
rdoc (3.5.3)
|
12
13
|
rspec (2.3.0)
|
13
14
|
rspec-core (~> 2.3.0)
|
14
15
|
rspec-expectations (~> 2.3.0)
|
@@ -26,5 +27,6 @@ DEPENDENCIES
|
|
26
27
|
bundler (~> 1.0.0)
|
27
28
|
jeweler (~> 1.5.2)
|
28
29
|
rcov
|
30
|
+
rdoc
|
29
31
|
rspec (~> 2.3.0)
|
30
32
|
yard (~> 0.6.0)
|
data/LICENSE.txt
CHANGED
data/README.rdoc
CHANGED
@@ -8,17 +8,15 @@ Well that's what SQLRecord does.
|
|
8
8
|
|
9
9
|
== Example
|
10
10
|
|
11
|
-
class UserWithAccount
|
12
|
-
include SQLRecord
|
11
|
+
class UserWithAccount << SQLRecord::Base
|
13
12
|
|
14
|
-
|
15
|
-
with_class User do
|
13
|
+
with_opts :class => User do
|
16
14
|
column :id
|
17
15
|
column :user_email, :from => :email
|
18
16
|
column :created_at
|
19
17
|
end
|
20
18
|
|
21
|
-
|
19
|
+
with_opts :class => Account do
|
22
20
|
column :account_name, :from => :name
|
23
21
|
end
|
24
22
|
|
@@ -44,6 +42,10 @@ Well that's what SQLRecord does.
|
|
44
42
|
=> Time
|
45
43
|
|
46
44
|
|
45
|
+
== Contributers
|
46
|
+
|
47
|
+
Thanks to {Loren Segal}[http://gnuu.org] for the big code review, and making me aware that sound OO principles are not dead in ruby.
|
48
|
+
|
47
49
|
== Contributing to sql-record
|
48
50
|
|
49
51
|
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
data/Rakefile
CHANGED
@@ -16,12 +16,7 @@ Jeweler::Tasks.new do |gem|
|
|
16
16
|
gem.homepage = "http://github.com/visfleet/sql_record"
|
17
17
|
gem.license = "MIT"
|
18
18
|
gem.summary = %Q{SQL direct mapping to ActiveRecord}
|
19
|
-
gem.description = %Q{Do you use ActiveRecord::Connection.execute for speed sometimes?
|
20
|
-
|
21
|
-
Does it bother you that the results are not mapped to your schema and type-cast as ActiveRecord would?
|
22
|
-
|
23
|
-
Well that's what SQLRecord does.
|
24
|
-
}
|
19
|
+
gem.description = %Q{Do you use ActiveRecord::Connection.execute for speed sometimes? Does it bother you that the results are not mapped to your schema and type-cast as ActiveRecord would? Well that's what SQLRecord does.}
|
25
20
|
gem.email = "rasheed@visfleet.com"
|
26
21
|
gem.authors = ["Rasheed Abdul-Aziz"]
|
27
22
|
# Include your dependencies below. Runtime dependencies are required when using your gem,
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# @author Rasheed Abdul-Aziz
|
2
|
+
module SQLRecord
|
3
|
+
module Attributes
|
4
|
+
module Mapper
|
5
|
+
|
6
|
+
attr_reader :sql_select_columns
|
7
|
+
|
8
|
+
# with_opts blocks specify default options for calls to {#column}
|
9
|
+
#
|
10
|
+
# @param opts [Hash] anything that {#column} supports. Currently this should only be :class
|
11
|
+
#
|
12
|
+
# @example Longhand (not using with_opts)
|
13
|
+
# column :name, :class => Account
|
14
|
+
# column :id, :class => Account
|
15
|
+
# ...snip...
|
16
|
+
# column :created_at, :class => Account
|
17
|
+
#
|
18
|
+
# @example Shorthand (using with_opts)
|
19
|
+
# with_opts :class => Account
|
20
|
+
# column :name
|
21
|
+
# column :id
|
22
|
+
# ...snip...
|
23
|
+
# column :created_at
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
def with_opts opts, &block
|
27
|
+
@default_opts = opts
|
28
|
+
block.arity == 2 ? yield(self) : self.instance_eval(&block)
|
29
|
+
@default_opts = nil
|
30
|
+
end
|
31
|
+
|
32
|
+
# Specifies the mapping from an ActiveRecord#column_definition to an SQLRecord instance attribute.
|
33
|
+
# @param [Symbol] attribute_name the attribute you are defining for this model
|
34
|
+
# @option opts [Class] :class the active record this attribute will use to type_cast from
|
35
|
+
# @option opts [Symbol,String] :from if it differs from the attribute_name, the schema column of the active record
|
36
|
+
# to use for type_cast
|
37
|
+
#
|
38
|
+
# @example Simple mapping
|
39
|
+
# # Account#name column maps to the "name" attribute
|
40
|
+
# column :name, :class => Account
|
41
|
+
#
|
42
|
+
# @example Mapping a different column name
|
43
|
+
# # Account#name column maps to the "account name" attribute
|
44
|
+
# column :account_name, :class => Account, :from => :name
|
45
|
+
#
|
46
|
+
def column attribute_name, opts = {}
|
47
|
+
klass = opts[:class] || @default_opts[:class] || nil
|
48
|
+
raise ArgumentError, 'You must specify a :class option, either explicitly, or using with_opts' if klass.nil?
|
49
|
+
|
50
|
+
source_attribute = (opts[:from] || attribute_name).to_s
|
51
|
+
|
52
|
+
define_method attribute_name do
|
53
|
+
klass.columns_hash[source_attribute].type_cast(@raw_attributes[attribute_name.to_s])
|
54
|
+
end
|
55
|
+
|
56
|
+
# bit mucky, a lot here that feels like it should be a little method of its own
|
57
|
+
select_column = "#{klass.table_name}.#{source_attribute}"
|
58
|
+
select_column += " as #{attribute_name}" if opts[:from]
|
59
|
+
(@sql_select_columns ||= []) << select_column
|
60
|
+
end
|
61
|
+
|
62
|
+
def sql_select_helper
|
63
|
+
@sql_select_columns.join(', ')
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module SQLRecord
|
2
|
+
# Base provides a class that has a collection of raw_attributes.
|
3
|
+
# These can be set from a database abstraction (SQLRecord::SanitizedQuery), and are expected to be type_cast by a mixin
|
4
|
+
# (SQLRecord::Attributes::Mapper)
|
5
|
+
#
|
6
|
+
# @todo Does it sound like the database abstraction could be a whole other class?
|
7
|
+
class Base
|
8
|
+
extend SQLRecord::SanitizedQuery
|
9
|
+
extend SQLRecord::Attributes::Mapper
|
10
|
+
|
11
|
+
# the raw attributes returned from a db query
|
12
|
+
attr_accessor :raw_attributes
|
13
|
+
|
14
|
+
def initialize raw_attributes = {}
|
15
|
+
@raw_attributes = raw_attributes
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module SQLRecord
|
2
|
+
module SanitizedQuery
|
3
|
+
# Executes the {#query} proc on your database, building SQLRecords with the results.
|
4
|
+
# @param params [Hash] a hash of parameters that are yielded to the {#query} proc
|
5
|
+
# @return [Array] {SQLRecord::Base}s with their raw_attributes set to the row results.
|
6
|
+
def find params={}
|
7
|
+
rows = execute_query params
|
8
|
+
|
9
|
+
rows.map do |row|
|
10
|
+
new row
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def query &deferred
|
15
|
+
@query_proc = deferred
|
16
|
+
end
|
17
|
+
|
18
|
+
protected
|
19
|
+
|
20
|
+
# @todo check that this logs the sql
|
21
|
+
def execute_query params={}
|
22
|
+
sql = ActiveRecord::Base.send(:sanitize_sql_array, get_query_array(params))
|
23
|
+
ActiveRecord::Base.connection.execute(sql)
|
24
|
+
end
|
25
|
+
|
26
|
+
def get_query_array(params)
|
27
|
+
@query_proc.call(params)
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
data/lib/sql_record.rb
CHANGED
@@ -1,65 +1,3 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
@row = row
|
5
|
-
end
|
6
|
-
|
7
|
-
def self.included(base)
|
8
|
-
base.extend ClassMethods
|
9
|
-
end
|
10
|
-
|
11
|
-
module ClassMethods
|
12
|
-
|
13
|
-
def with_class klass, &block
|
14
|
-
@current_class = klass
|
15
|
-
block.arity == 2 ? yield(self) : self.instance_eval(&block)
|
16
|
-
@current_class = nil
|
17
|
-
end
|
18
|
-
|
19
|
-
def column attribute_name, opts = {}
|
20
|
-
klass = opts[:class] || @current_class || nil
|
21
|
-
raise ArgumentError, 'Either opts[:class] is not defined or you have not specified a with_class block' if klass.nil?
|
22
|
-
|
23
|
-
source_attribute = (opts[:from] || attribute_name).to_s
|
24
|
-
|
25
|
-
define_method attribute_name do
|
26
|
-
klass.columns_hash[source_attribute].type_cast(@row[attribute_name.to_s])
|
27
|
-
end
|
28
|
-
|
29
|
-
# bit mucky, a lot here that feels like it should be a little method of its own
|
30
|
-
select_column = "#{klass.table_name}.#{source_attribute}"
|
31
|
-
select_column += " as #{attribute_name}" if opts[:from]
|
32
|
-
(@sql_select_columns ||= []) << select_column
|
33
|
-
end
|
34
|
-
|
35
|
-
def query &deferred
|
36
|
-
@query_proc = deferred
|
37
|
-
end
|
38
|
-
|
39
|
-
def find params={}
|
40
|
-
rows = execute_query params
|
41
|
-
|
42
|
-
rows.map do |row|
|
43
|
-
new row
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
protected
|
48
|
-
|
49
|
-
def execute_query params={}
|
50
|
-
# does this log?
|
51
|
-
sql = ActiveRecord::Base.send(:sanitize_sql_array, get_query_array(params))
|
52
|
-
ActiveRecord::Base.connection.execute(sql)
|
53
|
-
end
|
54
|
-
|
55
|
-
def get_query_array(params)
|
56
|
-
if @query_proc.arity == 2
|
57
|
-
@query_proc.call(params, @sql_select_columns.join(", "))
|
58
|
-
else
|
59
|
-
@query_proc.call(params)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
end
|
64
|
-
|
65
|
-
end
|
1
|
+
require 'sql_record/sanitized_query'
|
2
|
+
require 'sql_record/attributes/mapper'
|
3
|
+
require 'sql_record/base'
|
data/spec/spec_helper.rb
CHANGED
@@ -5,8 +5,8 @@ require 'sql-record'
|
|
5
5
|
|
6
6
|
# Requires supporting files with custom matchers and macros, etc,
|
7
7
|
# in ./support/ and its subdirectories.
|
8
|
-
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
8
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
9
9
|
|
10
10
|
RSpec.configure do |config|
|
11
|
-
|
11
|
+
|
12
12
|
end
|
data/sql_record.gemspec
CHANGED
@@ -5,17 +5,12 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{sql_record}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Rasheed Abdul-Aziz"]
|
12
|
-
s.date = %q{2011-04-
|
13
|
-
s.description = %q{Do you use ActiveRecord::Connection.execute for speed sometimes?
|
14
|
-
|
15
|
-
Does it bother you that the results are not mapped to your schema and type-cast as ActiveRecord would?
|
16
|
-
|
17
|
-
Well that's what SQLRecord does.
|
18
|
-
}
|
12
|
+
s.date = %q{2011-04-08}
|
13
|
+
s.description = %q{Do you use ActiveRecord::Connection.execute for speed sometimes? Does it bother you that the results are not mapped to your schema and type-cast as ActiveRecord would? Well that's what SQLRecord does.}
|
19
14
|
s.email = %q{rasheed@visfleet.com}
|
20
15
|
s.extra_rdoc_files = [
|
21
16
|
"LICENSE.txt",
|
@@ -32,6 +27,9 @@ Well that's what SQLRecord does.
|
|
32
27
|
"VERSION",
|
33
28
|
"init.rb",
|
34
29
|
"lib/sql_record.rb",
|
30
|
+
"lib/sql_record/attributes/mapper.rb",
|
31
|
+
"lib/sql_record/base.rb",
|
32
|
+
"lib/sql_record/sanitized_query.rb",
|
35
33
|
"spec/spec_helper.rb",
|
36
34
|
"spec/sql_record_spec.rb",
|
37
35
|
"sql_record.gemspec"
|
@@ -50,12 +48,14 @@ Well that's what SQLRecord does.
|
|
50
48
|
s.specification_version = 3
|
51
49
|
|
52
50
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
51
|
+
s.add_development_dependency(%q<rdoc>, [">= 0"])
|
53
52
|
s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
|
54
53
|
s.add_development_dependency(%q<yard>, ["~> 0.6.0"])
|
55
54
|
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
56
55
|
s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
|
57
56
|
s.add_development_dependency(%q<rcov>, [">= 0"])
|
58
57
|
else
|
58
|
+
s.add_dependency(%q<rdoc>, [">= 0"])
|
59
59
|
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
60
60
|
s.add_dependency(%q<yard>, ["~> 0.6.0"])
|
61
61
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
@@ -63,6 +63,7 @@ Well that's what SQLRecord does.
|
|
63
63
|
s.add_dependency(%q<rcov>, [">= 0"])
|
64
64
|
end
|
65
65
|
else
|
66
|
+
s.add_dependency(%q<rdoc>, [">= 0"])
|
66
67
|
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
67
68
|
s.add_dependency(%q<yard>, ["~> 0.6.0"])
|
68
69
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sql_record
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
- 1
|
9
8
|
- 2
|
10
|
-
|
9
|
+
- 0
|
10
|
+
version: 0.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Rasheed Abdul-Aziz
|
@@ -15,12 +15,26 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-04-
|
18
|
+
date: 2011-04-08 00:00:00 +00:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
|
-
name:
|
22
|
+
name: rdoc
|
23
23
|
version_requirements: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 3
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
32
|
+
prerelease: false
|
33
|
+
type: :development
|
34
|
+
requirement: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: rspec
|
37
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
24
38
|
none: false
|
25
39
|
requirements:
|
26
40
|
- - ~>
|
@@ -33,10 +47,10 @@ dependencies:
|
|
33
47
|
version: 2.3.0
|
34
48
|
prerelease: false
|
35
49
|
type: :development
|
36
|
-
requirement: *
|
50
|
+
requirement: *id002
|
37
51
|
- !ruby/object:Gem::Dependency
|
38
52
|
name: yard
|
39
|
-
version_requirements: &
|
53
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
40
54
|
none: false
|
41
55
|
requirements:
|
42
56
|
- - ~>
|
@@ -49,10 +63,10 @@ dependencies:
|
|
49
63
|
version: 0.6.0
|
50
64
|
prerelease: false
|
51
65
|
type: :development
|
52
|
-
requirement: *
|
66
|
+
requirement: *id003
|
53
67
|
- !ruby/object:Gem::Dependency
|
54
68
|
name: bundler
|
55
|
-
version_requirements: &
|
69
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
56
70
|
none: false
|
57
71
|
requirements:
|
58
72
|
- - ~>
|
@@ -65,10 +79,10 @@ dependencies:
|
|
65
79
|
version: 1.0.0
|
66
80
|
prerelease: false
|
67
81
|
type: :development
|
68
|
-
requirement: *
|
82
|
+
requirement: *id004
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: jeweler
|
71
|
-
version_requirements: &
|
85
|
+
version_requirements: &id005 !ruby/object:Gem::Requirement
|
72
86
|
none: false
|
73
87
|
requirements:
|
74
88
|
- - ~>
|
@@ -81,10 +95,10 @@ dependencies:
|
|
81
95
|
version: 1.5.2
|
82
96
|
prerelease: false
|
83
97
|
type: :development
|
84
|
-
requirement: *
|
98
|
+
requirement: *id005
|
85
99
|
- !ruby/object:Gem::Dependency
|
86
100
|
name: rcov
|
87
|
-
version_requirements: &
|
101
|
+
version_requirements: &id006 !ruby/object:Gem::Requirement
|
88
102
|
none: false
|
89
103
|
requirements:
|
90
104
|
- - ">="
|
@@ -95,14 +109,8 @@ dependencies:
|
|
95
109
|
version: "0"
|
96
110
|
prerelease: false
|
97
111
|
type: :development
|
98
|
-
requirement: *
|
99
|
-
description:
|
100
|
-
Do you use ActiveRecord::Connection.execute for speed sometimes?
|
101
|
-
|
102
|
-
Does it bother you that the results are not mapped to your schema and type-cast as ActiveRecord would?
|
103
|
-
|
104
|
-
Well that's what SQLRecord does.
|
105
|
-
|
112
|
+
requirement: *id006
|
113
|
+
description: Do you use ActiveRecord::Connection.execute for speed sometimes? Does it bother you that the results are not mapped to your schema and type-cast as ActiveRecord would? Well that's what SQLRecord does.
|
106
114
|
email: rasheed@visfleet.com
|
107
115
|
executables: []
|
108
116
|
|
@@ -122,6 +130,9 @@ files:
|
|
122
130
|
- VERSION
|
123
131
|
- init.rb
|
124
132
|
- lib/sql_record.rb
|
133
|
+
- lib/sql_record/attributes/mapper.rb
|
134
|
+
- lib/sql_record/base.rb
|
135
|
+
- lib/sql_record/sanitized_query.rb
|
125
136
|
- spec/spec_helper.rb
|
126
137
|
- spec/sql_record_spec.rb
|
127
138
|
- sql_record.gemspec
|