composite_primary_keys 13.0.1 → 14.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/History.rdoc +8 -2
  3. data/README.rdoc +1 -0
  4. data/Rakefile +37 -37
  5. data/lib/composite_primary_keys/arel/sqlserver.rb +37 -37
  6. data/lib/composite_primary_keys/arel/to_sql.rb +18 -18
  7. data/lib/composite_primary_keys/associations/association.rb +23 -23
  8. data/lib/composite_primary_keys/associations/collection_association.rb +31 -31
  9. data/lib/composite_primary_keys/associations/foreign_association.rb +15 -15
  10. data/lib/composite_primary_keys/associations/has_many_association.rb +35 -35
  11. data/lib/composite_primary_keys/associations/preloader/association.rb +68 -53
  12. data/lib/composite_primary_keys/associations/through_association.rb +25 -25
  13. data/lib/composite_primary_keys/autosave_association.rb +60 -60
  14. data/lib/composite_primary_keys/composite_arrays.rb +86 -86
  15. data/lib/composite_primary_keys/composite_predicates.rb +71 -70
  16. data/lib/composite_primary_keys/composite_relation.rb +29 -29
  17. data/lib/composite_primary_keys/connection_adapters/abstract_adapter.rb +10 -10
  18. data/lib/composite_primary_keys/connection_adapters/postgresql/database_statements.rb +26 -26
  19. data/lib/composite_primary_keys/counter_cache.rb +15 -15
  20. data/lib/composite_primary_keys/fixtures.rb +21 -21
  21. data/lib/composite_primary_keys/persistence.rb +21 -7
  22. data/lib/composite_primary_keys/relation/calculations.rb +7 -1
  23. data/lib/composite_primary_keys/sanitization.rb +42 -42
  24. data/lib/composite_primary_keys/transactions.rb +34 -34
  25. data/lib/composite_primary_keys/validations/uniqueness.rb +31 -31
  26. data/lib/composite_primary_keys/version.rb +1 -1
  27. data/lib/composite_primary_keys.rb +1 -1
  28. data/scripts/console.rb +48 -48
  29. data/scripts/txt2html +76 -76
  30. data/scripts/txt2js +65 -65
  31. data/tasks/databases/mysql.rake +40 -40
  32. data/tasks/databases/oracle.rake +41 -41
  33. data/tasks/databases/postgresql.rake +38 -38
  34. data/tasks/databases/sqlite.rake +25 -25
  35. data/tasks/databases/sqlserver.rake +43 -43
  36. data/tasks/website.rake +18 -18
  37. data/test/README_tests.rdoc +56 -56
  38. data/test/abstract_unit.rb +5 -1
  39. data/test/connections/connection_spec.rb +27 -27
  40. data/test/connections/databases.example.yml +40 -40
  41. data/test/connections/databases.yml +40 -39
  42. data/test/fixtures/article.rb +10 -10
  43. data/test/fixtures/articles.yml +7 -7
  44. data/test/fixtures/capitol.rb +3 -3
  45. data/test/fixtures/capitols.yml +16 -16
  46. data/test/fixtures/comment.rb +5 -5
  47. data/test/fixtures/comments.yml +17 -17
  48. data/test/fixtures/dorm.rb +2 -2
  49. data/test/fixtures/dorms.yml +4 -4
  50. data/test/fixtures/employee.rb +5 -5
  51. data/test/fixtures/group.rb +2 -2
  52. data/test/fixtures/groups.yml +6 -6
  53. data/test/fixtures/membership_status.rb +2 -2
  54. data/test/fixtures/membership_statuses.yml +16 -16
  55. data/test/fixtures/memberships.yml +10 -10
  56. data/test/fixtures/product.rb +9 -9
  57. data/test/fixtures/product_tariff.rb +5 -5
  58. data/test/fixtures/product_tariffs.yml +14 -14
  59. data/test/fixtures/products.yml +11 -11
  60. data/test/fixtures/reading.rb +4 -4
  61. data/test/fixtures/readings.yml +10 -10
  62. data/test/fixtures/reference_code.rb +7 -7
  63. data/test/fixtures/reference_codes.yml +28 -28
  64. data/test/fixtures/reference_type.rb +12 -12
  65. data/test/fixtures/reference_types.yml +9 -9
  66. data/test/fixtures/restaurant.rb +9 -9
  67. data/test/fixtures/restaurants.yml +14 -14
  68. data/test/fixtures/restaurants_suburb.rb +2 -2
  69. data/test/fixtures/room.rb +11 -11
  70. data/test/fixtures/room_assignment.rb +13 -13
  71. data/test/fixtures/room_assignments.yml +24 -24
  72. data/test/fixtures/room_attribute.rb +2 -2
  73. data/test/fixtures/room_attribute_assignment.rb +4 -4
  74. data/test/fixtures/room_attribute_assignments.yml +4 -4
  75. data/test/fixtures/room_attributes.yml +2 -2
  76. data/test/fixtures/rooms.yml +12 -12
  77. data/test/fixtures/street.rb +2 -2
  78. data/test/fixtures/student.rb +3 -3
  79. data/test/fixtures/students.yml +15 -15
  80. data/test/fixtures/suburb.rb +5 -5
  81. data/test/fixtures/tariff.rb +5 -5
  82. data/test/fixtures/tariffs.yml +14 -14
  83. data/test/fixtures/topic_sources.yml +3 -3
  84. data/test/fixtures/topics.yml +8 -8
  85. data/test/fixtures/users.yml +10 -10
  86. data/test/plugins/pagination.rb +405 -405
  87. data/test/plugins/pagination_helper.rb +135 -135
  88. data/test/test_attribute_methods.rb +63 -63
  89. data/test/test_callbacks.rb +99 -99
  90. data/test/test_composite_arrays.rb +38 -38
  91. data/test/test_counter_cache.rb +30 -30
  92. data/test/test_dumpable.rb +15 -15
  93. data/test/test_dup.rb +37 -37
  94. data/test/test_equal.rb +26 -26
  95. data/test/test_habtm.rb +141 -141
  96. data/test/test_miscellaneous.rb +32 -32
  97. data/test/test_optimistic.rb +18 -18
  98. data/test/test_pagination.rb +35 -35
  99. data/test/test_polymorphic.rb +43 -43
  100. data/test/test_predicates.rb +59 -59
  101. data/test/test_preload.rb +102 -102
  102. data/test/test_santiago.rb +23 -23
  103. data/test/test_touch.rb +23 -23
  104. data/test/test_tutorial_example.rb +25 -25
  105. data/test/test_validations.rb +13 -13
  106. metadata +6 -6
