Skip to content

Commit 7ca62e6

Browse files
committed
Added new ActiveRecord::View class as abstract superclass for views. Adapted view naming to plural convention.
1 parent b52f315 commit 7ca62e6

File tree

8 files changed

+83
-27
lines changed

8 files changed

+83
-27
lines changed

lib/active_record/view.rb

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
2+
module ActiveRecord
3+
class View < Base
4+
self.abstract_class = true
5+
6+
def readonly?
7+
true
8+
end
9+
10+
class << self
11+
def based_on(model)
12+
define_method("to_#{model.name.demodulize.underscore}") do
13+
### TODO reload?
14+
becomes(model)
15+
end
16+
17+
model.reflect_on_all_associations.each do |assoc|
18+
steal_association(model, assoc)
19+
end
20+
end
21+
22+
def steal_association(model, *associations)
23+
associations.each do |association|
24+
r = case association
25+
when String, Symbol
26+
model.reflect_on_association(association.to_sym)
27+
when ActiveRecord::Reflection::AssociationReflection
28+
association
29+
else
30+
raise ArgumentError, "Unrecognized association #{association.inspect}; must be a Symbol, String, or AssociationReflection."
31+
end
32+
case r.macro
33+
when :belongs_to
34+
### ensure that the fk column exists
35+
when :has_many
36+
### TODO add options for :through assocs
37+
options = r.options.merge(
38+
:class_name => r.class_name,
39+
:foreign_key => r.primary_key_name
40+
)
41+
has_many r.name, options
42+
when :has_and_belongs_to_many
43+
options = r.options.merge(
44+
:class_name => r.class_name,
45+
:foreign_key => r.primary_key_name,
46+
:association_foreign_key => r.association_foreign_key
47+
)
48+
has_and_belongs_to_many r.name, options
49+
end
50+
end
51+
end
52+
end
53+
end
54+
end

test/adapter_test.rb

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ def test_tables
1010
create_view
1111
found = ActiveRecord::Base.connection.tables.sort
1212
found.delete(ActiveRecord::Migrator.schema_migrations_table_name)
13-
assert_equal ["people", "people2", "places", "v_person"], found
13+
assert_equal ["people", "people2", "places", "v_people"], found
1414
end
1515
def test_base_tables
1616
create_view
@@ -20,54 +20,54 @@ def test_base_tables
2020
end
2121
def test_views
2222
create_view
23-
assert_equal ['v_person'], ActiveRecord::Base.connection.views
23+
assert_equal ['v_people'], ActiveRecord::Base.connection.views
2424
end
2525
def test_columns
2626
create_view
27-
assert_equal ["f_name", "l_name", "social_security"], ActiveRecord::Base.connection.columns('v_person').collect { |c| c.name }
27+
assert_equal ["f_name", "l_name", "social_security"], ActiveRecord::Base.connection.columns('v_people').collect { |c| c.name }
2828
end
2929
def test_supports_views
3030
assert ActiveRecord::Base.connection.supports_views?
3131
end
3232

3333
def test_mapped_views
3434
create_mapping
35-
assert_equal ['v_person'], ActiveRecord::Base.connection.views
35+
assert_equal ['v_people'], ActiveRecord::Base.connection.views
3636
end
3737
def test_mapped_columns
3838
create_mapping
39-
assert_equal ["f_name", "l_name"], ActiveRecord::Base.connection.columns('v_person').collect { |c| c.name }
39+
assert_equal ["f_name", "l_name"], ActiveRecord::Base.connection.columns('v_people').collect { |c| c.name }
4040
end
4141

4242
def test_view_select_statement
4343
case ActiveRecord::Base.connection.adapter_name
4444
when "MySQL":
45-
assert_equal "select `people`.`first_name` AS `f_name`,`people`.`last_name` AS `l_name`,`people`.`ssn` AS `social_security` from `people`", ActiveRecord::Base.connection.view_select_statement('v_person')
45+
assert_equal "select `people`.`first_name` AS `f_name`,`people`.`last_name` AS `l_name`,`people`.`ssn` AS `social_security` from `people`", ActiveRecord::Base.connection.view_select_statement('v_people')
4646
when "PostgreSQL":
47-
assert_equal "SELECT people.first_name AS f_name, people.last_name AS l_name, people.ssn AS social_security FROM people;", ActiveRecord::Base.connection.view_select_statement('v_person')
47+
assert_equal "SELECT people.first_name AS f_name, people.last_name AS l_name, people.ssn AS social_security FROM people;", ActiveRecord::Base.connection.view_select_statement('v_people')
4848
end
4949
end
5050

5151
def test_old_name_not_found_error_during_mapping
5252
assert_raise ActiveRecord::ActiveRecordError do
53-
ActiveRecord::Base.connection.create_mapping_view(:people, :v_person, :force => true) do |v|
53+
ActiveRecord::Base.connection.create_mapping_view(:people, :v_people, :force => true) do |v|
5454
v.map_column :foo, :bar
5555
end
5656
end
5757
end
5858

