What I need: I have a groups table and for -certain- groups I want user to be able to update only the name attribute. While trying to update other attributes, page must flash an error message. I'd like to realise it in model-level.
What I've done so far: I thought about making before_update
callback into my Group
model that asks @group.changed
and when it gets back an array that contains attributes user must not be able to update then model raises an error. I combined my existing solution from here and here like this:
before_update :check_update_params
protected
def check_update_params
if self.only_name_update_allowed?
changed = self.changed
# I'd like to have somekind of empty-value check here
# that ignores non-changed empty string and boolean-fields
if changed.present? && changed != ["name", "updated_at"]
raise I18n.t('my_app.groups.errors.only_name_update_available')
end
end
end
Problem: Everything is ok except empty values interpreted differently in form and in db. If I log out the changed
variable then I get an array that also includes some attributes that I didn't change in form but db interprets them as changed. That is due to the fact that form sends empty checkbox with a value of 0
which is saved in db as false
but previous value in db was nil
. Same problem is with text-fields- form form comes an empty string value like ""
but database has a value of nil
.
Here are some illustrating examples of my empty-value problem:
irb(main):130:0* Group.all.each do |g|
irb(main):131:1* puts "name: #{g.name} my_boolean_attr: #{g.my_boolean_attr}"
irb(main):132:1> end
Group Load (0.7ms) SELECT "groups".* FROM "groups"
name: group1 my_boolean_attr:
name: group2 my_boolean_attr:
name: group3 my_boolean_attr:
name: group4 my_boolean_attr:
name: group5 my_boolean_attr:
name: group6 my_boolean_attr: false
name: group7 my_boolean_attr: false
name: group8 my_boolean_attr: false
name: group9 my_boolean_attr: false
Similar problem with text field:
irb(main):130:0* Group.all.each do |g|
irb(main):131:1* puts "name: #{g.name} my_string_attr: #{g.my_string_attr == ""}"
irb(main):132:1> end
Group Load (0.7ms) SELECT "groups".* FROM "groups"
name: group1 my_string_attr: false
name: group2 my_string_attr: false
name: group3 my_string_attr: false
name: group4 my_string_attr: false
name: group5 my_string_attr: false
name: group6 my_string_attr: false
name: group7 my_string_attr: false
name: group8 my_string_attr: true
name: group9 my_string_attr: true