@@ -30,11 +30,18 @@ module ActiveRecord
30
30
  end
31
31
  end
32
32
 
33
- constraints = _substitute_values(constraints).map { |attr, bind| attr.eq(bind) }
33
+ constraints = constraints.map { |name, value| predicate_builder[name, value] }
34
34
 
35
- um = arel_table.where(
36
- constraints.reduce(&:and)
37
- ).compile_update(_substitute_values(values), primary_key)
35
+ default_constraint = build_default_constraint
36
+ constraints << default_constraint if default_constraint
37
+
38
+ if current_scope = self.global_current_scope
39
+ constraints << current_scope.where_clause.ast
40
+ end
41
+
42
+ um = Arel::UpdateManager.new(arel_table)
43
+ um.set(values.transform_keys { |name| arel_table[name] })
44
+ um.wheres = constraints
38
45
 
39
46
  connection.update(um, "#{self} Update")
40
47
  end
@@ -48,10 +55,16 @@ module ActiveRecord
48
55
  end
49
56
  end
50
57
 
51
- constraints = _substitute_values(constraints).map { |attr, bind| attr.eq(bind) }
58
+ constraints = constraints.map { |name, value| predicate_builder[name, value] }
59
+
60
+ default_constraint = build_default_constraint
61
+ constraints << default_constraint if default_constraint
62
+
63
+ if current_scope = self.global_current_scope
64
+ constraints << current_scope.where_clause.ast
65
+ end
52
66
 