5959
private
6060
def create_view
61-
# ActiveRecord::Base.connection.create_view(:v_person, 'select * from people', :force => true) do |v|
62-
ActiveRecord::Base.connection.create_view(:v_person, 'select first_name, last_name, ssn from people', :force => true) do |v|
61+
# ActiveRecord::Base.connection.create_view(:v_people, 'select * from people', :force => true) do |v|
62+
ActiveRecord::Base.connection.create_view(:v_people, 'select first_name, last_name, ssn from people', :force => true) do |v|
6363
v.column :f_name
6464
v.column :l_name
6565
v.column :social_security
6666
end
6767
end
6868

6969
def create_mapping
70-
ActiveRecord::Base.connection.create_mapping_view(:people, :v_person, :force => true) do |v|
70+
ActiveRecord::Base.connection.create_mapping_view(:people, :v_people, :force => true) do |v|
7171
v.map_column :id, nil
7272
v.map_column :first_name, :f_name
7373
v.map_column :last_name, :l_name

test/models/v_person.rb

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1-
class VPerson < ActiveRecord::Base
2-
set_table_name 'v_person'
3-
end
1+
require 'active_record/view'
2+
3+
class VPerson < ActiveRecord::View
4+
5+
end

test/schema.native_mysql.expected.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
t.string "country", :limit => 2
3131
end
3232

33-
create_view "v_person", "select `people`.`first_name` AS `f_name`,`people`.`last_name` AS `l_name`,`people`.`ssn` AS `social_security` from `people`", :force => true do |v|
33+
create_view "v_people", "select `people`.`first_name` AS `f_name`,`people`.`last_name` AS `l_name`,`people`.`ssn` AS `social_security` from `people`", :force => true do |v|
3434
v.column :f_name
3535
v.column :l_name
3636
v.column :social_security

test/schema.native_postgresql.expected.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
t.string "country", :limit => 2
3131
end
3232

33-
create_view "v_person", "SELECT people.first_name AS f_name, people.last_name AS l_name, people.ssn AS social_security FROM people;", :force => true do |v|
33+
create_view "v_people", "SELECT people.first_name AS f_name, people.last_name AS l_name, people.ssn AS social_security FROM people;", :force => true do |v|
3434
v.column :f_name
3535
v.column :l_name
3636
v.column :social_security

test/schema_dumper_test.rb

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,18 @@
44
Debugger.start
55
class SchemaDumperTest < Test::Unit::TestCase
66
def setup
7-
ActiveRecord::Base.connection.execute('drop view if exists v_person')
7+
ActiveRecord::Base.connection.execute('drop view if exists v_people')
88
ActiveRecord::Base.connection.execute('drop view if exists v_profile')
99
end
1010
def test_view
11-
create_person_view
11+
create_people_view
1212
stream = StringIO.new
1313
dumper = ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
1414
stream.rewind
1515
assert_equal File.open(File.dirname(__FILE__) + "/schema.#{$connection}.expected.rb", 'r').readlines, stream.readlines
1616
end
1717
def test_dump_and_load
18-
create_person_view
18+
create_people_view
1919
assert_dump_and_load_succeed
2020
end
2121
def test_union
@@ -32,19 +32,19 @@ def test_union
3232
assert_dump_and_load_succeed
3333
end
3434
def test_symbol_ignore
35-
ActiveRecord::SchemaDumper.ignore_views << :v_person
36-
create_person_view
35+
ActiveRecord::SchemaDumper.ignore_views << :v_people
36+
create_people_view
3737
assert_dump_and_load_succeed
3838
ActiveRecord::SchemaDumper.ignore_views.pop
3939
end
4040
def test_regex_ignore
41-
ActiveRecord::SchemaDumper.ignore_views << Regexp.new(/v_person/)
42-
create_person_view
41+
ActiveRecord::SchemaDumper.ignore_views << Regexp.new(/v_people/)
42+
create_people_view
4343
assert_dump_and_load_succeed
4444
ActiveRecord::SchemaDumper.ignore_views.pop
4545
end
4646
def test_non_allowed_object_raises_error
47-
create_person_view
47+
create_people_view
4848
ActiveRecord::SchemaDumper.ignore_views << 0
4949
begin
5050
schema_file = File.dirname(__FILE__) + "/schema.#{$connection}.out.rb"

test/test_helper.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
require 'models/v_person'
1717

1818
class Test::Unit::TestCase
19-
def create_person_view
20-
ActiveRecord::Base.connection.create_view(:v_person,
19+
def create_people_view
20+
ActiveRecord::Base.connection.create_view(:v_people,
2121
'select first_name, last_name, ssn from people', :force => true) do |v|
2222
v.column :f_name
2323
v.column :l_name

test/view_test.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ class ViewTest < Test::Unit::TestCase
44
def test_create_view
55
Person.create(:first_name => 'John', :last_name => 'Doe', :ssn => '123456789')
66
assert_nothing_raised do
7-
ActiveRecord::Base.connection.create_view(:v_person,
7+
ActiveRecord::Base.connection.create_view(:v_people,
88
'select first_name, last_name, ssn from people', :force => true) do |v|
99
v.column :f_name
1010
v.column :l_name

0 commit comments

Comments
 (0)