AmirolAhmad AmirolAhmad - 27 days ago 11
Ruby Question

Ruby update all same object data in hash array for JSON.parse

So

a = first
is

=> <Ng::EntityConfiguration id: 15903, entity_id: 1, entity_type: "Ng::Company", key: "wpa2.psk", value: "[{"ssid":"Main-Hall-Staff","password":"abc123","dhcp":"Enabled"},{"ssid":"Main-Hall-Guest","password":"def456","dhcp":"Disabled"}]", created_at: "2016-11-08 11:03:51", updated_at: "2016-11-08 11:03:51", name: "WIFI/Main Hall">


I have
a.value
which is will return:

"[
{\"ssid\":\"Main-Hall-Staff\",\"password\":\"abc123\"},
{\"ssid\":\"Main-Hall-Guest\",\"password\":\"def456\"}
]"


My question is, how to update both password value and save it?

new_pass1 = 'xyz123'
new_pass2 = 'xyz321'


I have tried code (below) but this will only update first password if i only have one hash_array.

Here is my full code

def encrypt_pass
# get the actual password
parse = JSON.parse(self.value)
get_pass = parse.last['password']

# encrypt the password
crypt = ActiveSupport::MessageEncryptor.new(ENV["SECRET_KEY_BASE"])
encrypted = crypt.encrypt_and_sign(get_pass)

# save the new encrypted password
parse.first['password'] = encrypted
encrypt_pass = parse.to_json
self.value = encrypt_pass
end

Answer

Just to be clear, you're trying to update both the Main-Hall-Staff password and the Main-Hall-Guest password (all passwords) from your record to be the encrypted version of themselves? I'm assuming this method is called in a before_save callback of some sort? If you show more code related to the model I can give you more details.

def encrypt_pass
  # Changed the name to devises, always use easy to understand naming
  # Also rescuing from a JSON parse error, this isnt always recommended
  # as it hides other errors that might be unrelated to parsing
  devices = JSON.parse(self.value) rescue []
  crypt = ActiveSupport::MessageEncryptor.new(ENV["SECRET_KEY_BASE"])

  devices.each do |device|
    # get the actual password
    password = device['password']

    # encrypt the password
    encrypted_pass = crypt.encrypt_and_sign(password)

    # Save the encrypted password
    device['password'] = encrypted_pass
  end

  self.value = devices.to_json
end

Hopefully you have some logic surrounding when this method is called as you dont want to encrypt an already encrypted password.

Comments