53
- dm = Arel::DeleteManager.new
54
- dm.from(arel_table)
67
+ dm = Arel::DeleteManager.new(arel_table)
55
68
  dm.wheres = constraints
56
69
 
57
70
  connection.delete(dm, "#{self} Destroy")
@@ -73,6 +86,7 @@ module ActiveRecord
73
86
  end
74
87
 
75
88
  @new_record = false
89
+ @previously_new_record = true
76
90
 
77
91
  yield(self) if block_given?
78
92
 
@@ -42,7 +42,13 @@ module CompositePrimaryKeys
42
42
 
43
43
  result = skip_query_cache_if_necessary { @klass.connection.select_all(query_builder) }
44
44
 
45
- type_cast_calculated_value(result.cast_values.first, operation) do |value|
45
+ if operation != "count"
46
+ type = column.try(:type_caster) ||
47
+ lookup_cast_type_from_join_dependencies(column_name.to_s) || ::ActiveRecord::Type.default_value
48
+ type = type.subtype if ::ActiveRecord::Enum::EnumType === type
49
+ end
50
+
51
+ type_cast_calculated_value(result.cast_values.first, operation, type) do |value|
46
52
  type = column.try(:type_caster) ||
47
53
  # CPK
48
54
  # lookup_cast_type_from_join_dependencies(column_name.to_s) || Type.default_value
@@ -1,43 +1,43 @@
1
- module ActiveRecord
2
- module Sanitization
3
- module ClassMethods
4
- # def expand_hash_conditions_for_aggregates(attrs)
5
- # expanded_attrs = {}
6
- # attrs.each do |attr, value|
7
- # # CPK
8
- # # if aggregation = reflect_on_aggregation(attr.to_sym)
9
- # if attr.is_a?(CompositePrimaryKeys::CompositeKeys)
10
- # value = value.split('/') if value.is_a?(String)
11
- # attr.each_with_index do |key,i|
12
- # expanded_attrs[key] = value.respond_to?(:flatten) ? value.flatten[i] : value
13
- # end
14
- # elsif aggregation = reflect_on_aggregation(attr.to_sym)
15
- # mapping = aggregation.mapping
16
- # mapping.each do |field_attr, aggregate_attr|
17
- # if mapping.size == 1 && !value.respond_to?(aggregate_attr)
18
- # expanded_attrs[field_attr] = value
19
- # else
20
- # expanded_attrs[field_attr] = value.send(aggregate_attr)
21
- # end
22
- # end
23
- # else
24
- # expanded_attrs[attr] = value
25
- # end
26
- # end
27
- # expanded_attrs
28
- # end
29
- #
30
- # def quoted_id
31
- # # CPK
32
- # # self.class.quote_value(@attributes[self.class.primary_key].value_for_database)
33
- # if self.composite?
34
- # [self.class.primary_keys, ids].transpose.map { |attr_name,id|
35
- # self.class.quote_value(@attributes[attr_name].value_for_database)
36
- # }
37
- # else
38
- # self.class.quote_value(@attributes[self.class.primary_key].value_for_database)
39
- # end
40
- # end
41
- end
42
- end
1
+ module ActiveRecord
2
+ module Sanitization
3
+ module ClassMethods
4
+ # def expand_hash_conditions_for_aggregates(attrs)
5
+ # expanded_attrs = {}
6
+ # attrs.each do |attr, value|
7
+ # # CPK
8
+ # # if aggregation = reflect_on_aggregation(attr.to_sym)
9
+ # if attr.is_a?(CompositePrimaryKeys::CompositeKeys)
10
+ # value = value.split('/') if value.is_a?(String)
11
+ # attr.each_with_index do |key,i|
12
+ # expanded_attrs[key] = value.respond_to?(:flatten) ? value.flatten[i] : value
13
+ # end
14
+ # elsif aggregation = reflect_on_aggregation(attr.to_sym)
15
+ # mapping = aggregation.mapping
16
+ # mapping.each do |field_attr, aggregate_attr|
17
+ # if mapping.size == 1 && !value.respond_to?(aggregate_attr)
18
+ # expanded_attrs[field_attr] = value
19
+ # else
20
+ # expanded_attrs[field_attr] = value.send(aggregate_attr)
21
+ # end
22
+ # end
23
+ # else
24
+ # expanded_attrs[attr] = value
25
+ # end
26
+ # end
27
+ # expanded_attrs
28
+ # end
29
+ #
30
+ # def quoted_id
31
+ # # CPK
32
+ # # self.class.quote_value(@attributes[self.class.primary_key].value_for_database)
33
+ # if self.composite?
34
+ # [self.class.primary_keys, ids].transpose.map { |attr_name,id|
35
+ # self.class.quote_value(@attributes[attr_name].value_for_database)
36
+ # }
37
+ # else
38
+ # self.class.quote_value(@attributes[self.class.primary_key].value_for_database)
39
+ # end
40
+ # end
41
+ end
42
+ end
43
43
  end
