Commit a294f41d2617c11734b018d5c5db7546836f5eb0
1 parent
b4e6aa3b
Exists in
master
and in
20 other branches
rails4.2: migrate type casting as acts_as_having_settings
Showing
6 changed files
with
68 additions
and
51 deletions
Show diff stats
app/models/blog_archives_block.rb
@@ -15,7 +15,7 @@ class BlogArchivesBlock < Block | @@ -15,7 +15,7 @@ class BlogArchivesBlock < Block | ||
15 | _('Blog posts') | 15 | _('Blog posts') |
16 | end | 16 | end |
17 | 17 | ||
18 | - settings_items :blog_id, Integer | 18 | + settings_items :blog_id, type: Integer |
19 | 19 | ||
20 | def blog | 20 | def blog |
21 | blog_id && owner.blogs.exists?(blog_id) ? owner.blogs.find(blog_id) : owner.blog | 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,7 +41,7 @@ class LinkListBlock < Block | ||
41 | [N_('New window'), '_new'], | 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 | before_save do |block| | 46 | before_save do |block| |
47 | block.links = block.links.delete_if {|i| i[:name].blank? and i[:address].blank?} | 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,7 +39,7 @@ class ProductsBlock < Block | ||
39 | link_to(_('View all products'), owner.public_profile_url.merge(:controller => 'catalog', :action => 'index')) | 39 | link_to(_('View all products'), owner.public_profile_url.merge(:controller => 'catalog', :action => 'index')) |
40 | end | 40 | end |
41 | 41 | ||
42 | - settings_items :product_ids, Array | 42 | + settings_items :product_ids, type: Array |
43 | def product_ids=(array) | 43 | def product_ids=(array) |
44 | self.settings[:product_ids] = array | 44 | self.settings[:product_ids] = array |
45 | if self.settings[:product_ids] | 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 | module ActsAsHavingSettings | 22 | module ActsAsHavingSettings |
2 | 23 | ||
3 | module ClassMethods | 24 | module ClassMethods |
25 | + | ||
4 | def acts_as_having_settings(*args) | 26 | def acts_as_having_settings(*args) |
5 | options = args.last.is_a?(Hash) ? args.pop : {} | 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 | end | 37 | end |
17 | 38 | ||
18 | - def setting_changed?(setting_field) | 39 | + def setting_changed? setting_field |
19 | setting_field = setting_field.to_sym | 40 | setting_field = setting_field.to_sym |
20 | - changed_settings = self.changes['#{settings_field}'] | 41 | + changed_settings = self.changes[self.class.settings_field] |
21 | return false if changed_settings.nil? | 42 | return false if changed_settings.nil? |
22 | 43 | ||
23 | old_setting_value = changed_settings.first.nil? ? nil : changed_settings.first[setting_field] | 44 | old_setting_value = changed_settings.first.nil? ? nil : changed_settings.first[setting_field] |
24 | new_setting_value = changed_settings.last[setting_field] | 45 | new_setting_value = changed_settings.last[setting_field] |
25 | old_setting_value != new_setting_value | 46 | old_setting_value != new_setting_value |
26 | end | 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 | end | 51 | end |
36 | 52 | ||
37 | def settings_items(*names) | 53 | def settings_items(*names) |
38 | 54 | ||
39 | options = names.last.is_a?(Hash) ? names.pop : {} | 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 | names.each do |setting| | 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 | end | 74 | end |
56 | end | 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 | end | 79 | end |
63 | 80 | ||
64 | end | 81 | end |
plugins/statistics/lib/statistics_block.rb
@@ -8,7 +8,7 @@ class StatisticsBlock < Block | @@ -8,7 +8,7 @@ class StatisticsBlock < Block | ||
8 | settings_items :tag_counter, :default => true | 8 | settings_items :tag_counter, :default => true |
9 | settings_items :comment_counter, :default => true | 9 | settings_items :comment_counter, :default => true |
10 | settings_items :hit_counter, :default => false | 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 | attr_accessible :comment_counter, :community_counter, :user_counter, :enterprise_counter, :product_counter, :category_counter, :tag_counter, :hit_counter, :templates_ids_counter | 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 "../test_helper" | @@ -2,11 +2,12 @@ require_relative "../test_helper" | ||
2 | 2 | ||
3 | class ActsAsHavingSettingsTest < ActiveSupport::TestCase | 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 | class TestClass < Block | 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 | attr_accessible :flag, :name, :flag_disabled_by_default | 11 | attr_accessible :flag, :name, :flag_disabled_by_default |
11 | end | 12 | end |
12 | 13 | ||
@@ -26,7 +27,7 @@ class ActsAsHavingSettingsTest < ActiveSupport::TestCase | @@ -26,7 +27,7 @@ class ActsAsHavingSettingsTest < ActiveSupport::TestCase | ||
26 | assert !block.respond_to?(:limit) | 27 | assert !block.respond_to?(:limit) |
27 | assert !block.respond_to?(:limit=) | 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 | assert_respond_to block, :limit | 32 | assert_respond_to block, :limit |
32 | assert_respond_to block, :limit= | 33 | assert_respond_to block, :limit= |
@@ -35,7 +36,7 @@ class ActsAsHavingSettingsTest < ActiveSupport::TestCase | @@ -35,7 +36,7 @@ class ActsAsHavingSettingsTest < ActiveSupport::TestCase | ||
35 | block.limit = 10 | 36 | block.limit = 10 |
36 | assert_equal 10, block.limit | 37 | assert_equal 10, block.limit |
37 | 38 | ||
38 | - assert_equal({ :limit => 10}, block.settings) | 39 | + assert_equal({ limit: 10}, block.settings) |
39 | end | 40 | end |
40 | 41 | ||
41 | should 'properly save the settings' do | 42 | should 'properly save the settings' do |
@@ -50,7 +51,7 @@ class ActsAsHavingSettingsTest < ActiveSupport::TestCase | @@ -50,7 +51,7 @@ class ActsAsHavingSettingsTest < ActiveSupport::TestCase | ||
50 | 51 | ||
51 | should 'be able to specify default values' do | 52 | should 'be able to specify default values' do |
52 | block_class = Class.new(Block) | 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 | assert_equal 10, block_class.new.some_setting | 55 | assert_equal 10, block_class.new.some_setting |
55 | end | 56 | end |
56 | 57 | ||
@@ -75,10 +76,9 @@ class ActsAsHavingSettingsTest < ActiveSupport::TestCase | @@ -75,10 +76,9 @@ class ActsAsHavingSettingsTest < ActiveSupport::TestCase | ||
75 | assert_equal true, obj.flag | 76 | assert_equal true, obj.flag |
76 | end | 77 | end |
77 | 78 | ||
78 | - should 'symbolize keys when save' do | 79 | + should 'have keys as symbols' do |
79 | obj = TestClass.new | 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 | end | 82 | end |
83 | 83 | ||
84 | should 'setting_changed be true if a setting passed as parameter was changed' do | 84 | should 'setting_changed be true if a setting passed as parameter was changed' do |
@@ -101,14 +101,14 @@ class ActsAsHavingSettingsTest < ActiveSupport::TestCase | @@ -101,14 +101,14 @@ class ActsAsHavingSettingsTest < ActiveSupport::TestCase | ||
101 | end | 101 | end |
102 | 102 | ||
103 | should 'setting_changed be false if a setting passed as parameter was not changed but another setting is changed' do | 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 | obj.save | 105 | obj.save |
106 | obj.name = 'antoher nme' | 106 | obj.name = 'antoher nme' |
107 | assert !obj.setting_changed?('flag') | 107 | assert !obj.setting_changed?('flag') |
108 | end | 108 | end |
109 | 109 | ||
110 | should 'setting_changed be true for all changed fields' do | 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 | obj.save | 112 | obj.save |
113 | obj.name = 'another nme' | 113 | obj.name = 'another nme' |
114 | obj.flag = true | 114 | obj.flag = true |