composite_primary_keys 8.1.8 → 9.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (136) hide show
  1. checksums.yaml +5 -5
  2. data/History.rdoc +3 -25
  3. data/README.rdoc +1 -0
  4. data/README_DB2.rdoc +33 -33
  5. data/Rakefile +34 -34
  6. data/lib/composite_primary_keys.rb +4 -11
  7. data/lib/composite_primary_keys/associations/association.rb +14 -12
  8. data/lib/composite_primary_keys/associations/association_scope.rb +27 -54
  9. data/lib/composite_primary_keys/associations/collection_association.rb +22 -8
  10. data/lib/composite_primary_keys/associations/has_many_association.rb +16 -54
  11. data/lib/composite_primary_keys/associations/has_many_through_association.rb +58 -58
  12. data/lib/composite_primary_keys/associations/join_dependency.rb +74 -56
  13. data/lib/composite_primary_keys/associations/join_dependency/join_association.rb +13 -11
  14. data/lib/composite_primary_keys/associations/preloader/association.rb +75 -72
  15. data/lib/composite_primary_keys/associations/singular_association.rb +8 -12
  16. data/lib/composite_primary_keys/attribute_methods.rb +6 -4
  17. data/lib/composite_primary_keys/attribute_methods/primary_key.rb +13 -11
  18. data/lib/composite_primary_keys/attribute_methods/read.rb +16 -15
  19. data/lib/composite_primary_keys/attribute_methods/write.rb +21 -19
  20. data/lib/composite_primary_keys/attribute_set/builder.rb +13 -11
  21. data/lib/composite_primary_keys/base.rb +5 -69
  22. data/lib/composite_primary_keys/composite_arrays.rb +8 -51
  23. data/lib/composite_primary_keys/composite_predicates.rb +7 -16
  24. data/lib/composite_primary_keys/connection_adapters/abstract_adapter.rb +10 -10
  25. data/lib/composite_primary_keys/connection_adapters/postgresql_adapter.rb +42 -11
  26. data/lib/composite_primary_keys/core.rb +46 -45
  27. data/lib/composite_primary_keys/dirty.rb +19 -19
  28. data/lib/composite_primary_keys/fixtures.rb +19 -17
  29. data/lib/composite_primary_keys/locking/optimistic.rb +48 -44
  30. data/lib/composite_primary_keys/nested_attributes.rb +64 -53
  31. data/lib/composite_primary_keys/persistence.rb +49 -41
  32. data/lib/composite_primary_keys/relation.rb +22 -47
  33. data/lib/composite_primary_keys/relation/batches.rb +33 -30
  34. data/lib/composite_primary_keys/relation/calculations.rb +3 -7
  35. data/lib/composite_primary_keys/relation/finder_methods.rb +123 -56
  36. data/lib/composite_primary_keys/relation/predicate_builder.rb +18 -29
  37. data/lib/composite_primary_keys/relation/where_clause.rb +33 -0
  38. data/lib/composite_primary_keys/sanitization.rb +45 -38
  39. data/lib/composite_primary_keys/validations/uniqueness.rb +37 -37
  40. data/lib/composite_primary_keys/version.rb +4 -4
  41. data/scripts/console.rb +48 -48
  42. data/scripts/txt2html +76 -76
  43. data/scripts/txt2js +65 -65
  44. data/tasks/databases/mysql.rake +42 -42
  45. data/tasks/databases/postgresql.rake +47 -47
  46. data/tasks/databases/sqlite3.rake +27 -27
  47. data/tasks/website.rake +18 -18
  48. data/test/README_tests.rdoc +56 -56
  49. data/test/abstract_unit.rb +10 -9
  50. data/test/connections/connection_spec.rb +18 -18
  51. data/test/connections/databases.yml +9 -39
  52. data/test/connections/native_ibm_db/connection.rb +18 -18
  53. data/test/connections/native_mysql/connection.rb +17 -17
  54. data/test/connections/native_postgresql/connection.rb +12 -12
  55. data/test/connections/native_sqlite3/connection.rb +9 -9
  56. data/test/db_test.rb +52 -52
  57. data/test/fixtures/article.rb +5 -5
  58. data/test/fixtures/articles.yml +6 -6
  59. data/test/fixtures/capitol.rb +3 -3
  60. data/test/fixtures/capitols.yml +16 -16
  61. data/test/fixtures/comments.yml +15 -15
  62. data/test/fixtures/db_definitions/mysql.sql +2 -12
  63. data/test/fixtures/db_definitions/oracle.sql +1 -2
  64. data/test/fixtures/db_definitions/postgresql.sql +0 -10
  65. data/test/fixtures/db_definitions/sqlite.sql +0 -9
  66. data/test/fixtures/db_definitions/sqlserver.sql +1 -2
  67. data/test/fixtures/department.rb +5 -5
  68. data/test/fixtures/departments.yml +15 -15
  69. data/test/fixtures/dorms.yml +4 -4
  70. data/test/fixtures/employee.rb +1 -2
  71. data/test/fixtures/employees.yml +19 -23
  72. data/test/fixtures/group.rb +2 -2
  73. data/test/fixtures/groups.yml +6 -6
  74. data/test/fixtures/hack.rb +4 -4
  75. data/test/fixtures/hacks.yml +2 -2
  76. data/test/fixtures/membership_status.rb +2 -2
  77. data/test/fixtures/product.rb +9 -9
  78. data/test/fixtures/product_tariff.rb +5 -5
  79. data/test/fixtures/products.yml +11 -11
  80. data/test/fixtures/reading.rb +4 -4
  81. data/test/fixtures/readings.yml +10 -10
  82. data/test/fixtures/reference_code_using_composite_key_alias.rb +8 -8
  83. data/test/fixtures/reference_code_using_simple_key_alias.rb +8 -8
  84. data/test/fixtures/reference_codes.yml +28 -28
  85. data/test/fixtures/reference_type.rb +1 -1
  86. data/test/fixtures/reference_types.yml +9 -9
  87. data/test/fixtures/restaurant.rb +9 -9
  88. data/test/fixtures/restaurants.yml +14 -14
  89. data/test/fixtures/restaurants_suburbs.yml +10 -10
  90. data/test/fixtures/room.rb +11 -11
  91. data/test/fixtures/room_assignment.rb +13 -13
  92. data/test/fixtures/room_assignments.yml +24 -24
  93. data/test/fixtures/room_attribute.rb +2 -2
  94. data/test/fixtures/room_attribute_assignment.rb +4 -4
  95. data/test/fixtures/room_attribute_assignments.yml +4 -4
  96. data/test/fixtures/room_attributes.yml +2 -2
  97. data/test/fixtures/rooms.yml +12 -12
  98. data/test/fixtures/seat.rb +5 -5
  99. data/test/fixtures/seats.yml +8 -8
  100. data/test/fixtures/street.rb +2 -2
  101. data/test/fixtures/streets.yml +16 -16
  102. data/test/fixtures/student.rb +3 -3
  103. data/test/fixtures/students.yml +15 -15
  104. data/test/fixtures/suburbs.yml +14 -14
  105. data/test/fixtures/tariff.rb +5 -5
  106. data/test/fixtures/tariffs.yml +14 -14
  107. data/test/fixtures/user.rb +0 -1
  108. data/test/plugins/pagination.rb +405 -405
  109. data/test/plugins/pagination_helper.rb +135 -135
  110. data/test/setup.rb +50 -50
  111. data/test/test_aliases.rb +18 -18
  112. data/test/test_associations.rb +7 -18
  113. data/test/test_composite_arrays.rb +24 -38
  114. data/test/test_counter_cache.rb +30 -30
  115. data/test/test_create.rb +5 -5
  116. data/test/test_delete_all.rb +7 -13
  117. data/test/test_dup.rb +37 -37
  118. data/test/test_exists.rb +39 -39
  119. data/test/test_find.rb +16 -12
  120. data/test/test_habtm.rb +26 -2
  121. data/test/test_ids.rb +109 -116
  122. data/test/test_miscellaneous.rb +32 -32
  123. data/test/test_pagination.rb +35 -35
  124. data/test/test_polymorphic.rb +0 -7
  125. data/test/test_predicates.rb +9 -28
  126. data/test/test_update.rb +3 -5
  127. data/test/test_validations.rb +13 -13
  128. metadata +24 -32
  129. data/lib/composite_primary_keys/arel/visitors/to_sql.rb +0 -36
  130. data/lib/composite_primary_keys/attribute_methods/dirty.rb +0 -29
  131. data/lib/composite_primary_keys/autosave_association.rb +0 -67
  132. data/lib/composite_primary_keys/connection_adapters/abstract_mysql_adapter.rb +0 -23
  133. data/test/fixtures/pk_called_id.rb +0 -5
  134. data/test/fixtures/pk_called_ids.yml +0 -11
  135. data/test/test_find_in_batches.rb +0 -30
  136. data/test/test_update_all.rb +0 -17