@@ -1,34 +1,34 @@
1
- module ActiveRecord
2
- module Transactions
3
- # Restore the new record state and id of a record that was previously saved by a call to save_record_state.
4
- def restore_transaction_record_state(force_restore_state = false)
5
- if restore_state = @_start_transaction_state
6
- if force_restore_state || restore_state[:level] <= 1
7
- @new_record = restore_state[:new_record]
8
- @destroyed = restore_state[:destroyed]
9
- @attributes = restore_state[:attributes].map do |attr|
10
- value = @attributes.fetch_value(attr.name)
11
- attr = attr.with_value_from_user(value) if attr.value != value
12
- attr
13
- end
14
- @mutations_from_database = nil
15
- @mutations_before_last_save = nil
16
-
17
- # CPK
18
- if self.composite?
19
- values = @primary_key.map {|attribute| @attributes.fetch_value(attribute)}
20
- restore_id = restore_state[:id]
21
- if values != restore_id
22
- @primary_key.each_with_index do |attribute, i|
23
- @attributes.write_from_user(attribute, restore_id[i])
24
- end
25
- end
26
- elsif @attributes.fetch_value(@primary_key) != restore_state[:id]
27
- @attributes.write_from_user(@primary_key, restore_state[:id])
28
- end
29
- freeze if restore_state[:frozen?]
30
- end
31
- end
32
- end
33
- end
34
- end
1
+ module ActiveRecord
2
+ module Transactions
3
+ # Restore the new record state and id of a record that was previously saved by a call to save_record_state.
4
+ def restore_transaction_record_state(force_restore_state = false)
5
+ if restore_state = @_start_transaction_state
6
+ if force_restore_state || restore_state[:level] <= 1
7
+ @new_record = restore_state[:new_record]
8
+ @destroyed = restore_state[:destroyed]
9
+ @attributes = restore_state[:attributes].map do |attr|
10
+ value = @attributes.fetch_value(attr.name)
11
+ attr = attr.with_value_from_user(value) if attr.value != value
12
+ attr
13
+ end
14
+ @mutations_from_database = nil
15
+ @mutations_before_last_save = nil
16
+
17
+ # CPK
18
+ if self.composite?
19
+ values = @primary_key.map {|attribute| @attributes.fetch_value(attribute)}
20
+ restore_id = restore_state[:id]
21
+ if values != restore_id
22
+ @primary_key.each_with_index do |attribute, i|
23
+ @attributes.write_from_user(attribute, restore_id[i])
24
+ end
25
+ end
26
+ elsif @attributes.fetch_value(@primary_key) != restore_state[:id]
27
+ @attributes.write_from_user(@primary_key, restore_state[:id])
28
+ end
29
+ freeze if restore_state[:frozen?]
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -1,32 +1,32 @@
1
- module ActiveRecord
2
- module Validations
3
- class UniquenessValidator
4
- def validate_each(record, attribute, value)
5
- finder_class = find_finder_class_for(record)
6
- value = map_enum_attribute(finder_class, attribute, value)
7
-
8
- relation = build_relation(finder_class, attribute, value)
9
- if record.persisted?
10
- # CPK
11
- if finder_class.primary_key.is_a?(Array)
12
- predicate = finder_class.cpk_id_predicate(finder_class.arel_table, finder_class.primary_key, record.id_in_database || record.id)
13
- relation = relation.where.not(predicate)
14
- elsif finder_class.primary_key
15
- relation = relation.where.not(finder_class.primary_key => record.id_in_database)
16
- else
17
- raise UnknownPrimaryKey.new(finder_class, "Can not validate uniqueness for persisted record without primary key.")
18
- end
19
- end
20
- relation = scope_relation(record, relation)
21
- relation = relation.merge(options[:conditions]) if options[:conditions]
22
-
23
- if relation.exists?
24
- error_options = options.except(:case_sensitive, :scope, :conditions)
25
- error_options[:value] = value
26
-
27
- record.errors.add(attribute, :taken, **error_options)
28
- end
29
- end
30
- end
31
- end
1
+ module ActiveRecord
2
+ module Validations
3
+ class UniquenessValidator
4
+ def validate_each(record, attribute, value)
5
+ finder_class = find_finder_class_for(record)
6
+ value = map_enum_attribute(finder_class, attribute, value)
7
+
8
+ relation = build_relation(finder_class, attribute, value)
9
+ if record.persisted?
10
+ # CPK
11
+ if finder_class.primary_key.is_a?(Array)
12
+ predicate = finder_class.cpk_id_predicate(finder_class.arel_table, finder_class.primary_key, record.id_in_database || record.id)
13
+ relation = relation.where.not(predicate)
14
+ elsif finder_class.primary_key
15
+ relation = relation.where.not(finder_class.primary_key => record.id_in_database)
16
+ else
17
+ raise UnknownPrimaryKey.new(finder_class, "Can not validate uniqueness for persisted record without primary key.")
18
+ end
19
+ end
20
+ relation = scope_relation(record, relation)
21
+ relation = relation.merge(options[:conditions]) if options[:conditions]
22
+
23
+ if relation.exists?
24
+ error_options = options.except(:case_sensitive, :scope, :conditions)
25
+ error_options[:value] = value
26
+
27
+ record.errors.add(attribute, :taken, **error_options)
28
+ end
29
+ end
30
+ end
31
+ end
32
32
  end
