active_illusion 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,18 @@
1
+ .bundle
2
+ db/*.sqlite3
3
+ log/*.log
4
+ tmp/
5
+ .*.sw*
6
+ *.orig
7
+ .swp
8
+ public/system
9
+ *.*.BACKUP.*.lock
10
+ *.*.BASE.*.lock
11
+ *.*.REMOTE.*.lock
12
+ *.*.LOCAL.*.lock
13
+ .DS_Store
14
+ *.*.gz
15
+ Session.vim
16
+ err.txt
17
+ .sass-cache
18
+ public/stylesheets/*.css
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'http://rubygems.org'
2
+ # dependencies are specified in jasmine.gemspec
3
+
4
+ gemspec
5
+
6
+ gem "rspec"
@@ -0,0 +1,47 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ active_illusion (0.0.1)
5
+ activerecord (>= 3.1.0.rc4)
6
+ squeel (>= 0.8.5)
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ activemodel (3.1.0.rc5)
12
+ activesupport (= 3.1.0.rc5)
13
+ bcrypt-ruby (~> 2.1.4)
14
+ builder (~> 3.0.0)
15
+ i18n (~> 0.6)
16
+ activerecord (3.1.0.rc5)
17
+ activemodel (= 3.1.0.rc5)
18
+ activesupport (= 3.1.0.rc5)
19
+ arel (~> 2.1.4)
20
+ tzinfo (~> 0.3.29)
21
+ activesupport (3.1.0.rc5)
22
+ multi_json (~> 1.0)
23
+ arel (2.1.4)
24
+ bcrypt-ruby (2.1.4)
25
+ builder (3.0.0)
26
+ diff-lcs (1.1.2)
27
+ i18n (0.6.0)
28
+ multi_json (1.0.3)
29
+ rspec (2.6.0)
30
+ rspec-core (~> 2.6.0)
31
+ rspec-expectations (~> 2.6.0)
32
+ rspec-mocks (~> 2.6.0)
33
+ rspec-core (2.6.4)
34
+ rspec-expectations (2.6.0)
35
+ diff-lcs (~> 1.1.2)
36
+ rspec-mocks (2.6.0)
37
+ squeel (0.8.6)
38
+ activerecord (~> 3.0)
39
+ activesupport (~> 3.0)
40
+ tzinfo (0.3.29)
41
+
42
+ PLATFORMS
43
+ ruby
44
+
45
+ DEPENDENCIES
46
+ active_illusion!
47
+ rspec
@@ -0,0 +1,47 @@
1
+ Inherit from this class to create tableless models that are backed by a query. Behaves
2
+ a little like a classic SQL view.
3
+
4
+ For example
5
+
6
+ class Award < ActiveRecord::Base
7
+ has_many :award_type_view
8
+ end
9
+
10
+ class AwardTypeView < ActiveRecord::Illusion
11
+ column :award_type, :string
12
+ column :award_id, :integer
13
+
14
+ belongs_to :award
15
+
16
+ view
17
+ Award.select{
18
+ [awards.type.as(award_type), awards.id.as(award_id)]
19
+ }
20
+ end
21
+
22
+ end
23
+
24
+ The cool thing is, is that the relations work on both directions
25
+
26
+ a = AwardTypeView.first
27
+
28
+ SELECT "award_type_views".* FROM
29
+ (SELECT "awards"."type" AS award_type, "awards"."id" AS award_id FROM awards )
30
+ award_type_views LIMIT 1
31
+
32
+ a.award
33
+
34
+ SELECT "awards".* FROM "awards" WHERE "awards"."id" = 1 LIMIT 1
35
+
36
+ b = Award.first
37
+
38
+ SELECT "awards".* FROM "awards" LIMIT 1
39
+
40
+ b.award_type_views
41
+
42
+ SELECT "award_type_views".* FROM
43
+ (SELECT "awards"."type" AS award_type, "awards"."id" AS award_id FROM awards )
44
+ award_type_views
45
+ WHERE "award_type_views"."award_id" = 1
46
+
47
+ Currently this gem depends on the SQUEEL SQL gem
@@ -0,0 +1,15 @@
1
+ # Provide a simple gemspec so you can easily use your
2
+ # project in your rails apps through git.
3
+ Gem::Specification.new do |s|
4
+ s.name = "active_illusion"
5
+ s.summary = "Create ActiveRecord models backed only by an SQL query NOT a table."
6
+ s.description = ""
7
+ s.files = `git ls-files`.split "\n"
8
+ s.authors = ["Brad Phelan"]
9
+ s.email = "bradphelan@xtargets.com"
10
+ s.homepage = "https://github.com/bradphelan/Active-Illusion"
11
+ s.version = "0.0.1"
12
+ s.platform = Gem::Platform::RUBY
13
+ s.add_dependency 'activerecord', '>= 3.1.0.rc4'
14
+ s.add_dependency 'squeel', '>= 0.8.5'
15
+ end
@@ -0,0 +1,99 @@
1
+ require 'active_record'
2
+ require 'active_support/all'
3
+
4
+ module ActiveRecord
5
+ # requires the squeel gem
6
+ #
7
+ # https://github.com/ernie/squeel
8
+ #
9
+ # Inherit from this class to create tableless
10
+ # models that are backed by a query.
11
+ #
12
+ # For example
13
+ #
14
+ # class Award < ActiveRecord::Base
15
+ # has_many :award_type_view
16
+ # end
17
+ #
18
+ # class AwardTypeView < Illusion
19
+ # column :award_type, :string
20
+ # column :award_id, :integer
21
+ #
22
+ # belongs_to :award
23
+ #
24
+ # view
25
+ # select{[awards.type.as(award_type), awards.id.as(award_id)]}.from("awards")
26
+ # end
27
+ # end
28
+ #
29
+ # The cool thing is, is that the relations work on both directions
30
+ #
31
+ # a = AwardTypeView.first
32
+ #
33
+ # SELECT "award_type_views".* FROM
34
+ # (SELECT "awards"."type" AS award_type, "awards"."id" AS award_id FROM awards )
35
+ # award_type_views LIMIT 1
36
+ #
37
+ # a.award
38
+ #
39
+ # SELECT "awards".* FROM "awards" WHERE "awards"."id" = 1 LIMIT 1
40
+ #
41
+ # b = Award.first
42
+ #
43
+ # SELECT "awards".* FROM "awards" LIMIT 1
44
+ #
45
+ # b.award_type_views
46
+ #
47
+ # SELECT "award_type_views".* FROM
48
+ # (SELECT "awards"."type" AS award_type, "awards"."id" AS award_id FROM awards )
49
+ # award_type_views
50
+ # WHERE "award_type_views"."award_id" = 1
51
+
52
+ # end
53
+ class Illusion < ActiveRecord::Base
54
+ def self.columns()
55
+ @columns ||= []
56
+ end
57
+
58
+ def self.columns_hash()
59
+ @columns_hash ||= {}
60
+ end
61
+
62
+ def self.find_all
63
+ raise "please override"
64
+ end
65
+
66
+ class << self
67
+ def default_scope_with_wrap
68
+ end
69
+ end
70
+
71
+ def self.view
72
+ meta = class << self;self;end
73
+ m = yield
74
+ table = self.to_s.underscore.pluralize
75
+ meta.send :define_method, :default_scope do
76
+ q = m.arel.as table
77
+ select{}.from(q)
78
+ end
79
+ end
80
+
81
+ def self.column(name, sql_type = :string, default = nil, null = true)
82
+ column = ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default, sql_type.to_s, null)
83
+
84
+ columns << column
85
+ columns_hash[name.to_s] = column
86
+ end
87
+
88
+ self.abstract_class = true
89
+
90
+ def self.table_name
91
+ to_s.underscore.pluralize
92
+ end
93
+
94
+ def readonly?
95
+ true
96
+ end
97
+
98
+ end
99
+ end
@@ -0,0 +1,122 @@
1
+ require 'rubygems'
2
+ require 'active_illusion'
3
+ require 'squeel'
4
+
5
+ TIMES = (ENV['N'] || 10000).to_i
6
+
7
+ require 'rubygems'
8
+ require "active_record"
9
+
10
+ conn = { :adapter => 'sqlite3', :database => ':memory:' }
11
+ ActiveRecord::Base.establish_connection(conn)
12
+
13
+ class User < ActiveRecord::Base
14
+ connection.create_table :users, :force => true do |t|
15
+ t.string :name, :email
16
+ t.timestamps
17
+ end
18
+
19
+ has_many :exhibits
20
+ end
21
+
22
+ class Exhibit < ActiveRecord::Base
23
+ connection.create_table :exhibits, :force => true do |t|
24
+ t.belongs_to :user
25
+ t.string :name
26
+ t.text :notes
27
+ t.integer :ssn
28
+ t.timestamps
29
+ end
30
+
31
+ belongs_to :user
32
+
33
+ def look; attributes end
34
+ def feel; look; user.name end
35
+
36
+ def self.look(exhibits) exhibits.each { |e| e.look } end
37
+ def self.feel(exhibits) exhibits.each { |e| e.feel } end
38
+ end
39
+
40
+ module ActiveRecord
41
+ class Faker
42
+ LOREM = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse non aliquet diam. Curabitur vel urna metus, quis malesuada elit. Integer consequat tincidunt felis. Etiam non erat dolor. Vivamus imperdiet nibh sit amet diam eleifend id posuere diam malesuada. Mauris at accumsan sem. Donec id lorem neque. Fusce erat lorem, ornare eu congue vitae, malesuada quis neque. Maecenas vel urna a velit pretium fermentum. Donec tortor enim, tempor venenatis egestas a, tempor sed ipsum. Ut arcu justo, faucibus non imperdiet ac, interdum at diam. Pellentesque ipsum enim, venenatis ut iaculis vitae, varius vitae sem. Sed rutrum quam ac elit euismod bibendum. Donec ultricies ultricies magna, at lacinia libero mollis aliquam. Sed ac arcu in tortor elementum tincidunt vel interdum sem. Curabitur eget erat arcu. Praesent eget eros leo. Nam magna enim, sollicitudin vehicula scelerisque in, vulputate ut libero. Praesent varius tincidunt commodo".split
43
+ def self.name
44
+ LOREM.grep(/^\w*$/).sort_by { rand }.first(2).join ' '
45
+ end
46
+
47
+ def self.email
48
+ LOREM.grep(/^\w*$/).sort_by { rand }.first(2).join('@') + ".com"
49
+ end
50
+ end
51
+ end
52
+
53
+ class Test0 < ActiveRecord::Illusion
54
+ column :name
55
+ column :exhibition
56
+ column :number
57
+ #belongs_to :user, :foreign_key => :name
58
+
59
+ view do
60
+ User.joins{exhibits}.select{
61
+ [users.name.as(name), exhibits.name.as(xname), exhibits.ssn.as(number) ]
62
+ }
63
+ end
64
+ end
65
+
66
+ # pre-compute the insert statements and fake data compilation,
67
+ # so the benchmarks below show the actual runtime for the execute
68
+ # method, minus the setup steps
69
+
70
+ # Using the same paragraph for all exhibits because it is very slow
71
+ # to generate unique paragraphs for all exhibits.
72
+ notes = ActiveRecord::Faker::LOREM.join ' '
73
+ today = Date.today
74
+
75
+
76
+ describe ActiveRecord::Illusion do
77
+ before :each do
78
+
79
+ User.destroy_all
80
+
81
+ Exhibit.destroy_all
82
+
83
+ puts 'Inserting 100 users and exhibits...'
84
+ 100.times do |i|
85
+ user = User.create(
86
+ :created_at => today,
87
+ :name => ActiveRecord::Faker.name,
88
+ :email => ActiveRecord::Faker.email
89
+ )
90
+
91
+ Exhibit.create(
92
+ :created_at => today,
93
+ :name => ActiveRecord::Faker.name,
94
+ :user => user,
95
+ :notes => notes,
96
+ :ssn => i
97
+ )
98
+ end
99
+
100
+ end
101
+
102
+ it "should have 100 users" do
103
+ User.count.should == 100
104
+ end
105
+
106
+ it "should have 100 exhibits" do
107
+ Exhibit.count.should == 100
108
+ end
109
+
110
+ describe Test0 do
111
+ it "should retrieve 100 rows" do
112
+ Test0.where{}.to_sql.should ==
113
+ %Q[SELECT \"test0s\".* FROM (SELECT \"users\".\"name\" AS name, \"exhibits\".\"name\" AS xname, \"exhibits\".\"ssn\" AS number FROM \"users\" INNER JOIN \"exhibits\" ON \"exhibits\".\"user_id\" = \"users\".\"id\") test0s ]
114
+ Test0.count.should == 100
115
+
116
+
117
+ Test0.where{number < 20}.to_sql.should ==
118
+ %Q[SELECT "test0s".* FROM (SELECT "users"."name" AS name, "exhibits"."name" AS xname, "exhibits"."ssn" AS number FROM "users" INNER JOIN "exhibits" ON "exhibits"."user_id" = "users"."id") test0s WHERE "test0s"."number" < 20]
119
+ Test0.where{number < 20}.count.should == 20
120
+ end
121
+ end
122
+ end
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: active_illusion
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - Brad Phelan
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-08-05 00:00:00 +02:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: activerecord
18
+ prerelease: false
19
+ requirement: &id001 !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: 3.1.0.rc4
25
+ type: :runtime
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
28
+ name: squeel
29
+ prerelease: false
30
+ requirement: &id002 !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: 0.8.5
36
+ type: :runtime
37
+ version_requirements: *id002
38
+ description: ""
39
+ email: bradphelan@xtargets.com
40
+ executables: []
41
+
42
+ extensions: []
43
+
44
+ extra_rdoc_files: []
45
+
46
+ files:
47
+ - .gitignore
48
+ - Gemfile
49
+ - Gemfile.lock
50
+ - README.md
51
+ - active_illusion.gemspec
52
+ - lib/active_illusion.rb
53
+ - spec/illusion_spec.rb
54
+ has_rdoc: true
55
+ homepage: https://github.com/bradphelan/Active-Illusion
56
+ licenses: []
57
+
58
+ post_install_message:
59
+ rdoc_options: []
60
+
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: "0"
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: "0"
75
+ requirements: []
76
+
77
+ rubyforge_project:
78
+ rubygems_version: 1.6.2
79
+ signing_key:
80
+ specification_version: 3
81
+ summary: Create ActiveRecord models backed only by an SQL query NOT a table.
82
+ test_files: []
83
+