@@ -1,37 +1,26 @@
1
1
  module ActiveRecord
2
2
  class PredicateBuilder
3
- def self.expand(klass, table, column, value)
4
- queries = []
5
-
6
- # Find the foreign key when using queries such as:
7
- # Post.where(author: author)
8
- #
9
- # For polymorphic relationships, find the foreign key and type:
10
- # PriceEstimate.where(estimate_of: treasure)
11
- if klass && reflection = klass._reflect_on_association(column)
12
- base_class = polymorphic_base_class_from_value(value)
13
-
14
- if reflection.polymorphic? && base_class
15
- queries << build(table[reflection.foreign_type], base_class)
16
- end
17
-
18
- column = reflection.foreign_key
3
+ silence_warnings do
4
+ def expand(column, value)
5
+ # Find the foreign key when using queries such as:
6
+ # Post.where(author: author)
7
+ #
8
+ # For polymorphic relationships, find the foreign key and type:
9
+ # PriceEstimate.where(estimate_of: treasure)
19
10
 
20
11
  # CPK
21
- # if base_class
22
- if base_class && !(Base === value && value.composite?)
23
- primary_key = reflection.association_primary_key(base_class)
24
- value = convert_value_to_association_ids(value, primary_key)
12
+ if Base === Array(value).first && Array(value).first.composite? && reflection = table.associated_with?(column)
13
+ columns = reflection.foreign_key
14
+ values = Array(value).map{|v| columns.map{|c| v.public_send(c) }}
15
+ cpk_predicate_builder = Class.new.extend(CompositePrimaryKeys::Predicates)
16
+ predicate = cpk_predicate_builder.cpk_in_predicate(table.send(:arel_table), columns, values)
17
+ return predicate
18
+ else
19
+ # Original code
20
+ value = AssociationQueryHandler.value_for(table, column, value) if table.associated_with?(column)
21
+ build(table.arel_attribute(column), value)
25
22
  end
