Commit a294f41d2617c11734b018d5c5db7546836f5eb0

Authored by Braulio Bhavamitra
1 parent b4e6aa3b

rails4.2: migrate type casting as acts_as_having_settings

app/models/blog_archives_block.rb
... ... @@ -15,7 +15,7 @@ class BlogArchivesBlock < Block
15 15 _('Blog posts')
16 16 end
17 17  
18   - settings_items :blog_id, Integer
  18 + settings_items :blog_id, type: Integer
19 19  
20 20 def blog
21 21 blog_id && owner.blogs.exists?(blog_id) ? owner.blogs.find(blog_id) : owner.blog
... ...
app/models/link_list_block.rb
... ... @@ -41,7 +41,7 @@ class LinkListBlock < Block
41 41 [N_('New window'), '_new'],
42 42 ]
43 43  
44   - settings_items :links, Array, :default => []
  44 + settings_items :links, type: Array, :default => []
45 45  
46 46 before_save do |block|
47 47 block.links = block.links.delete_if {|i| i[:name].blank? and i[:address].blank?}
... ...
app/models/products_block.rb
... ... @@ -39,7 +39,7 @@ class ProductsBlock < Block
39 39 link_to(_('View all products'), owner.public_profile_url.merge(:controller => 'catalog', :action => 'index'))
40 40 end
41 41  
42   - settings_items :product_ids, Array
  42 + settings_items :product_ids, type: Array
43 43 def product_ids=(array)
44 44 self.settings[:product_ids] = array
45 45 if self.settings[:product_ids]
... ...
lib/acts_as_having_settings.rb
  1 +# declare missing types
  2 +module ActiveRecord
  3 + module Type
  4 + class Symbol < Value
  5 + def cast_value value
  6 + value.to_sym
  7 + end
  8 + end
  9 + class Array < Value
  10 + def cast_value value
  11 + Array(value)
  12 + end
  13 + end
  14 + class Hash < Value
  15 + def cast_value value
  16 + Hash[value]
  17 + end
  18 + end
  19 + end
  20 +end
  21 +
1 22 module ActsAsHavingSettings
2 23  
3 24 module ClassMethods
  25 +
4 26 def acts_as_having_settings(*args)
5 27 options = args.last.is_a?(Hash) ? args.pop : {}
6   -
7   - settings_field = options[:field] || 'settings'
  28 + field = (options[:field] || :settings).to_sym
