ar_loader 0.0.4 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|