mongo_mapper_ext 0.2.4 → 0.2.5
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/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
|