mongo_mapper_ext 0.2.4 → 0.2.5
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +2 -2
- data/lib/mongo_mapper_ext/carrier_wave.rb +4 -2
- data/lib/mongo_mapper_ext/carrier_wave/mongo_mapper/plugins/mount_uploader.rb +31 -0
- data/lib/mongo_mapper_ext/carrier_wave/mongo_mapper/plugins/mount_uploaders.rb +137 -0
- data/lib/mongo_mapper_ext/gems.rb +6 -7
- data/lib/mongo_mapper_ext/mongo_mapper.rb +12 -9
- data/lib/mongo_mapper_ext/mongo_mapper/fixes.rb +13 -21
- data/lib/mongo_mapper_ext/mongo_mapper/hacks.rb +59 -0
- data/lib/mongo_mapper_ext/mongo_mapper/plugins/attribute_cache.rb +14 -18
- data/lib/mongo_mapper_ext/mongo_mapper/plugins/attribute_convertors.rb +69 -73
- data/lib/mongo_mapper_ext/mongo_mapper/plugins/belongs_to_with_counter_cache.rb +33 -37
- data/lib/mongo_mapper_ext/mongo_mapper/plugins/custom_scope.rb +67 -71
- data/lib/mongo_mapper_ext/mongo_mapper/plugins/db_config.rb +27 -24
- data/lib/mongo_mapper_ext/mongo_mapper/plugins/micelaneous.rb +46 -50
- data/lib/mongo_mapper_ext/rad.rb +3 -0
- data/lib/mongo_mapper_ext/rad/file_uploader.rb +21 -23
- data/readme.md +1 -1
- data/spec/carrier_wave/carrier_wave_spec.rb +82 -27
- data/spec/mongo_mapper/mongo_mapper_spec.rb +28 -27
- data/spec/rad/uploading_spec.rb +1 -1
- metadata +106 -112
- data/lib/mongo_mapper_ext/carrier_wave/mongo_mapper/plugins/carrier_wave.rb +0 -41
- data/lib/mongo_mapper_ext/mongo_mapper/locales/activemodel/ru.yml +0 -27
- data/lib/mongo_mapper_ext/mongo_mapper/locales/mongo_mapper/en.yml +0 -4
- data/lib/mongo_mapper_ext/mongo_mapper/locales/mongo_mapper/ru.yml +0 -4
- data/lib/mongo_mapper_ext/mongo_mapper/logging.rb +0 -75
data/Rakefile
CHANGED
@@ -2,9 +2,9 @@ require 'rake_ext'
|
|
2
2
|
|
3
3
|
project(
|
4
4
|
name: "mongo_mapper_ext",
|
5
|
-
version: "0.2.4",
|
6
5
|
summary: "Extensions for MongoMapper",
|
6
|
+
gem: true,
|
7
7
|
|
8
8
|
author: "Alexey Petrushin",
|
9
|
-
homepage: "http://github.com/alexeypetrushin/
|
9
|
+
homepage: "http://github.com/alexeypetrushin/mongo_mapper_ext"
|
10
10
|
)
|
@@ -6,7 +6,9 @@ require 'mongo_mapper_ext/mongo_mapper'
|
|
6
6
|
%w(
|
7
7
|
fixes
|
8
8
|
micelaneous
|
9
|
-
mongo_mapper/plugins/
|
9
|
+
mongo_mapper/plugins/mount_uploader
|
10
|
+
mongo_mapper/plugins/mount_uploaders
|
10
11
|
).each{|f| require "mongo_mapper_ext/carrier_wave/#{f}"}
|
11
12
|
|
12
|
-
MongoMapper::Document.send :include, MongoMapper::Plugins::
|
13
|
+
MongoMapper::Document.send :include, MongoMapper::Plugins::MountUploader
|
14
|
+
MongoMapper::EmbeddedDocument.send :include, MongoMapper::Plugins::MountUploader
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#
|
2
|
+
# mount_uploader
|
3
|
+
#
|
4
|
+
module MongoMapper::Plugins::MountUploader
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
include ::CarrierWave::Mount
|
9
|
+
|
10
|
+
def mount_uploader(column, uploader, options={}, &block)
|
11
|
+
options[:mount_on] ||= "#{column}_filename"
|
12
|
+
name = options[:mount_on]
|
13
|
+
key name
|
14
|
+
|
15
|
+
super
|
16
|
+
|
17
|
+
alias_method :read_uploader, :read_attribute
|
18
|
+
alias_method :write_uploader, :write_attribute
|
19
|
+
|
20
|
+
include ::CarrierWave::Validations::ActiveModel
|
21
|
+
|
22
|
+
validates_integrity_of column if uploader_option(column.to_sym, :validate_integrity)
|
23
|
+
validates_processing_of column if uploader_option(column.to_sym, :validate_processing)
|
24
|
+
|
25
|
+
after_save "store_#{column}!".to_sym
|
26
|
+
before_save "write_#{column}_identifier".to_sym
|
27
|
+
after_destroy "remove_#{column}!".to_sym
|
28
|
+
end
|
29
|
+
alias_method :file_key, :mount_uploader
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
# #
|
2
|
+
# # mount_uploaders
|
3
|
+
# #
|
4
|
+
# module MongoMapper::Plugins::MountUploaders
|
5
|
+
# extend ActiveSupport::Concern
|
6
|
+
#
|
7
|
+
# class FileHelper
|
8
|
+
# attr_reader :data
|
9
|
+
# def initialize data
|
10
|
+
# data.must_be.a String, File, Hash
|
11
|
+
# if data.is_a?(Hash)
|
12
|
+
# data.must.include('filename')
|
13
|
+
# data.must.include('tempfile')
|
14
|
+
# end
|
15
|
+
# @data = data
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# def real_file?
|
19
|
+
# data.is_a?(File) or data.is_a?(Hash)
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# def file_name
|
23
|
+
# real_file?
|
24
|
+
# end
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# module InstanceMethods
|
28
|
+
# def set_uploaders attr_name, files
|
29
|
+
# before = get_uploaders attr_name
|
30
|
+
# after = files
|
31
|
+
#
|
32
|
+
# # selecting File and HTTP TempFile
|
33
|
+
# added = files.select{|file| FileHelper.new(file).real_file?}
|
34
|
+
# deleted = files.
|
35
|
+
#
|
36
|
+
#
|
37
|
+
# added = after - before
|
38
|
+
# deleted = before - after
|
39
|
+
#
|
40
|
+
# added.each do |name|
|
41
|
+
# if tag = Tag.find_by_name(name)
|
42
|
+
# tag.update_count!
|
43
|
+
# else
|
44
|
+
# tag = Tag.new name: name
|
45
|
+
# tag.count = 1
|
46
|
+
# tag.save!
|
47
|
+
# end
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# deleted.each do |name|
|
51
|
+
# if tag = Tag.find_by_name(name)
|
52
|
+
# tag.update_count!
|
53
|
+
# tag.destroy if tag.count == 0
|
54
|
+
# end
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
#
|
58
|
+
# # tags.join(", ")
|
59
|
+
# end
|
60
|
+
#
|
61
|
+
# def get_uploaders attr_name
|
62
|
+
# # self.tags = tags_as_string.split(Tag::TAG_LIST_DELIMITER).collect{|name| name.strip}.sort
|
63
|
+
# end
|
64
|
+
#
|
65
|
+
# after_save :update_tags
|
66
|
+
# def update_tags
|
67
|
+
# return unless changed.include? 'tags'
|
68
|
+
#
|
69
|
+
# before, after = changes['tags']
|
70
|
+
# added = after - before
|
71
|
+
# deleted = before - after
|
72
|
+
#
|
73
|
+
# added.each do |name|
|
74
|
+
# if tag = Tag.find_by_name(name)
|
75
|
+
# tag.update_count!
|
76
|
+
# else
|
77
|
+
# tag = Tag.new name: name
|
78
|
+
# tag.count = 1
|
79
|
+
# tag.save!
|
80
|
+
# end
|
81
|
+
# end
|
82
|
+
#
|
83
|
+
# deleted.each do |name|
|
84
|
+
# if tag = Tag.find_by_name(name)
|
85
|
+
# tag.update_count!
|
86
|
+
# tag.destroy if tag.count == 0
|
87
|
+
# end
|
88
|
+
# end
|
89
|
+
# end
|
90
|
+
# protected :update_tags
|
91
|
+
#
|
92
|
+
# after_destroy :delete_tags
|
93
|
+
# def delete_tags
|
94
|
+
# raise "Can't destroy item with changed tags!" if changed.include? 'tags'
|
95
|
+
#
|
96
|
+
# tags.each do |name|
|
97
|
+
# if tag = Tag.find_by_name(name)
|
98
|
+
# tag.update_count!
|
99
|
+
# tag.destroy if tag.count == 0
|
100
|
+
# end
|
101
|
+
# end
|
102
|
+
# end
|
103
|
+
# protected :delete_tags
|
104
|
+
#
|
105
|
+
# protected
|
106
|
+
# def parse_file_name obj
|
107
|
+
# if obj.is_a
|
108
|
+
# end
|
109
|
+
#
|
110
|
+
# def
|
111
|
+
# end
|
112
|
+
#
|
113
|
+
# module ClassMethods
|
114
|
+
# include ::CarrierWave::Mount
|
115
|
+
#
|
116
|
+
# def mount_uploaders(column, uploader, options={}, &block)
|
117
|
+
# options[:mount_on] ||= "#{column}_filename"
|
118
|
+
# name = options[:mount_on]
|
119
|
+
# key name
|
120
|
+
#
|
121
|
+
# # super
|
122
|
+
# #
|
123
|
+
# # alias_method :read_uploader, :read_attribute
|
124
|
+
# # alias_method :write_uploader, :write_attribute
|
125
|
+
# #
|
126
|
+
# # include ::CarrierWave::Validations::ActiveModel
|
127
|
+
# #
|
128
|
+
# # validates_integrity_of column if uploader_option(column.to_sym, :validate_integrity)
|
129
|
+
# # validates_processing_of column if uploader_option(column.to_sym, :validate_processing)
|
130
|
+
# #
|
131
|
+
# # after_save "store_#{column}!".to_sym
|
132
|
+
# # before_save "write_#{column}_identifier".to_sym
|
133
|
+
# # after_destroy "remove_#{column}!".to_sym
|
134
|
+
# end
|
135
|
+
# alias_method :file_keys, :mount_uploaders
|
136
|
+
# end
|
137
|
+
# end
|
@@ -1,8 +1,3 @@
|
|
1
|
-
# core gems
|
2
|
-
gem 'mongo_mapper', '0.9.0'
|
3
|
-
|
4
|
-
gem 'carrierwave', '0.5.3'
|
5
|
-
|
6
1
|
# dependencies for core gems
|
7
2
|
gem 'i18n', '0.5.0'
|
8
3
|
gem 'activesupport', '3.0.7'
|
@@ -11,7 +6,11 @@ gem 'bson', '1.3.0'
|
|
11
6
|
gem 'bson_ext', '1.3.0'
|
12
7
|
gem 'mongo', '1.3.0'
|
13
8
|
gem 'plucky', '0.3.6'
|
14
|
-
gem 'jnunemaker-validatable', '1.8.4'
|
15
9
|
|
16
10
|
gem 'mini_magick', '3.2.1'
|
17
|
-
gem 'subexec', '0.0.4'
|
11
|
+
gem 'subexec', '0.0.4'
|
12
|
+
|
13
|
+
# core gems
|
14
|
+
gem 'mongo_mapper', '0.9.0'
|
15
|
+
|
16
|
+
gem 'carrierwave', '0.5.3'
|
@@ -3,14 +3,14 @@ require 'mongo_mapper'
|
|
3
3
|
|
4
4
|
require 'mongo_mapper_ext/mongo_db'
|
5
5
|
|
6
|
+
|
6
7
|
%w(
|
7
8
|
fixes
|
8
9
|
hacks
|
9
10
|
support
|
10
11
|
|
11
12
|
migration
|
12
|
-
view_helpers
|
13
|
-
logging
|
13
|
+
view_helpers
|
14
14
|
|
15
15
|
plugins/attribute_cache
|
16
16
|
plugins/attribute_convertors
|
@@ -24,11 +24,14 @@ require 'mongo_mapper_ext/mongo_db'
|
|
24
24
|
#
|
25
25
|
# Default plugins
|
26
26
|
#
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
27
|
+
[
|
28
|
+
MongoMapper::Plugins::CustomScope,
|
29
|
+
MongoMapper::Plugins::AttributeCache,
|
30
|
+
MongoMapper::Plugins::AttributeConvertors,
|
31
|
+
MongoMapper::Plugins::BelongsToWithCounterCache,
|
32
|
+
MongoMapper::Plugins::Micelaneous,
|
33
|
+
MongoMapper::Plugins::DbConfig
|
34
|
+
].each{|plugin| ::MongoMapper::Document.send :include, plugin}
|
32
35
|
|
33
36
|
|
34
37
|
#
|
@@ -42,5 +45,5 @@ end
|
|
42
45
|
#
|
43
46
|
# Locales
|
44
47
|
#
|
45
|
-
dir = __FILE__
|
46
|
-
I18n.load_path += Dir["#{dir}/
|
48
|
+
dir = File.expand_path "#{__FILE__}/../../.."
|
49
|
+
I18n.load_path += Dir["#{dir}/config/locales/**/*.{rb,yml}"]
|
@@ -23,17 +23,13 @@ end
|
|
23
23
|
# Problem after destroying model the :to_param method returns :nill,
|
24
24
|
# and we can't use :to_param in view (for example in ajax to remove element with id from the screen).
|
25
25
|
#
|
26
|
-
module MongoMapper
|
27
|
-
module
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
def to_param
|
34
|
-
id.to_s
|
35
|
-
end
|
36
|
-
end
|
26
|
+
module MongoMapper::Plugins::Rails
|
27
|
+
module InstanceMethods
|
28
|
+
# def to_param
|
29
|
+
# id.to_s if persisted? # old realization
|
30
|
+
# end
|
31
|
+
def to_param
|
32
|
+
id.to_s
|
37
33
|
end
|
38
34
|
end
|
39
35
|
end
|
@@ -43,15 +39,11 @@ end
|
|
43
39
|
# Use class alias instead of class name, because it causes foreign keys like 'models_account_id' instead of 'account_id' if
|
44
40
|
# for models like Models::Account
|
45
41
|
#
|
46
|
-
module MongoMapper
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
# options[:foreign_key] || proxy_owner.class.name.to_s.underscore.gsub("/", "_") + "_id"
|
52
|
-
options[:foreign_key] || proxy_owner.class.alias.to_s.underscore.gsub("/", "_") + "_id"
|
53
|
-
end
|
42
|
+
module MongoMapper::Plugins::Associations
|
43
|
+
class ManyDocumentsProxy
|
44
|
+
def foreign_key
|
45
|
+
# options[:foreign_key] || proxy_owner.class.name.to_s.underscore.gsub("/", "_") + "_id"
|
46
|
+
options[:foreign_key] || proxy_owner.class.alias.to_s.underscore.gsub("/", "_") + "_id"
|
54
47
|
end
|
55
|
-
end
|
56
48
|
end
|
57
|
-
end
|
49
|
+
end
|
@@ -1,3 +1,6 @@
|
|
1
|
+
#
|
2
|
+
# Allow to specify different model name than class name
|
3
|
+
#
|
1
4
|
ActiveModel::Name.class_eval do
|
2
5
|
def initialize klass, name = nil
|
3
6
|
name ||= klass.name
|
@@ -13,4 +16,60 @@ ActiveModel::Name.class_eval do
|
|
13
16
|
@partial_path = "#{@collection}/#{@element}".freeze
|
14
17
|
@i18n_key = ActiveSupport::Inflector.underscore(self).tr('/', '.').to_sym
|
15
18
|
end
|
19
|
+
|
20
|
+
# def initialize(klass)
|
21
|
+
# super(klass.name)
|
22
|
+
# @klass = klass
|
23
|
+
# @singular = ActiveSupport::Inflector.underscore(self).tr('/', '_').freeze
|
24
|
+
# @plural = ActiveSupport::Inflector.pluralize(@singular).freeze
|
25
|
+
# @element = ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(self)).freeze
|
26
|
+
# @human = ActiveSupport::Inflector.humanize(@element).freeze
|
27
|
+
# @collection = ActiveSupport::Inflector.tableize(self).freeze
|
28
|
+
# @partial_path = "#{@collection}/#{@element}".freeze
|
29
|
+
# @i18n_key = ActiveSupport::Inflector.underscore(self).tr('/', '.').to_sym
|
30
|
+
# end
|
16
31
|
end
|
32
|
+
|
33
|
+
|
34
|
+
#
|
35
|
+
# Logger
|
36
|
+
#
|
37
|
+
MongoMapper.class_eval do
|
38
|
+
class << self
|
39
|
+
attr_writer :logger
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
Mongo::Connection.class_eval do
|
44
|
+
attr_writer :logger
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
#
|
49
|
+
# Silence Logger
|
50
|
+
#
|
51
|
+
MongoMapper.class_eval do
|
52
|
+
def self.silince_logger &block
|
53
|
+
logger, nil_logger = self.logger, Logger.new(nil)
|
54
|
+
|
55
|
+
begin
|
56
|
+
MongoMapper.logger = nil_logger
|
57
|
+
connections.each{|name, connection| connection.logger = nil_logger}
|
58
|
+
block.call
|
59
|
+
ensure
|
60
|
+
MongoMapper.logger = logger
|
61
|
+
connections.each{|name, connection| connection.logger = logger}
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
#
|
68
|
+
# Silent index creation
|
69
|
+
#
|
70
|
+
MongoMapper::Plugins::Indexes::ClassMethods.class_eval do
|
71
|
+
def ensure_index_with_silent_logger *a
|
72
|
+
MongoMapper.silince_logger{ensure_index_without_silent_logger *a}
|
73
|
+
end
|
74
|
+
alias_method_chain :ensure_index, :silent_logger
|
75
|
+
end
|
@@ -1,23 +1,19 @@
|
|
1
|
-
module MongoMapper
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
@cache ||= {}
|
9
|
-
end
|
1
|
+
module MongoMapper::Plugins::AttributeCache
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
module InstanceMethods
|
5
|
+
def cache
|
6
|
+
@cache ||= {}
|
7
|
+
end
|
10
8
|
|
11
|
-
|
12
|
-
|
13
|
-
|
9
|
+
def clear_cache
|
10
|
+
@cache = {}
|
11
|
+
end
|
14
12
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
13
|
+
def reload
|
14
|
+
@cache.clear if @cache
|
15
|
+
super
|
21
16
|
end
|
22
17
|
end
|
18
|
+
|
23
19
|
end
|
@@ -1,79 +1,75 @@
|
|
1
|
-
module MongoMapper
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
hash = {}; v.each{|k, v| hash[k] = v}
|
29
|
-
hash.to_json.strip
|
30
|
-
}
|
31
|
-
}
|
1
|
+
module MongoMapper::Plugins::AttributeConvertors
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
module ClassMethods
|
5
|
+
ATTRIBUTE_CONVERTORS = {
|
6
|
+
line: {
|
7
|
+
from_string: -> s {(s || "").split(',').collect{|s| s.strip}},
|
8
|
+
to_string: -> v {v.join(', ')}
|
9
|
+
},
|
10
|
+
column: {
|
11
|
+
from_string: -> s {(s || "").split("\n").collect{|s| s.strip}},
|
12
|
+
to_string: -> v {v.join("\n")}
|
13
|
+
},
|
14
|
+
yaml: {
|
15
|
+
from_string: -> s {YAML.load s rescue {}},
|
16
|
+
to_string: -> v {
|
17
|
+
# MongoMapper uses it's internal Hash that doesn't support to_yaml
|
18
|
+
hash = {}; v.each{|k, v| hash[k] = v}
|
19
|
+
hash.to_yaml.strip
|
20
|
+
}
|
21
|
+
},
|
22
|
+
json: {
|
23
|
+
from_string: -> s {JSON.parse s rescue {}},
|
24
|
+
to_string: -> v {
|
25
|
+
# MongoMapper uses it's internal Hash that doesn't support to_yaml
|
26
|
+
hash = {}; v.each{|k, v| hash[k] = v}
|
27
|
+
hash.to_json.strip
|
32
28
|
}
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
end
|
47
|
-
|
48
|
-
def available_as_string key_name, converter_name
|
49
|
-
converter = ATTRIBUTE_CONVERTORS[converter_name]
|
50
|
-
raise "unknown converter name :#{converter_name} for :#{key_name} key!" unless converter
|
51
|
-
|
52
|
-
from_string, to_string = converter[:from_string], converter[:to_string]
|
53
|
-
key_name_as_string = "#{key_name}_as_string".to_sym
|
54
|
-
define_method key_name_as_string do
|
55
|
-
cache[key_name_as_string] ||= to_string.call(self.send(key_name))
|
56
|
-
end
|
57
|
-
define_method "#{key_name_as_string}=" do |value|
|
58
|
-
cache.delete key_name_as_string
|
59
|
-
self.send "#{key_name}=", from_string.call(value)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def available_as_yaml key_name
|
64
|
-
raise "delimiter not specified for :#{key_name} key!" unless delimiter
|
65
|
-
method = "#{key_name}_as_string"
|
66
|
-
define_method method do
|
67
|
-
self.send(key_name).join(delimiter)
|
68
|
-
end
|
69
|
-
define_method "#{method}=" do |value|
|
70
|
-
value = (value || "").split(delimiter.strip).collect{|s| s.strip}
|
71
|
-
self.send "#{key_name}=", value
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
|
33
|
+
#
|
34
|
+
# supporf for :as_string option
|
35
|
+
#
|
36
|
+
def key(*args)
|
37
|
+
key = super
|
38
|
+
if converter_name = key.options[:as_string]
|
39
|
+
key_name = key.name.to_sym
|
40
|
+
available_as_string key_name, converter_name
|
41
|
+
attr_protected "#{key_name}_as_string".to_sym if key.options[:protected]
|
75
42
|
end
|
43
|
+
key
|
44
|
+
end
|
45
|
+
|
46
|
+
def available_as_string key_name, converter_name
|
47
|
+
converter = ATTRIBUTE_CONVERTORS[converter_name]
|
48
|
+
raise "unknown converter name :#{converter_name} for :#{key_name} key!" unless converter
|
76
49
|
|
50
|
+
from_string, to_string = converter[:from_string], converter[:to_string]
|
51
|
+
key_name_as_string = "#{key_name}_as_string".to_sym
|
52
|
+
define_method key_name_as_string do
|
53
|
+
cache[key_name_as_string] ||= to_string.call(self.send(key_name))
|
54
|
+
end
|
55
|
+
define_method "#{key_name_as_string}=" do |value|
|
56
|
+
cache.delete key_name_as_string
|
57
|
+
self.send "#{key_name}=", from_string.call(value)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def available_as_yaml key_name
|
62
|
+
raise "delimiter not specified for :#{key_name} key!" unless delimiter
|
63
|
+
method = "#{key_name}_as_string"
|
64
|
+
define_method method do
|
65
|
+
self.send(key_name).join(delimiter)
|
66
|
+
end
|
67
|
+
define_method "#{method}=" do |value|
|
68
|
+
value = (value || "").split(delimiter.strip).collect{|s| s.strip}
|
69
|
+
self.send "#{key_name}=", value
|
70
|
+
end
|
77
71
|
end
|
72
|
+
|
78
73
|
end
|
74
|
+
|
79
75
|
end
|