ar_loader 0.0.4 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +9 -9
- data/README.markdown +221 -210
- data/Rakefile +76 -76
- data/lib/VERSION +1 -1
- data/lib/ar_loader.rb +66 -53
- data/lib/engine/file_definitions.rb +353 -353
- data/lib/engine/jruby/jexcel_file.rb +181 -181
- data/lib/engine/jruby/method_mapper_excel.rb +43 -43
- data/lib/engine/mapping_file_definitions.rb +87 -87
- data/lib/engine/method_detail.rb +140 -139
- data/lib/engine/method_mapper.rb +156 -156
- data/lib/engine/method_mapper_csv.rb +27 -27
- data/lib/engine/word.rb +70 -70
- data/lib/loaders/loader_base.rb +73 -60
- data/lib/loaders/spree/image_loader.rb +41 -46
- data/lib/loaders/spree/product_loader.rb +91 -92
- data/lib/to_b.rb +24 -24
- data/spec/database.yml +6 -0
- data/spec/db/migrate/20110803201325_create_testbed.rb +25 -0
- data/spec/excel_loader_spec.rb +98 -137
- data/spec/spec_helper.rb +18 -36
- data/spec/spree_loader_spec.rb +158 -0
- data/tasks/{seed_fu_product_template.erb → config/seed_fu_product_template.erb} +15 -15
- data/tasks/{tidy_config.txt → config/tidy_config.txt} +12 -12
- data/tasks/db_tasks.rake +64 -64
- data/tasks/excel_loader.rake +113 -100
- data/tasks/file_tasks.rake +37 -37
- data/tasks/spree/image_load.rake +107 -102
- data/tasks/spree/product_loader.rake +107 -106
- data/tasks/word_to_seedfu.rake +166 -166
- metadata +61 -47
data/lib/engine/word.rb
CHANGED
@@ -1,70 +1,70 @@
|
|
1
|
-
# Author:: Tom Statter
|
2
|
-
# License:: MIT ?
|
3
|
-
#
|
4
|
-
# NOTES ON INVESTIGATING OLE METHODS in irb
|
5
|
-
#
|
6
|
-
# visible = @word_app.ole_method_help( 'Visible' ) # Get a Method Object
|
7
|
-
|
8
|
-
# log( visible.return_type_detail.to_s ) # => ["BOOL"]
|
9
|
-
# log( visible.invoke_kind.to_s ) # => "PROPERTYGET"
|
10
|
-
# log( visible.params.to_s ) # => []
|
11
|
-
|
12
|
-
# @fc.ole_method_help( 'Report' ).params[1].ole_type_detail
|
13
|
-
#
|
14
|
-
# prefs = @word_app.Preferences.Strings.ole_method_help( 'Set' ).params
|
15
|
-
# => [index, newVal]
|
16
|
-
#
|
17
|
-
# WORD_OLE_CONST.constants
|
18
|
-
#
|
19
|
-
# WORD_OLE_CONST.constants.sort.grep /CR/
|
20
|
-
# => ["ClHideCRLF", "LesCR", "LesCRLF"]
|
21
|
-
#
|
22
|
-
# WORD_OLE_CONST.const_get( 'LesCR' ) or WORD_OLE_CONST::LesCR
|
23
|
-
# => 1
|
24
|
-
require 'win32ole'
|
25
|
-
|
26
|
-
# Module for constants to be loaded int
|
27
|
-
|
28
|
-
module WORD_OLE_CONST
|
29
|
-
end
|
30
|
-
|
31
|
-
class Word
|
32
|
-
|
33
|
-
attr_reader :wd, :doc
|
34
|
-
|
35
|
-
def initialize( visible )
|
36
|
-
@wd = WIN32OLE.new('Word.Application')
|
37
|
-
|
38
|
-
WIN32OLE.const_load(@wd, WORD_OLE_CONST) if WORD_OLE_CONST.constants.empty?
|
39
|
-
|
40
|
-
@wd.Visible = visible
|
41
|
-
end
|
42
|
-
|
43
|
-
def open(file)
|
44
|
-
@doc = @wd.Documents.Open(file)
|
45
|
-
@doc
|
46
|
-
end
|
47
|
-
|
48
|
-
def save()
|
49
|
-
@doc.Save()
|
50
|
-
@doc
|
51
|
-
end
|
52
|
-
|
53
|
-
# Format : From WORD_OLE_CONST e.g WORD_OLE_CONST::WdFormatHTML
|
54
|
-
#
|
55
|
-
def save_as(name, format)
|
56
|
-
@doc.SaveAs(name, format)
|
57
|
-
return @doc
|
58
|
-
end
|
59
|
-
|
60
|
-
# WdFormatFilteredHTML
|
61
|
-
# WdFormatHTML
|
62
|
-
def save_as_html(name)
|
63
|
-
@doc.SaveAs(name, WORD_OLE_CONST::WdFormatHTML)
|
64
|
-
return @doc
|
65
|
-
end
|
66
|
-
|
67
|
-
def quit
|
68
|
-
@wd.quit()
|
69
|
-
end
|
70
|
-
end
|
1
|
+
# Author:: Tom Statter
|
2
|
+
# License:: MIT ?
|
3
|
+
#
|
4
|
+
# NOTES ON INVESTIGATING OLE METHODS in irb
|
5
|
+
#
|
6
|
+
# visible = @word_app.ole_method_help( 'Visible' ) # Get a Method Object
|
7
|
+
|
8
|
+
# log( visible.return_type_detail.to_s ) # => ["BOOL"]
|
9
|
+
# log( visible.invoke_kind.to_s ) # => "PROPERTYGET"
|
10
|
+
# log( visible.params.to_s ) # => []
|
11
|
+
|
12
|
+
# @fc.ole_method_help( 'Report' ).params[1].ole_type_detail
|
13
|
+
#
|
14
|
+
# prefs = @word_app.Preferences.Strings.ole_method_help( 'Set' ).params
|
15
|
+
# => [index, newVal]
|
16
|
+
#
|
17
|
+
# WORD_OLE_CONST.constants
|
18
|
+
#
|
19
|
+
# WORD_OLE_CONST.constants.sort.grep /CR/
|
20
|
+
# => ["ClHideCRLF", "LesCR", "LesCRLF"]
|
21
|
+
#
|
22
|
+
# WORD_OLE_CONST.const_get( 'LesCR' ) or WORD_OLE_CONST::LesCR
|
23
|
+
# => 1
|
24
|
+
require 'win32ole'
|
25
|
+
|
26
|
+
# Module for constants to be loaded int
|
27
|
+
|
28
|
+
module WORD_OLE_CONST
|
29
|
+
end
|
30
|
+
|
31
|
+
class Word
|
32
|
+
|
33
|
+
attr_reader :wd, :doc
|
34
|
+
|
35
|
+
def initialize( visible )
|
36
|
+
@wd = WIN32OLE.new('Word.Application')
|
37
|
+
|
38
|
+
WIN32OLE.const_load(@wd, WORD_OLE_CONST) if WORD_OLE_CONST.constants.empty?
|
39
|
+
|
40
|
+
@wd.Visible = visible
|
41
|
+
end
|
42
|
+
|
43
|
+
def open(file)
|
44
|
+
@doc = @wd.Documents.Open(file)
|
45
|
+
@doc
|
46
|
+
end
|
47
|
+
|
48
|
+
def save()
|
49
|
+
@doc.Save()
|
50
|
+
@doc
|
51
|
+
end
|
52
|
+
|
53
|
+
# Format : From WORD_OLE_CONST e.g WORD_OLE_CONST::WdFormatHTML
|
54
|
+
#
|
55
|
+
def save_as(name, format)
|
56
|
+
@doc.SaveAs(name, format)
|
57
|
+
return @doc
|
58
|
+
end
|
59
|
+
|
60
|
+
# WdFormatFilteredHTML
|
61
|
+
# WdFormatHTML
|
62
|
+
def save_as_html(name)
|
63
|
+
@doc.SaveAs(name, WORD_OLE_CONST::WdFormatHTML)
|
64
|
+
return @doc
|
65
|
+
end
|
66
|
+
|
67
|
+
def quit
|
68
|
+
@wd.quit()
|
69
|
+
end
|
70
|
+
end
|
data/lib/loaders/loader_base.rb
CHANGED
@@ -1,61 +1,74 @@
|
|
1
|
-
# Copyright:: (c) Autotelik Media Ltd 2011
|
2
|
-
# Author :: Tom Statter
|
3
|
-
# Date :: Aug 2010
|
4
|
-
# License:: MIT
|
5
|
-
#
|
6
|
-
class
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
1
|
+
# Copyright:: (c) Autotelik Media Ltd 2011
|
2
|
+
# Author :: Tom Statter
|
3
|
+
# Date :: Aug 2010
|
4
|
+
# License:: MIT
|
5
|
+
#
|
6
|
+
# Details:: Base class for loaders, providing a process hook which populates a model,
|
7
|
+
# based on a method map and supplied value from a file - i.e a single column/row's string value.
|
8
|
+
# Note that although a single column, the string can be formatted to contain multiple values.
|
9
|
+
#
|
10
|
+
# Tightly coupled with MethodMapper classes (in lib/engine) which contains full details of
|
11
|
+
# a file's column and it's correlated AR associations.
|
12
|
+
#
|
13
|
+
class LoaderBase
|
14
|
+
|
15
|
+
attr_accessor :load_object_class, :load_object, :value
|
16
|
+
|
17
|
+
# Enable single column (association) to contain multiple name/value sets in default form :
|
18
|
+
# Name1:value1, value2|Name2:value1, value2, value3|Name3:value1, value2
|
19
|
+
#
|
20
|
+
# E.G.
|
21
|
+
# Row for association could have a name (Size/Colour/Sex) with a set of values,
|
22
|
+
# and this combination can be expressed multiple times :
|
23
|
+
# Size:small,medium,large|Colour:red, green|Sex:Female
|
24
|
+
|
25
|
+
@@name_value_delim = ':'
|
26
|
+
@@multi_value_delim = ','
|
27
|
+
@@multi_assoc_delim = '|'
|
28
|
+
|
29
|
+
def self.set_name_value_delim(x) @@name_value_delim = x; end
|
30
|
+
def self.set_multi_value_delim(x) @@multi_value_delim = x; end
|
31
|
+
def self.set_multi_assoc_delim(x) @@multi_assoc_delim = x; end
|
32
|
+
|
33
|
+
def initialize(object_class, object = nil)
|
34
|
+
@load_object_class = object_class
|
35
|
+
@load_object = object || @load_object_class.new
|
36
|
+
end
|
37
|
+
|
38
|
+
def reset()
|
39
|
+
@load_object = @load_object_class.new
|
40
|
+
end
|
41
|
+
|
42
|
+
# What process a value string from a column.
|
43
|
+
# Assigning value(s) to correct association on @load_object.
|
44
|
+
# Method map represents a column from a file and it's correlated AR associations.
|
45
|
+
# Value string which may contain multiple values for a collection association.
|
46
|
+
#
|
47
|
+
def process(method_map, value)
|
48
|
+
#puts "INFO: LOADER BASE processing #{@load_object}"
|
49
|
+
@value = value
|
50
|
+
|
51
|
+
if(method_map.has_many && method_map.has_many_class && @value)
|
52
|
+
# The Generic handler for Associations
|
53
|
+
# The actual class of the association so we can find_or_create on it
|
54
|
+
assoc_class = method_map.has_many_class
|
55
|
+
|
56
|
+
puts "Processing Association: #{assoc_class} : #{@value}"
|
57
|
+
|
58
|
+
@value.split(@@multi_assoc_delim).collect do |lookup|
|
59
|
+
# TODO - Don't just rely on 'name' but try different finds as per MethodMappe::insistent_belongs_to ..
|
60
|
+
x = assoc_class.find(:first, :conditions => ['lower(name) LIKE ?', "%#{lookup.downcase}%"])
|
61
|
+
unless x
|
62
|
+
puts "WARNING: #{lookup} in #{assoc_class} NOT found - Not added to #{@load_object.class}"
|
63
|
+
next
|
64
|
+
end
|
65
|
+
@load_object.send( method_map.has_many ) << x
|
66
|
+
@load_object.save
|
67
|
+
end
|
68
|
+
else
|
69
|
+
# Nice n simple straight assignment to a column variable
|
70
|
+
method_map.assign(@load_object, @value) unless method_map.has_many
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
61
74
|
end
|
@@ -1,47 +1,42 @@
|
|
1
|
-
# Copyright:: (c) Autotelik Media Ltd 2011
|
2
|
-
# Author :: Tom Statter
|
3
|
-
# Date :: Jan 2011
|
4
|
-
# License:: MIT. Free, Open Source.
|
5
|
-
#
|
6
|
-
require 'loader_base'
|
7
|
-
|
8
|
-
class ImageLoader < LoaderBase
|
9
|
-
|
10
|
-
def initialize(image = nil)
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
@load_object.attachment.reprocess!
|
43
|
-
@load_object.viewable = record if record
|
44
|
-
|
45
|
-
puts @load_object.save ? "Success: Uploaded Image: #{@load_object.inspect}" : "ERROR : Problem saving to DB Image: #{@load_object}"
|
46
|
-
end
|
1
|
+
# Copyright:: (c) Autotelik Media Ltd 2011
|
2
|
+
# Author :: Tom Statter
|
3
|
+
# Date :: Jan 2011
|
4
|
+
# License:: MIT. Free, Open Source.
|
5
|
+
#
|
6
|
+
require 'loader_base'
|
7
|
+
|
8
|
+
class ImageLoader < LoaderBase
|
9
|
+
|
10
|
+
def initialize(klass = Image, image = nil)
|
11
|
+
super( klass, image )
|
12
|
+
raise "Failed to create Image for loading" unless @load_object
|
13
|
+
end
|
14
|
+
|
15
|
+
# Note the Spree Image model sets default storage path to
|
16
|
+
# => :path => ":rails_root/public/assets/products/:id/:style/:basename.:extension"
|
17
|
+
|
18
|
+
def process( image_path, record = nil)
|
19
|
+
|
20
|
+
unless File.exists?(image_path)
|
21
|
+
puts "ERROR : Invalid Path"
|
22
|
+
return
|
23
|
+
end
|
24
|
+
|
25
|
+
alt = (record and record.respond_to? :name) ? record.name : ""
|
26
|
+
|
27
|
+
@load_object.alt = alt
|
28
|
+
|
29
|
+
begin
|
30
|
+
@load_object.attachment = File.new(image_path, "r")
|
31
|
+
rescue => e
|
32
|
+
puts e.inspect
|
33
|
+
puts "ERROR : Failed to read image #{image_path}"
|
34
|
+
return
|
35
|
+
end
|
36
|
+
|
37
|
+
@load_object.attachment.reprocess!
|
38
|
+
@load_object.viewable = record if record
|
39
|
+
|
40
|
+
puts @load_object.save ? "Success: Uploaded Image: #{@load_object.inspect}" : "ERROR : Problem saving to DB Image: #{@load_object}"
|
41
|
+
end
|
47
42
|
end
|
@@ -1,93 +1,92 @@
|
|
1
|
-
# Copyright:: (c) Autotelik Media Ltd 2010
|
2
|
-
# Author :: Tom Statter
|
3
|
-
# Date :: Aug 2010
|
4
|
-
# License:: MIT ?
|
5
|
-
#
|
6
|
-
# Details:: Specific over-rides/additions to
|
7
|
-
#
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
#
|
20
|
-
#
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
option_types
|
34
|
-
|
35
|
-
|
36
|
-
option_type
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
ovalues
|
46
|
-
|
47
|
-
ovname
|
48
|
-
ov
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
#
|
61
|
-
#
|
62
|
-
#
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
property
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
end
|
1
|
+
# Copyright:: (c) Autotelik Media Ltd 2010
|
2
|
+
# Author :: Tom Statter
|
3
|
+
# Date :: Aug 2010
|
4
|
+
# License:: MIT ?
|
5
|
+
#
|
6
|
+
# Details:: Specific over-rides/additions to support Spree Products
|
7
|
+
#
|
8
|
+
require 'loader_base'
|
9
|
+
|
10
|
+
class ProductLoader < LoaderBase
|
11
|
+
|
12
|
+
def initialize(klass = Product, product = nil)
|
13
|
+
super( klass, product )
|
14
|
+
raise "Failed to create Product for loading" unless @load_object
|
15
|
+
end
|
16
|
+
|
17
|
+
# What process a value string from a column, assigning value(s) to correct association on Product.
|
18
|
+
# Method map represents a column from a file and it's correlated Product association.
|
19
|
+
# Value string which may contain multiple values for a collection association.
|
20
|
+
# Product to assign that value to.
|
21
|
+
def process( method_map, value)
|
22
|
+
#puts "INFO: PRODUCT LOADER processing #{@load_object}"
|
23
|
+
@value = value
|
24
|
+
|
25
|
+
#puts "DEBUG : process #{method_map.inspect} : #{value.inspect}"
|
26
|
+
# Special case for OptionTypes as it's two stage process
|
27
|
+
# First add the possible option_types to Product, then we are able
|
28
|
+
# to define Variants on those options.
|
29
|
+
|
30
|
+
if(method_map.name == 'option_types' && @value)
|
31
|
+
|
32
|
+
option_types = @value.split(@@multi_assoc_delim)
|
33
|
+
option_types.each do |ostr|
|
34
|
+
oname, value_str = ostr.split(@@name_value_delim)
|
35
|
+
option_type = OptionType.find_or_create_by_name(oname)
|
36
|
+
unless option_type
|
37
|
+
puts "WARNING: OptionType #{oname} NOT found - Not set Product"
|
38
|
+
next
|
39
|
+
end
|
40
|
+
|
41
|
+
@load_object.option_types << option_type unless @load_object.option_types.include?(option_type)
|
42
|
+
|
43
|
+
# Now get the value(s) for the option e.g red,blue,green for OptType 'colour'
|
44
|
+
ovalues = value_str.split(',')
|
45
|
+
ovalues.each_with_index do |ovname, i|
|
46
|
+
ovname.strip!
|
47
|
+
ov = OptionValue.find_by_name(ovname)
|
48
|
+
if ov
|
49
|
+
object = Variant.new( :sku => "#{@load_object.sku}_#{i}", :price => @load_object.price, :available_on => @load_object.available_on)
|
50
|
+
#puts "DEBUG: Create New Variant: #{object.inspect}"
|
51
|
+
object.option_values << ov
|
52
|
+
@load_object.variants << object
|
53
|
+
else
|
54
|
+
puts "WARNING: Option #{ovname} NOT FOUND - No Variant created"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Special case for ProductProperties since it can have additional value applied.
|
60
|
+
# A list of Properties with a optional Value - supplied in form :
|
61
|
+
# Property:value|Property2:value|Property3:value
|
62
|
+
#
|
63
|
+
elsif(method_map.name == 'product_properties' && @value)
|
64
|
+
|
65
|
+
property_list = @value.split(@@multi_assoc_delim)
|
66
|
+
|
67
|
+
property_list.each do |pstr|
|
68
|
+
pname, pvalue = pstr.split(@@name_value_delim)
|
69
|
+
property = Property.find_by_name(pname)
|
70
|
+
unless property
|
71
|
+
puts "WARNING: Property #{pname} NOT found - Not set Product"
|
72
|
+
next
|
73
|
+
end
|
74
|
+
@load_object.product_properties << ProductProperty.create( :property => property, :value => pvalue)
|
75
|
+
end
|
76
|
+
|
77
|
+
elsif(method_map.name == 'count_on_hand' && @load_object.variants.size > 0 &&
|
78
|
+
@value.is_a?(String) && @value.include?(@@multi_assoc_delim))
|
79
|
+
# Check if we processed Option Types and assign count per option
|
80
|
+
values = @value.split(@@multi_assoc_delim)
|
81
|
+
if(@load_object.variants.size == values.size)
|
82
|
+
@load_object.variants.each_with_index {|v, i| v.count_on_hand == values[i] }
|
83
|
+
else
|
84
|
+
puts "WARNING: Count on hand entries does not match number of Variants"
|
85
|
+
end
|
86
|
+
|
87
|
+
else
|
88
|
+
super(method_map, value)
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
93
92
|
end
|
data/lib/to_b.rb
CHANGED
@@ -1,24 +1,24 @@
|
|
1
|
-
class Object
|
2
|
-
def to_b
|
3
|
-
case self
|
4
|
-
when true, false: self
|
5
|
-
when nil: false
|
6
|
-
else
|
7
|
-
to_i != 0
|
8
|
-
end
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
class String
|
13
|
-
TRUE_REGEXP = /^(yes|true|on|t|1|\-1)$/i.freeze
|
14
|
-
FALSE_REGEXP = /^(no|false|off|f|0)$/i.freeze
|
15
|
-
|
16
|
-
def to_b
|
17
|
-
case self
|
18
|
-
when TRUE_REGEXP: true
|
19
|
-
when FALSE_REGEXP: false
|
20
|
-
else
|
21
|
-
to_i != 0
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
1
|
+
class Object
|
2
|
+
def to_b
|
3
|
+
case self
|
4
|
+
when true, false: self
|
5
|
+
when nil: false
|
6
|
+
else
|
7
|
+
to_i != 0
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class String
|
13
|
+
TRUE_REGEXP = /^(yes|true|on|t|1|\-1)$/i.freeze
|
14
|
+
FALSE_REGEXP = /^(no|false|off|f|0)$/i.freeze
|
15
|
+
|
16
|
+
def to_b
|
17
|
+
case self
|
18
|
+
when TRUE_REGEXP: true
|
19
|
+
when FALSE_REGEXP: false
|
20
|
+
else
|
21
|
+
to_i != 0
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/spec/database.yml
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
class CreateTestBed < ActiveRecord::Migration
|
2
|
+
|
3
|
+
def self.up
|
4
|
+
|
5
|
+
create_table :test_model do |t|
|
6
|
+
t.string :value_as_string
|
7
|
+
t.text :value_as_text
|
8
|
+
t.boolean :value_as_boolean, :default => false
|
9
|
+
t.datetime :value_as_datetime, :default => nil
|
10
|
+
t.timestamps
|
11
|
+
end
|
12
|
+
|
13
|
+
create_table :test_association_model do |t|
|
14
|
+
t.string :value_as_string
|
15
|
+
t.references :test_model
|
16
|
+
t.timestamps
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.down
|
22
|
+
drop_table :test_model
|
23
|
+
drop_table :test_association_model
|
24
|
+
end
|
25
|
+
end
|