remi-activerecord-comments 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown CHANGED
@@ -26,15 +26,12 @@ Usage
26
26
  >> ActiveRecord::Base.comment :foxes
27
27
  => "Represents a Fox, a creature that craves chunky bacon"
28
28
 
29
+ >> ActiveRecord::Base.connection.comment :foxes
30
+ => "Represents a Fox, a creature that craves chunky bacon"
31
+
29
32
  >> Fox.columns
30
33
  => [#<ActiveRecord::...>, #<ActiveRecord::...>]
31
34
 
32
- >> Fox.column_names
33
- => ["id", "name", "has_had_truck_stolen"]
34
-
35
- >> Fox.column_comments
36
- => ["Primary Key", "Fox's name", "Whether or not this Fox has had his/her truck stolen"]
37
-
38
35
  >> Fox.columns.first.name
39
36
  => "id"
40
37
 
@@ -47,6 +44,9 @@ Usage
47
44
  >> ActiveRecord::Base.column_comment :id, :foxes
48
45
  => "Primary Key"
49
46
 
47
+ >> ActiveRecord::Base.connection.column_comment :id, :foxes
48
+ => "Primary Key"
49
+
50
50
 
51
51
  Database Support
52
52
  ----------------
@@ -75,5 +75,11 @@ this, or you can add comments to your `CREATE TABLE` declarations ...
75
75
  for more MySQL examples, see [spec/mysql_comments_spec.rb][mysql_spec]
76
76
 
77
77
 
78
+ Future Ideas
79
+ ------------
80
+
81
+ - create `db-doc` or (something) that provides a system for documenting your database schema, whether it be via .yml files or as database comments or whatever. then make `activerecord-comments` an extension to that (basically just a different data store for your schema documentation). there should always be a way to easily document your schema, regardless of whether or not your database(s) supports comments. and, with or without database comments, there should be an easy way to see which tables/columns you have and haven't documented!
82
+
83
+
78
84
  [mysql_adapter]: http://github.com/remi/activerecord-comments/tree/master/lib/activerecord-comments/mysql_adapter.rb
79
85
  [mysql_spec]: http://github.com/remi/activerecord-comments/tree/master/spec/mysql_comments_spec.rb
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 1
4
+ :patch: 1
@@ -0,0 +1,103 @@
1
+ module ActiveRecord::Comments::AbstractAdapterExt
2
+
3
+ def self.included base
4
+ puts "including abstract adapter extensions in #{ base.inspect }"
5
+
6
+ base.instance_eval {
7
+ alias_method_chain :columns, :table_name # this is evil!!! how to fix? column needs to know its table :(
8
+ }
9
+ end
10
+
11
+ # Get the database comment (if any) defined for a table
12
+ #
13
+ # ==== Parameters
14
+ # table<~to_s>::
15
+ # The name of the table to get the comment for
16
+ #
17
+ # ==== Returns
18
+ # String:: The comment for the given table (or nil if no comment)
19
+ #
20
+ # :api: public
21
+ def comment table
22
+ adapter = adapter_name.downcase
23
+ database_specific_method_name = "#{ adapter }_comment"
24
+
25
+ if self.respond_to? database_specific_method_name
26
+ send database_specific_method_name, table.to_s
27
+ else
28
+
29
+ # try requiring 'activerecord-comments/[name-of-adapter]_adapter'
30
+ begin
31
+
32
+ # see if there right method exists after requiring
33
+ require "activerecord-comments/#{ adapter }_adapter"
34
+ if self.respond_to? database_specific_method_name
35
+ send database_specific_method_name, table.to_s
36
+ else
37
+ raise ActiveRecord::Comments::UnsupportedDatabase.new("#{adapter} unsupported by ActiveRecord::Comments")
38
+ end
39
+
40
+ rescue LoadError
41
+ raise ActiveRecord::Comments::UnsupportedDatabase.new("#{adapter} unsupported by ActiveRecord::Comments")
42
+ end
43
+ end
44
+ end
45
+
46
+ # Get the database comment (if any) defined for a column
47
+ #
48
+ # ==== Parameters
49
+ # column<~to_s>::
50
+ # The name of the column to get the comment for
51
+ #
52
+ # table<~to_s>::
53
+ # The name of the table to get the column comment for
54
+ #
55
+ # ==== Returns
56
+ # String:: The comment for the given column (or nil if no comment)
57
+ #
58
+ # :api: public
59
+ def column_comment column, table
60
+ adapter = adapter_name.downcase
61
+ database_specific_method_name = "#{ adapter }_column_comment"
62
+
63
+ if self.respond_to? database_specific_method_name
64
+ send database_specific_method_name, column.to_s, table.to_s
65
+ else
66
+
67
+ # try requiring 'activerecord-comments/[name-of-adapter]_adapter'
68
+ begin
69
+
70
+ # see if there right method exists after requiring
71
+ require "activerecord-comments/#{ adapter }_adapter"
72
+ if self.respond_to? database_specific_method_name
73
+ send database_specific_method_name, column.to_s, table.to_s
74
+ else
75
+ raise ActiveRecord::Comments::UnsupportedDatabase.new("#{adapter} unsupported by ActiveRecord::Comments")
76
+ end
77
+
78
+ rescue LoadError
79
+ raise ActiveRecord::Comments::UnsupportedDatabase.new("#{adapter} unsupported by ActiveRecord::Comments")
80
+ end
81
+ end
82
+ end
83
+
84
+ # Extends #columns, setting @table_name as an instance variable
85
+ # on each of the column instances that are returned
86
+ #
87
+ # ==== Returns
88
+ # Array[ActiveRecord::ConnectionAdapters::Column]::
89
+ # Returns an Array of column objects, each with @table_name set
90
+ #
91
+ # :api: private
92
+ def columns_with_table_name *args
93
+ puts "\n\n HELLO ???? HELLO ????? \n\n"
94
+ puts "asking adapter for columns for #{ args.inspect }"
95
+ columns = columns_without_table_name *args
96
+ table = self.table_name # make table_name available as variable in instanve_eval closure
97
+ columns.each do |column|
98
+ column.instance_eval { @table_name = table }
99
+ end
100
+ columns
101
+ end
102
+
103
+ end
@@ -25,32 +25,13 @@ module ActiveRecord::Comments::BaseExt
25
25
  #
26
26
  # :api: public
27
27
  def comment table = self.table_name
28
- adapter = connection.adapter_name.downcase
29
- database_specific_method_name = "#{ adapter }_comment"
30
-
31
- if self.respond_to? database_specific_method_name
32
- send database_specific_method_name, table.to_s
33
- else
34
-
35
- # try requiring 'activerecord-comments/[name-of-adapter]_adapter'
36
- begin
37
-
38
- # see if there right method exists after requiring
39
- require "activerecord-comments/#{ adapter }_adapter"
40
- if self.respond_to? database_specific_method_name
41
- send database_specific_method_name, table.to_s
42
- else
43
- raise ActiveRecord::Comments::UnsupportedDatabase.new("#{adapter} unsupported by ActiveRecord::Comments")
44
- end
45
-
46
- rescue LoadError
47
- raise ActiveRecord::Comments::UnsupportedDatabase.new("#{adapter} unsupported by ActiveRecord::Comments")
48
- end
49
- end
28
+ connection.comment table
50
29
  end
51
30
 
52
31
  # Get the database comment (if any) defined for a column
53
32
  #
33
+ # TODO move into adapter!
34
+ #
54
35
  # ==== Parameters
55
36
  # column<~to_s>::
56
37
  # The name of the column to get the comment for
@@ -65,28 +46,7 @@ module ActiveRecord::Comments::BaseExt
65
46
  #
66
47
  # :api: public
67
48
  def column_comment column, table = self.table_name
68
- adapter = connection.adapter_name.downcase
69
- database_specific_method_name = "#{ adapter }_column_comment"
70
-
71
- if self.respond_to? database_specific_method_name
72
- send database_specific_method_name, column.to_s, table.to_s
73
- else
74
-
75
- # try requiring 'activerecord-comments/[name-of-adapter]_adapter'
76
- begin
77
-
78
- # see if there right method exists after requiring
79
- require "activerecord-comments/#{ adapter }_adapter"
80
- if self.respond_to? database_specific_method_name
81
- send database_specific_method_name, column.to_s, table.to_s
82
- else
83
- raise ActiveRecord::Comments::UnsupportedDatabase.new("#{adapter} unsupported by ActiveRecord::Comments")
84
- end
85
-
86
- rescue LoadError
87
- raise ActiveRecord::Comments::UnsupportedDatabase.new("#{adapter} unsupported by ActiveRecord::Comments")
88
- end
89
- end
49
+ connection.column_comment column, table
90
50
  end
91
51
 
92
52
  # Extends ActiveRecord::Base#columns, setting @table_name as an instance variable
@@ -2,6 +2,7 @@ module ActiveRecord::Comments::ColumnExt
2
2
  attr_reader :table_name
3
3
 
4
4
  def comment
5
+ raise "table_name not set for column #{ self.inspect }" if table_name.nil? or table_name.empty?
5
6
  ActiveRecord::Base.column_comment name, table_name
6
7
  end
7
8
  end
@@ -70,3 +70,70 @@ module ActiveRecord::Comments::MysqlAdapter
70
70
  end
71
71
 
72
72
  ActiveRecord::Base.send :include, ActiveRecord::Comments::MysqlAdapter
73
+
74
+ ################ WE SHOULD DO EVERYTHING ON THE CONNECTION (ADAPTER) INSTEAD!!!!!!
75
+
76
+ module ActiveRecord::Comments::MysqlAdapterAdapter
77
+
78
+ # MySQL implementation of ActiveRecord::Comments::BaseExt#comment
79
+ def mysql_comment table
80
+ table_options = create_table_sql(table).split("\n").last
81
+ if table_options =~ /COMMENT='/
82
+ /COMMENT='(.*)'/.match(table_options).captures.first
83
+ else
84
+ nil
85
+ end
86
+ end
87
+
88
+ # MySQL implementation of ActiveRecord::Comments::BaseExt#column_comment
89
+ def mysql_column_comment column, table
90
+ column_creation_sql = create_column_sql(column, table)
91
+ if column_creation_sql =~ /COMMENT '/
92
+ /COMMENT '(.*)'/.match(column_creation_sql).captures.first
93
+ else
94
+ nil
95
+ end
96
+ end
97
+
98
+ private
99
+
100
+ # Returns the SQL used to create the given table
101
+ #
102
+ # ==== Parameters
103
+ # table<~to_s>::
104
+ # The name of the table to get the 'CREATE TABLE' SQL for
105
+ #
106
+ # ==== Returns
107
+ # String:: the SQL used to create the table
108
+ #
109
+ # :api: private
110
+ def create_table_sql table = table_name
111
+ execute("show create table `#{ table }`").all_hashes.first['Create Table']
112
+ end
113
+
114
+ # Returns the SQL used to create the given column for the given table
115
+ #
116
+ # ==== Parameters
117
+ # column<~to_s>::
118
+ # The name of the column to get the creation SQL for
119
+ #
120
+ # table<~to_s>::
121
+ # The name of the table to get the 'CREATE TABLE' SQL for
122
+ #
123
+ # ==== Returns
124
+ # String:: the SQL used to create the column
125
+ #
126
+ # :api: private
127
+ def create_column_sql column, table = table_name
128
+ full_table_create_sql = create_table_sql(table)
129
+ parts = full_table_create_sql.split("\n")
130
+ create_table = parts.shift # take off the first CREATE TABLE part
131
+ create_table_options = parts.pop # take off the last options for the table, leaving just the columns
132
+ sql_for_this_column = parts.find {|str| str =~ /^ *`#{ column }`/ }
133
+ sql_for_this_column.strip! if sql_for_this_column
134
+ sql_for_this_column
135
+ end
136
+
137
+ end
138
+
139
+ ActiveRecord::ConnectionAdapters::AbstractAdapter.send :include, ActiveRecord::Comments::MysqlAdapterAdapter
@@ -12,14 +12,18 @@ if defined?(ActiveRecord)
12
12
 
13
13
  end
14
14
 
15
- if defined?(ActiveRecord::Base) && defined?(ActiveRecord::ConnectionAdapters::Column)
15
+ if defined?(ActiveRecord::Base) &&
16
+ defined?(ActiveRecord::ConnectionAdapters::Column) &&
17
+ defined?(ActiveRecord::ConnectionAdapters::AbstractAdapter)
16
18
 
17
19
  # require and include our modules which add the 'comment' functionality to ActiveRecord
18
20
 
19
21
  require 'activerecord-comments/base_ext'
20
22
  require 'activerecord-comments/column_ext'
23
+ require 'activerecord-comments/abstract_adapter_ext'
21
24
 
22
- ActiveRecord::Base.send :include, ActiveRecord::Comments::BaseExt
23
- ActiveRecord::ConnectionAdapters::Column.send :include, ActiveRecord::Comments::ColumnExt
25
+ ActiveRecord::Base.send :include, ActiveRecord::Comments::BaseExt
26
+ ActiveRecord::ConnectionAdapters::Column.send :include, ActiveRecord::Comments::ColumnExt
27
+ ActiveRecord::ConnectionAdapters::AbstractAdapter.send :include, ActiveRecord::Comments::AbstractAdapterExt
24
28
 
25
29
  end
@@ -1,6 +1,6 @@
1
1
  require File.dirname(__FILE__) + '/spec_helper'
2
2
 
3
- describe ActiveRecord::Comments, 'MySQL support' do
3
+ describe ActiveRecord::Comments, 'MySQL' do
4
4
 
5
5
  # HELPERS
6
6
 
@@ -19,58 +19,91 @@ describe ActiveRecord::Comments, 'MySQL support' do
19
19
 
20
20
  # EXAMPLES
21
21
 
22
- it "should create table OK" do
23
- connection.execute "CREATE TABLE foxes( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY );"
24
- @foxes.count.should == 0
25
- end
22
+ describe ActiveRecord::Base, 'extensions' do
26
23
 
27
- it "Model#comment should return nil for a model that doesn't have a database comment" do
28
- connection.execute "CREATE TABLE foxes( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY );"
29
- @foxes.comment.should be_nil
30
- ActiveRecord::Base.comment(:foxes).should be_nil
31
- ActiveRecord::Base.comment('foxes').should be_nil
32
- end
24
+ it "should create table OK" do
25
+ connection.execute "CREATE TABLE foxes( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY );"
26
+ @foxes.count.should == 0
27
+ end
33
28
 
34
- it "Model#comment should return the database comment for a model that has a database comment" do
35
- connection.execute "CREATE TABLE foxes( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY ) COMMENT 'foxes Rule';"
36
- @foxes.comment.should == 'foxes Rule'
37
- ActiveRecord::Base.comment(:foxes).should == 'foxes Rule'
38
- ActiveRecord::Base.comment('foxes').should == 'foxes Rule'
39
- end
29
+ it "Model#comment should return nil for a model that doesn't have a database comment" do
30
+ connection.execute "CREATE TABLE foxes( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY );"
31
+ @foxes.comment.should be_nil
32
+ ActiveRecord::Base.comment(:foxes).should be_nil
33
+ ActiveRecord::Base.comment('foxes').should be_nil
34
+ end
40
35
 
41
- it "Model#comment should return the database comment for a model that has a database comment in different formats" do
42
- pending
43
- #[ 'foxes Rule', 'i has Numbers123', 'i have " double " quotes', "i have ' single quotes'" ].each do
44
- # connection.execute "CREATE TABLE foxes( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY ) COMMENT 'foxes Rule';"
45
- #@foxes.comment.should == 'foxes Rule'
46
- end
36
+ it "Model#comment should return the database comment for a model that has a database comment" do
37
+ connection.execute "CREATE TABLE foxes( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY ) COMMENT 'foxes Rule';"
38
+ @foxes.comment.should == 'foxes Rule'
39
+ ActiveRecord::Base.comment(:foxes).should == 'foxes Rule'
40
+ ActiveRecord::Base.comment('foxes').should == 'foxes Rule'
41
+ end
47
42
 
48
- it 'Model#column_comment should return the comment for a column' do
49
- connection.execute "CREATE TABLE foxes( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT 'i am the ID column' );"
50
- @foxes.column_comment('id').should == 'i am the ID column'
51
- @foxes.column_comment(:id).should == 'i am the ID column'
52
- ActiveRecord::Base.column_comment(:id, :foxes).should == 'i am the ID column'
53
- ActiveRecord::Base.column_comment(:id, 'foxes').should == 'i am the ID column'
54
- ActiveRecord::Base.column_comment('id', 'foxes').should == 'i am the ID column'
55
- end
43
+ it "Model#comment should return the database comment for a model that has a database comment in different formats" do
44
+ pending
45
+ #[ 'foxes Rule', 'i has Numbers123', 'i have " double " quotes', "i have ' single quotes'" ].each do
46
+ # connection.execute "CREATE TABLE foxes( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY ) COMMENT 'foxes Rule';"
47
+ #@foxes.comment.should == 'foxes Rule'
48
+ end
56
49
 
57
- it "@column#comment should return nil for a column that doesn't have a database comment" do
58
- connection.execute "CREATE TABLE foxes( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY );"
59
- @foxes.columns.first.name.should == 'id'
60
- @foxes.columns.first.comment.should be_nil
61
50
  end
62
51
 
63
- # need to add this extension (tho it's yucky) so a column can easily find its comment (needs its table name)
64
- it "@column should know its #table_name" do
65
- connection.execute "CREATE TABLE foxes( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY );"
66
- @foxes.columns.length.should == 1
67
- @foxes.columns.first.table_name.should == 'foxes'
52
+ describe ActiveRecord::ConnectionAdapters::Column, 'extensions' do
53
+
54
+ it 'Model#column_comment should return the comment for a column' do
55
+ connection.execute "CREATE TABLE foxes( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT 'i am the ID column' );"
56
+ @foxes.column_comment('id').should == 'i am the ID column'
57
+ @foxes.column_comment(:id).should == 'i am the ID column'
58
+ ActiveRecord::Base.column_comment(:id, :foxes).should == 'i am the ID column'
59
+ ActiveRecord::Base.column_comment(:id, 'foxes').should == 'i am the ID column'
60
+ ActiveRecord::Base.column_comment('id', 'foxes').should == 'i am the ID column'
61
+ end
62
+
63
+ it "@column#comment should return nil for a column that doesn't have a database comment" do
64
+ connection.execute "CREATE TABLE foxes( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY );"
65
+ @foxes.columns.first.name.should == 'id'
66
+ @foxes.columns.first.comment.should be_nil
67
+ end
68
+
69
+ # need to add this extension (tho it's yucky) so a column can easily find its comment (needs its table name)
70
+ it "@column should know its #table_name" do
71
+ connection.execute "CREATE TABLE foxes( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY );"
72
+ @foxes.columns.length.should == 1
73
+ @foxes.columns.first.table_name.should == 'foxes'
74
+ end
75
+
76
+ it "@column#comment should return the database comment for a column that has a database comment" do
77
+ connection.execute "CREATE TABLE foxes( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT 'i am the ID column' );"
78
+ @foxes.columns.first.name.should == 'id'
79
+ @foxes.columns.first.comment.should == 'i am the ID column'
80
+ end
81
+
68
82
  end
69
83
 
70
- it "@column#comment should return the database comment for a column that has a database comment" do
71
- connection.execute "CREATE TABLE foxes( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT 'i am the ID column' );"
72
- @foxes.columns.first.name.should == 'id'
73
- @foxes.columns.first.comment.should == 'i am the ID column'
84
+ describe 'Connection', 'extensions' do
85
+
86
+ it "@connection#comment(table) should return the database comment for a table that has a database comment" do
87
+ connection.execute "CREATE TABLE foxes( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY ) COMMENT 'foxes Rule';"
88
+ connection.comment('foxes').should == 'foxes Rule'
89
+ connection.comment(:foxes).should == 'foxes Rule'
90
+ end
91
+
92
+ it "@connection.columns(table) should inject the table name to column objects" do
93
+ pending "Not implementing this (for now?)"
94
+ connection.execute "CREATE TABLE foxes( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT 'i am the ID column' );"
95
+ connection.columns(:foxes).length.should == 1
96
+ connection.columns(:foxes).first.name.should == 'id'
97
+ connection.columns(:foxes).first.comment.should == 'i am the ID column'
98
+ end
99
+
100
+ it "@connection#column_comment should return the database comment for a column that has a database comment" do
101
+ connection.execute "CREATE TABLE foxes( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT 'i am the ID column' );"
102
+ connection.column_comment(:id, :foxes).should == 'i am the ID column'
103
+ connection.column_comment('id', :foxes).should == 'i am the ID column'
104
+ connection.column_comment('id', 'foxes').should == 'i am the ID column'
105
+ end
106
+
74
107
  end
75
108
 
76
109
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: remi-activerecord-comments
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - remi
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-02-02 00:00:00 -08:00
12
+ date: 2009-02-03 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -27,6 +27,7 @@ files:
27
27
  - lib/activerecord-comments
28
28
  - lib/activerecord-comments/column_ext.rb
29
29
  - lib/activerecord-comments/mysql_adapter.rb
30
+ - lib/activerecord-comments/abstract_adapter_ext.rb
30
31
  - lib/activerecord-comments/base_ext.rb
31
32
  - lib/activerecord-comments.rb
32
33
  - spec/mysql_comments_spec.rb