@@ -1,6 +1,6 @@
1
1
  module CompositePrimaryKeys
2
2
  module VERSION
3
- MAJOR = 13
3
+ MAJOR = 14
4
4
  MINOR = 0
5
5
  TINY = 1
6
6
  STRING = [MAJOR, MINOR, TINY].join('.')
@@ -23,7 +23,7 @@
23
23
 
24
24
  unless defined?(ActiveRecord)
25
25
  require 'rubygems'
26
- gem 'activerecord', '~>6.1.0'
26
+ gem 'activerecord', '~>7.0.0', '>= 7.0.1'
27
27
  require 'active_record'
28
28
  end
29
29
 
data/scripts/console.rb CHANGED
@@ -1,48 +1,48 @@
1
- #!/usr/bin/env ruby
2
-
3
- #
4
- # if run as script, load the file as library while starting irb
5
- #
6
- if __FILE__ == $0
7
- irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
8
- ENV['ADAPTER'] = ARGV[0]
9
- exec "#{irb} -f -r #{$0} --simple-prompt"
10
- end
11
-
12
- #
13
- # check if the given adapter is supported (default: mysql)
14
- #
15
- adapters = %w[mysql sqlite oracle oracle_enhanced postgresql ibm_db]
16
- adapter = ENV['ADAPTER'] || 'mysql'
17
- unless adapters.include? adapter
18
- puts "Usage: #{__FILE__} <adapter>"
19
- puts ''
20
- puts 'Adapters: '
21
- puts adapters.map{ |adapter| " #{adapter}" }.join("\n")
22
- exit 1
23
- end
24
-
25
- #
26
- # load all necessary libraries
27
- #
28
- require 'rubygems'
29
- require 'local/database_connections'
30
-
31
- $LOAD_PATH.unshift 'lib'
32
-
33
- begin
34
- require 'local/paths'
35
- $LOAD_PATH.unshift "#{ENV['EDGE_RAILS_DIR']}/active_record/lib" if ENV['EDGE_RAILS_DIR']
36
- $LOAD_PATH.unshift "#{ENV['EDGE_RAILS_DIR']}/activesupport/lib" if ENV['EDGE_RAILS_DIR']
37
- rescue
38
- end
39
-
40
- require 'active_support'
41
- require 'active_record'
42
-
43
- require "test/connections/native_#{adapter}/connection"
44
- require 'composite_primary_keys'
45
-
46
- PROJECT_ROOT = File.join(File.dirname(__FILE__), '..')
47
- Dir[File.join(PROJECT_ROOT,'test/fixtures/*.rb')].each { |model| require model }
48
-
1
+ #!/usr/bin/env ruby
2
+
3
+ #
4
+ # if run as script, load the file as library while starting irb
5
+ #
6
+ if __FILE__ == $0
7
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
8
+ ENV['ADAPTER'] = ARGV[0]
9
+ exec "#{irb} -f -r #{$0} --simple-prompt"
10
+ end
11
+
12
+ #
13
+ # check if the given adapter is supported (default: mysql)
14
+ #
15
+ adapters = %w[mysql sqlite oracle oracle_enhanced postgresql ibm_db]
16
+ adapter = ENV['ADAPTER'] || 'mysql'
17
+ unless adapters.include? adapter
18
+ puts "Usage: #{__FILE__} <adapter>"
19
+ puts ''
20
+ puts 'Adapters: '
21
+ puts adapters.map{ |adapter| " #{adapter}" }.join("\n")
22
+ exit 1
23
+ end
24
+
25
+ #
26
+ # load all necessary libraries
27
+ #
28
+ require 'rubygems'
29
+ require 'local/database_connections'
30
+
31
+ $LOAD_PATH.unshift 'lib'
32
+
33
+ begin
34
+ require 'local/paths'
35
+ $LOAD_PATH.unshift "#{ENV['EDGE_RAILS_DIR']}/active_record/lib" if ENV['EDGE_RAILS_DIR']
36
+ $LOAD_PATH.unshift "#{ENV['EDGE_RAILS_DIR']}/activesupport/lib" if ENV['EDGE_RAILS_DIR']
37
+ rescue
38
+ end
39
+
40
+ require 'active_support'
41
+ require 'active_record'
42
+
43
+ require "test/connections/native_#{adapter}/connection"
44
+ require 'composite_primary_keys'
45
+
46
+ PROJECT_ROOT = File.join(File.dirname(__FILE__), '..')
47
+ Dir[File.join(PROJECT_ROOT,'test/fixtures/*.rb')].each { |model| require model }
48
+
data/scripts/txt2html CHANGED
@@ -1,76 +1,76 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'rubygems'
4
- gem 'RedCloth'
5
- gem 'syntax'
6
-
7
- require 'redcloth'
8
- require 'syntax/convertors/html'
9
- require 'erb'
10
-
11
- version_path = File.join(File.dirname(__FILE__), '..', 'lib', 'composite_primary_keys', 'version.rb')
12
- require File.expand_path(version_path)
13
-
14
- version = CompositePrimaryKeys::VERSION::STRING
15
- download = 'http://rubygems.org/gems/composite_primary_keys'
16
-
17
- class Fixnum
18
- def ordinal
19
- # teens
20
- return 'th' if (10..19).include?(self % 100)
21
- # others
22
- case self % 10
23
- when 1
24
- return 'st'
25
- when 2
26
- return 'nd'
27
- when 3
28
- return 'rd'
29
- else
30
- return 'th'
31
- end
32
- end
33
- end
34
-
35
- class Time
36
- def pretty
37
- return "#{mday}#{mday.ordinal} #{strftime('%B')} #{year}"
38
- end
39
- end
40
-
41
- def convert_syntax(syntax, source)
42
- return Syntax::Convertors::HTML.for_syntax(syntax).convert(source).gsub(%r!^<pre>|</pre>$!,'')
43
- end
44
-
45
- if ARGV.length >= 1
46
- src, template = ARGV
47
- template ||= File.dirname(__FILE__) + '/../website/template.rhtml'
48
-
49
- else
50
- puts("Usage: #{File.split($0).last} source.txt [template.rhtml] > output.html")
51
- exit!
52
- end
53
-
54
- template = ERB.new(File.open(template).read)
55
-
56
- title = nil
57
- body = nil
58
- File.open(src) do |fsrc|
59
- title_text = fsrc.readline
60
- body_text = fsrc.read
61
- syntax_items = []
62
- body_text.gsub!(%r!<(pre|code)[^>]*?syntax=['"]([^'"]+)[^>]*>(.*?)</\1>!m){
63
- ident = syntax_items.length
64
- element, syntax, source = $1, $2, $3
65
- syntax_items << "<#{element} class=\"syntax\">#{convert_syntax(syntax, source)}</#{element}>"
66
- "syntax-temp-#{ident}"
67
- }
68
- title = RedCloth.new(title_text).to_html.gsub(%r!<.*?>!,'').strip
69
- body = RedCloth.new(body_text).to_html
70
- body.gsub!(%r!(?:<pre><code>)?syntax-temp-(\d+)(?:</code></pre>)?!){ syntax_items[$1.to_i] }
71
- end
72
- stat = File.stat(src)
73
- created = stat.ctime
74
- modified = stat.mtime
75
-
76
- $stdout << template.result(binding)
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ gem 'RedCloth'
5
+ gem 'syntax'
6
+
7
+ require 'redcloth'
8
+ require 'syntax/convertors/html'
9
+ require 'erb'
10
+
11
+ version_path = File.join(File.dirname(__FILE__), '..', 'lib', 'composite_primary_keys', 'version.rb')
12
+ require File.expand_path(version_path)
13
+
14
+ version = CompositePrimaryKeys::VERSION::STRING
15
+ download = 'http://rubygems.org/gems/composite_primary_keys'
16
+
17
+ class Fixnum
18
+ def ordinal
19
+ # teens
20
+ return 'th' if (10..19).include?(self % 100)
21
+ # others
22
+ case self % 10
23
+ when 1
24
+ return 'st'
25
+ when 2
26
+ return 'nd'
27
+ when 3
28
+ return 'rd'
29
+ else
30
+ return 'th'
31
+ end
32
+ end
33
+ end
34
+
35
+ class Time
36
+ def pretty
37
+ return "#{mday}#{mday.ordinal} #{strftime('%B')} #{year}"
38
+ end
39
+ end
40
+
41
+ def convert_syntax(syntax, source)
42
+ return Syntax::Convertors::HTML.for_syntax(syntax).convert(source).gsub(%r!^<pre>|</pre>$!,'')
43
+ end
44
+
45
+ if ARGV.length >= 1
46
+ src, template = ARGV
47
+ template ||= File.dirname(__FILE__) + '/../website/template.rhtml'
48
+
49
+ else
50
+ puts("Usage: #{File.split($0).last} source.txt [template.rhtml] > output.html")
51
+ exit!
52
+ end
53
+
54
+ template = ERB.new(File.open(template).read)
55
+
56
+ title = nil
57
+ body = nil
58
+ File.open(src) do |fsrc|
59
+ title_text = fsrc.readline
60
+ body_text = fsrc.read
61
+ syntax_items = []
62
+ body_text.gsub!(%r!<(pre|code)[^>]*?syntax=['"]([^'"]+)[^>]*>(.*?)</\1>!m){
63
+ ident = syntax_items.length
64
+ element, syntax, source = $1, $2, $3
65
+ syntax_items << "<#{element} class=\"syntax\">#{convert_syntax(syntax, source)}</#{element}>"
66
+ "syntax-temp-#{ident}"
67
+ }
68
+ title = RedCloth.new(title_text).to_html.gsub(%r!<.*?>!,'').strip
69
+ body = RedCloth.new(body_text).to_html
70
+ body.gsub!(%r!(?:<pre><code>)?syntax-temp-(\d+)(?:</code></pre>)?!){ syntax_items[$1.to_i] }
71
+ end
72
+ stat = File.stat(src)
73
+ created = stat.ctime
74
+ modified = stat.mtime
75
+
76
+ $stdout << template.result(binding)