26
23
  end
27
-
28
- #CPK
29
- if Base === value && value.composite?
30
- queries << cpk_id_predicate(table, column, value.id)
31
- else
32
- queries << build(table[column], value)
33
- end
34
- queries
35
24
  end
36
25
  end
37
- end
26
+ end
@@ -0,0 +1,33 @@
1
+ module ActiveRecord
2
+ class Relation
3
+ class WhereClause
4
+ silence_warnings do
5
+ def to_h(table_name = nil)
6
+ equalities = predicates.grep(Arel::Nodes::Equality)
7
+
8
+ # CPK Adds this line, because ours are coming in with AND->{EQUALITY, EQUALITY}
9
+ equalities = predicates.grep(Arel::Nodes::And).map(&:children).flatten.grep(Arel::Nodes::Equality) if equalities.empty?
10
+
11
+ if table_name
12
+ equalities = equalities.select do |node|
13
+ node.left.relation.name == table_name
14
+ end
15
+ end
16
+
17
+ binds = self.binds.map { |attr| [attr.name, attr.value] }.to_h
18
+
19
+ equalities.map do |node|
20
+ name = node.left.name
21
+ [name, binds.fetch(name.to_s) {
22
+ case node.right
23
+ when Array then node.right.map(&:val)
24
+ when Arel::Nodes::Casted, Arel::Nodes::Quoted
25
+ node.right.val
26
+ end
27
+ }]
28
+ end.to_h
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,54 +1,61 @@
1
1
  module ActiveRecord
