-
-
Save ozgun/e062ff629708286f7211 to your computer and use it in GitHub Desktop.
| # File: app/models/concerns/boolean_store_accessor.rb | |
| # | |
| # When we submit a form in order to update a model, a booelan/checkbox field is posted | |
| # as '1' or '0', and if we are using ActiveRecord::Store, posted value is stored in | |
| # database as '1' or '0'. By the help of this module, we store '1' and '0' | |
| # values as `true` or `false`. | |
| # | |
| # Example usage: | |
| # | |
| # ``` | |
| # class Page < ActiveRecord::Base | |
| # extend BooleanStoreAccessor | |
| # store :settings, accessors: [:hide_from_navigation] | |
| # boolean_store_accessor :hide_from_navigation | |
| # end | |
| # | |
| # page = Page.first | |
| # page.hide_from_navigation? #=> false | |
| # page.hide_from_navigation = true | |
| # page.save | |
| # page.hide_from_navigation? #=> true | |
| # page.settings #=> {"hide_from_navigation"=>true} | |
| # ``` | |
| # | |
| module BooleanStoreAccessor | |
| def boolean_store_accessor(attr_name) | |
| define_method "#{attr_name}=".to_sym do |value| | |
| values = ['1', true] | |
| super((values.include?(value)) ? true : false) | |
| end | |
| define_method attr_name do | |
| values = [nil, false, '0'] | |
| (values.include?(super())) ? false : true | |
| end | |
| define_method "#{attr_name}?".to_sym do | |
| send(attr_name) | |
| end | |
| end | |
| end |
Hi @esale, thanks for the feedback. I don't think I've tested it with attr_accessor. I wonder if you could paste your code here so I can try to make BooleanStoreAccessor work with attr_accessor. Thanks.
@esale give this a try:
module BooleanStoreAccessor
def boolean_store_accessor(attr_name)
define_method "#{attr_name}=".to_sym do |value|
values = ['1', true]
new_value = values.include?(value) ? true : false
begin
super(new_value)
rescue NoMethodError => e # This is hack for `attr_accessor`
if e.message.match?(/super: no superclass method/)
instance_variable_set("@#{attr_name}", new_value)
else
raise e
end
end
end
define_method attr_name do
values = [nil, false, '0']
stored_value =
begin
super()
rescue NoMethodError => e # This is hack for `attr_accessor`
if e.message.match?(/super: no superclass method/)
instance_variable_get("@#{attr_name}")
else
raise e
end
end
(values.include?(stored_value)) ? false : true
end
define_method "#{attr_name}?".to_sym do
send(attr_name)
end
end
endOf course!
This is how I use your module:
store_accessor :hstore_field, :max, :min, :avg, :sent
extend BooleanStoreAccessor
boolean_store_accessor :sentand it works as a charm.
Sadly, when I try this (extend inserted before):
attr_accessor :prueba
boolean_store_accessor :pruebaIt doesn't work. I also tried attr_reader instead of attr_accessor without success. The error I get is:
super: no superclass method `prueba=' for #<Modelo:0x00007f0b30042e40> Did you mean? prueba prueba?
Thanks.
@ozgun, your new code works!
Thanks again!
@esale great, thanks!
Thanks for this!
Thanks for this!
My pleasure :)
Thanks for this! Here's a small change that allows defining a series of multiple attributes in the same signature as store_accessor.
boolean_store_accessor :eula_agreement, :subscribemodule BooleanStoreAccessor
def boolean_store_accessor(*attr_names)
attr_names.each do |attr_name|
define_method "#{attr_name}=".to_sym do |value|
values = ['1', true]
new_value = values.include?(value) ? true : false
begin
super(new_value)
rescue NoMethodError => e # This is hack for `attr_accessor`
if e.message.match?(/super: no superclass method/)
instance_variable_set("@#{attr_name}", new_value)
else
raise e
end
end
end
define_method attr_name do
values = [nil, false, '0']
stored_value =
begin
super()
rescue NoMethodError => e # This is hack for `attr_accessor`
if e.message.match?(/super: no superclass method/)
instance_variable_get("@#{attr_name}")
else
raise e
end
end
(values.include?(stored_value)) ? false : true
end
define_method "#{attr_name}?".to_sym do
send(attr_name)
end
end
end
endThanks @dylanfisher . I haven't tested it yet but it looks good to me at first glance. 👍
Great, thanks! I tried to make it work with attr_accessor but it didn't. Any advise? Regards.