1

Looks like my form does what is expected to do - sends the right value, but its not being saved in db. Check_box_tag takes data from enum (I use enum because I use same data for select field):

class UserProfile < ApplicationRecord
  enum locations: { Kursenai: 0, Papiskes: 1, Versiai: 2 }

And in form_for:

<% UserProfile.locations.each do |key, val| %>
  <%= f.label key %>
  <%= check_box_tag('user_profile[locations][]', val, false, id: val) %>
<% end %>

But it fails to update:

'["0", "1"]' is not a valid locations

Postgres:

t.integer "locations", array: true

So I thought it fails because row type is integer, but this:

<%= check_box_tag('user_profile[locations][].to_i', val.to_i, false, id: val) %>

removed error but user field :locations is still nil. What do I miss?

Strong params:

..permit(locations: [])

p.s. if you think this could be done in a better way - please feel free to show.

Julius Dzidzevičius
  • 10,775
  • 11
  • 36
  • 81

2 Answers2

1

Why are you using enum? I think it's better to create a new model Location and connect with UserProfile via HABTM relation. It would fullfill the Database normalization and easier to work with.

Edit:

class UserProfile < ApplicationRecord
  has_and_belongs_to_many :locations
end

class Location < ApplicationRecord
  has_and_belongs_to_many :user_profiles
end

and you need to create 3 location records

Location.create(name: 'Kursenai')
Location.create(name: 'Papiskes')
Location.create(name: 'Versiai')

Use any standart queries, joins. You can built a form like here: Rails 4 - checkboxes for has_and_belongs_to_many association

or Multiple select issue with a HABTM relationship using Rails 4

kolas
  • 754
  • 5
  • 16
  • And what then? I will still have hashed enum there – Julius Dzidzevičius Oct 20 '17 at 08:13
  • Thanks, @kolas, but I can't see serious reasons to do like this. Enum is much lighter and in this approach I would create many static objects, while including enum in class seems much lighter job. I am dealing now with simple array of strings and I hash it because later I might remove or add items to it. But i think I will definitely use this way if my array of strings will become array of objects. Thanks for info. Please correct me if I am wrong – Julius Dzidzevičius Oct 21 '17 at 07:27
1

Why?

Because '["0", "1"]' is considered as string and it is not among values you mentioned in enum i.e 0,1,2.

You can't achieve it directly as enum requires field type to hold single value.But in your case it's an array.

How to achieve?

class UserProfile < ApplicationRecord
  # value should store as array not as string.
  serialize :locations, Array

  # define your own enum by creating static var.U can use Array or Hash structure.
  # Here I am using Hash.
  # ENUM_LOCATIONS = ["Kursenai", "Papiskes", "Versiai"]
  ENUM_LOCATIONS = {"Kursenai": 0, "Papiskes": 1, "Versiai": 2}


  # Now modify you getter little bit to return enumed values
  def locations
   res = []
   self[:locations].each{|v| ENUM_LOCATIONS.is_a?(Array) ? res << ENUM_LOCATIONS[v.to_i] : res << ENUM_LOCATIONS.key(v.to_i).to_s}
   res    
  end

end

That's it.

halfer
  • 19,824
  • 17
  • 99
  • 186
krishnar
  • 2,537
  • 9
  • 23