2
2
  module Sanitization
3
3
  module ClassMethods
4
+
4
5
  protected
5
6
  # Accepts a hash of SQL conditions and replaces those attributes
6
- # that correspond to a +composed_of+ relationship with their expanded
7
- # aggregate attribute values.
7
+ # that correspond to a {#composed_of}[rdoc-ref:Aggregations::ClassMethods#composed_of]
8
+ # relationship with their expanded aggregate attribute values.
9
+ #
8
10
  # Given:
9
- # class Person < ActiveRecord::Base
10
- # composed_of :address, class_name: "Address",
11
- # mapping: [%w(address_street street), %w(address_city city)]
12
- # end
11
+ #
12
+ # class Person < ActiveRecord::Base
13
+ # composed_of :address, class_name: "Address",
14
+ # mapping: [%w(address_street street), %w(address_city city)]
15
+ # end
16
+ #
13
17
  # Then:
14
- # { address: Address.new("813 abc st.", "chicago") }
15
- # # => { address_street: "813 abc st.", address_city: "chicago" }
16
- def expand_hash_conditions_for_aggregates(attrs)
17
- expanded_attrs = {}
18
- attrs.each do |attr, value|
19
- # CPK
20
- # if aggregation = reflect_on_aggregation(attr.to_sym)
21
- if attr.is_a?(CompositePrimaryKeys::CompositeKeys)
22
- attr.each_with_index do |key,i|
23
- expanded_attrs[key] = value.respond_to?(:flatten) ? value.flatten[i] : value
24
- end
25
- elsif aggregation = reflect_on_aggregation(attr.to_sym)
26
- mapping = aggregation.mapping
27
- mapping.each do |field_attr, aggregate_attr|
28
- if mapping.size == 1 && !value.respond_to?(aggregate_attr)
29
- expanded_attrs[field_attr] = value
30
- else
31
- expanded_attrs[field_attr] = value.send(aggregate_attr)
18
+ #
19
+ # { address: Address.new("813 abc st.", "chicago") }
20
+ # # => { address_street: "813 abc st.", address_city: "chicago" }
21
+ silence_warnings do
22
+ def expand_hash_conditions_for_aggregates(attrs)
23
+ expanded_attrs = {}
24
+ attrs.each do |attr, value|
25
+ # CPK
26
+ # if aggregation = reflect_on_aggregation(attr.to_sym)
27
+ if attr.is_a?(CompositePrimaryKeys::CompositeKeys)
28
+ attr.each_with_index do |key,i|
29
+ expanded_attrs[key] = value.respond_to?(:flatten) ? value.flatten[i] : value
32
30
  end
31
+ elsif aggregation = reflect_on_aggregation(attr.to_sym)
32
+ mapping = aggregation.mapping
33
+ mapping.each do |field_attr, aggregate_attr|
34
+ if mapping.size == 1 && !value.respond_to?(aggregate_attr)
35
+ expanded_attrs[field_attr] = value
36
+ else
37
+ expanded_attrs[field_attr] = value.send(aggregate_attr)
38
+ end
39
+ end
40
+ else
41
+ expanded_attrs[attr] = value
33
42
  end
34
- else
35
- expanded_attrs[attr] = value
36
43
  end
44
+ expanded_attrs
37
45
  end
38
- expanded_attrs
39
- end
40
46
 
41
- def quoted_id
42
- # CPK
43
- # self.class.quote_value(id, column_for_attribute(self.class.primary_key))
44
- if self.composite?
45
- [self.class.primary_keys, ids].transpose.map { |attr_name,id|
46
- self.class.quote_value(id, column_for_attribute(attr_name))
47
- }
48
- else
49
- self.class.quote_value(id, column_for_attribute(self.class.primary_key))
47
+ def quoted_id
48
+ # CPK
49
+ # self.class.quote_value(@attributes[self.class.primary_key].value_for_database)
50
+ if self.composite?
51
+ [self.class.primary_keys, ids].transpose.map { |attr_name,id|
52
+ self.class.quote_value(@attributes[attr_name].value_for_database)
53
+ }
54
+ else
55
+ self.class.quote_value(@attributes[self.class.primary_key].value_for_database)
56
+ end
50
57
  end