8 29  
9   - class_eval <<-CODE
10   - serialize :#{settings_field}, Hash
11   - def self.settings_field
12   - #{settings_field.inspect}
13   - end
14   - def #{settings_field}
15   - self[:#{settings_field}] ||= Hash.new
  30 + serialize field, Hash
  31 + class_attribute :settings_field
  32 + self.settings_field = field
  33 +
  34 + class_eval do
  35 + def settings_field
  36 + self[self.class.settings_field] ||= Hash.new
16 37 end
17 38  
18   - def setting_changed?(setting_field)
  39 + def setting_changed? setting_field
19 40 setting_field = setting_field.to_sym
20   - changed_settings = self.changes['#{settings_field}']
  41 + changed_settings = self.changes[self.class.settings_field]
21 42 return false if changed_settings.nil?
22 43  
23 44 old_setting_value = changed_settings.first.nil? ? nil : changed_settings.first[setting_field]
24 45 new_setting_value = changed_settings.last[setting_field]
25 46 old_setting_value != new_setting_value
26 47 end
  48 + end
27 49  
28   - before_save :symbolize_settings_keys
29   - private
30   - def symbolize_settings_keys
31   - self[:#{settings_field}] && self[:#{settings_field}].symbolize_keys!
32   - end
33   - CODE
34   - settings_items(*args)
  50 + settings_items *args
35 51 end
36 52  
37 53 def settings_items(*names)
38 54  
39 55 options = names.last.is_a?(Hash) ? names.pop : {}
40   - default = (!options[:default].nil?) ? options[:default].inspect : "val"
41   - data_type = options[:type] || :string
  56 + default = if !options[:default].nil? then options[:default] else nil end
  57 + data_type = options[:type]
  58 + data_type = if data_type.present? then data_type.to_s.camelize.to_sym else :String end
  59 + data_type = ActiveRecord::Type.const_get(data_type).new
42 60  
43 61 names.each do |setting|
44   - class_eval <<-CODE
45   - def #{setting}
46   - val = send(self.class.settings_field)[:#{setting}]
47   - val.nil? ? (#{default}.is_a?(String) ? gettext(#{default}) : #{default}) : val
48   - end
49   - def #{setting}=(value)
50   - h = send(self.class.settings_field).clone
51   - h[:#{setting}] = self.class.acts_as_having_settings_type_cast(value, #{data_type.inspect})
52   - send(self.class.settings_field.to_s + '=', h)
53   - end
54   - CODE
  62 + # symbolize key
  63 + setting = setting.to_sym
  64 +
  65 + define_method setting do
  66 + h = send self.class.settings_field
  67 + val = h[setting]
  68 + if val.nil? then (if default.is_a? String then gettext default else default end) else val end
  69 + end
  70 + define_method "#{setting}=" do |value|
  71 + h = send self.class.settings_field
  72 + h[setting] = self.class.acts_as_having_settings_type_cast value, data_type
  73 + end
55 74 end
56 75 end
57 76  
58   - def acts_as_having_settings_type_cast(value, type)
59   - # FIXME creating a new instance at every call, will the garbage collector
60   - # be able to cope with it?
61   - ActiveRecord::ConnectionAdapters::Column.new(:dummy, nil, type.to_s).type_cast(value)
  77 + def acts_as_having_settings_type_cast value, type
  78 + type.send :cast_value, value
62 79 end
63 80  
64 81 end
... ...
plugins/statistics/lib/statistics_block.rb
... ... @@ -8,7 +8,7 @@ class StatisticsBlock &lt; Block
8 8 settings_items :tag_counter, :default => true
9 9 settings_items :comment_counter, :default => true
10 10 settings_items :hit_counter, :default => false
11   - settings_items :templates_ids_counter, Hash, :default => {}
  11 + settings_items :templates_ids_counter, type: Hash, default: {}
12 12  
13 13 attr_accessible :comment_counter, :community_counter, :user_counter, :enterprise_counter, :product_counter, :category_counter, :tag_counter, :hit_counter, :templates_ids_counter
14 14  
... ...
test/unit/acts_as_having_settings_test.rb
... ... @@ -2,11 +2,12 @@ require_relative &quot;../test_helper&quot;
2 2  
3 3 class ActsAsHavingSettingsTest < ActiveSupport::TestCase
4 4  
5   - # using Block class as a sample user of the module
  5 + # using Block class as a sample user of the module
6 6 class TestClass < Block
7   - settings_items :flag, :type => :boolean
8   - settings_items :flag_disabled_by_default, :type => :boolean, :default => false
9   - settings_items :name, :type => :string, :default => N_('ENGLISH TEXT')
  7 + settings_items :flag, type: :boolean
  8 + settings_items :flag_disabled_by_default, type: :boolean, default: false
  9 + # to test that 'name' will be symbolized (see below)
  10 + settings_items 'name', type: :string, default: N_('ENGLISH TEXT')
10 11 attr_accessible :flag, :name, :flag_disabled_by_default
11 12 end
12 13  
... ... @@ -26,7 +27,7 @@ class ActsAsHavingSettingsTest &lt; ActiveSupport::TestCase
26 27 assert !block.respond_to?(:limit)
27 28 assert !block.respond_to?(:limit=)
28 29  
29   - block_class.settings_items :limit
  30 + block_class.settings_items :limit, type: :integer
30 31  
31 32 assert_respond_to block, :limit
32 33 assert_respond_to block, :limit=
... ... @@ -35,7 +36,7 @@ class ActsAsHavingSettingsTest &lt; ActiveSupport::TestCase
35 36 block.limit = 10
36 37 assert_equal 10, block.limit
37 38  
38   - assert_equal({ :limit => 10}, block.settings)
  39 + assert_equal({ limit: 10}, block.settings)
39 40 end
40 41  
41 42 should 'properly save the settings' do
... ... @@ -50,7 +51,7 @@ class ActsAsHavingSettingsTest &lt; ActiveSupport::TestCase
50 51  
51 52 should 'be able to specify default values' do
52 53 block_class = Class.new(Block)
53   - block_class.settings_items :some_setting, :default => 10
  54 + block_class.settings_items :some_setting, default: 10
54 55 assert_equal 10, block_class.new.some_setting
55 56 end
56 57  
... ... @@ -75,10 +76,9 @@ class ActsAsHavingSettingsTest &lt; ActiveSupport::TestCase
75 76 assert_equal true, obj.flag
76 77 end
77 78  
78   - should 'symbolize keys when save' do
  79 + should 'have keys as symbols' do
79 80 obj = TestClass.new
80   - obj.settings.expects(:symbolize_keys!).once
81   - assert obj.save
  81 + assert obj.settings.all?{ |k,v| k.is_a? Symbol }
82 82 end
83 83  
84 84 should 'setting_changed be true if a setting passed as parameter was changed' do
... ... @@ -101,14 +101,14 @@ class ActsAsHavingSettingsTest &lt; ActiveSupport::TestCase
101 101 end
102 102  
103 103 should 'setting_changed be false if a setting passed as parameter was not changed but another setting is changed' do
104   - obj = TestClass.new(:name => 'some name')
  104 + obj = TestClass.new(name: 'some name')
105 105 obj.save
106 106 obj.name = 'antoher nme'
107 107 assert !obj.setting_changed?('flag')
108 108 end
109 109  
110 110 should 'setting_changed be true for all changed fields' do
111   - obj = TestClass.new(:name => 'some name', :flag => false)
  111 + obj = TestClass.new(name: 'some name', flag: false)
112 112 obj.save
113 113 obj.name = 'another nme'
114 114 obj.flag = true
... ...