51
58
  end
52
59
  end
53
60
  end
54
- end
61
+ end
@@ -1,41 +1,41 @@
1
1
  module ActiveRecord
2
2
  module Validations
3
- class UniquenessValidator
4
- def validate_each(record, attribute, value)
5
- finder_class = find_finder_class_for(record)
6
- table = finder_class.arel_table
7
- value = map_enum_attribute(finder_class, attribute, value)
8
-
9
- begin
10
- relation = build_relation(finder_class, table, attribute, value)
11
- # CPK
12
- # relation = relation.and(table[finder_class.primary_key.to_sym].not_eq(record.id)) if record.persisted?
13
- if record.persisted?
14
- not_eq_conditions = Array(finder_class.primary_key).zip(Array(record.send(:id))).map do |name, value|
15
- table[name.to_sym].not_eq(value)
16
- end
17
-
18
- condition = not_eq_conditions.shift
19
- not_eq_conditions.each do |not_eq_condition|
20
- condition = condition.or(not_eq_condition)
21
- end
22
- relation = relation.and(condition)
23
- end
24
- # End CPK
25
- relation = scope_relation(record, table, relation)
26
- relation = finder_class.unscoped.where(relation)
27
- relation = relation.merge(options[:conditions]) if options[:conditions]
28
- rescue RangeError
29
- relation = finder_class.none
30
- end
31
-
32
- if relation.exists?
33
- error_options = options.except(:case_sensitive, :scope, :conditions)
34
- error_options[:value] = value
35
-
36
- record.errors.add(attribute, :taken, error_options)
37
- end
38
- end
39
- end
3
+ # class UniquenessValidator
4
+ # def validate_each(record, attribute, value)
5
+ # finder_class = find_finder_class_for(record)
6
+ # table = finder_class.arel_table
7
+ # value = map_enum_attribute(finder_class, attribute, value)
8
+ #
9
+ # begin
10
+ # relation = build_relation(finder_class, table, attribute, value)
11
+ # # CPK
12
+ # # relation = relation.and(table[finder_class.primary_key.to_sym].not_eq(record.id)) if record.persisted?
13
+ # if record.persisted?
14
+ # not_eq_conditions = Array(finder_class.primary_key).zip(Array(record.send(:id))).map do |name, value|
15
+ # table[name.to_sym].not_eq(value)
16
+ # end
17
+ #
18
+ # condition = not_eq_conditions.shift
19
+ # not_eq_conditions.each do |not_eq_condition|
20
+ # condition = condition.or(not_eq_condition)
21
+ # end
22
+ # relation = relation.and(condition)
23
+ # end
24
+ # # End CPK
25
+ # relation = scope_relation(record, table, relation)
26
+ # relation = finder_class.unscoped.where(relation)
27
+ # relation = relation.merge(options[:conditions]) if options[:conditions]
28
+ # rescue RangeError
29
+ # relation = finder_class.none
30
+ # end
31
+ #
32
+ # if relation.exists?
33
+ # error_options = options.except(:case_sensitive, :scope, :conditions)
34
+ # error_options[:value] = value
35
+ #
36
+ # record.errors.add(attribute, :taken, error_options)
37
+ # end
38
+ # end
39
+ # end
40
40
  end
41
41
  end
@@ -1,8 +1,8 @@
1
1
  module CompositePrimaryKeys
2
2
  module VERSION
3
- MAJOR = 8
4
- MINOR = 1
5
- TINY = 8
6
- STRING = [MAJOR, MINOR, TINY].join('.')
3
+ MAJOR = 9
4
+ MINOR = 0
5
+ TINY = 0
6
+ STRING = [MAJOR, MINOR, TINY, 'beta1'].join('.')
7
7
  end
8
8
  end
@@ -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
+
@@ -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)