обновить хэш параметров в рельсах - PullRequest
1 голос
/ 14 октября 2019

Мне нужен способ изменить хэш параметров. Я попробовал пару вещей, но ничего из этого не сработало.

Unpermitted parameters: :players, :leaders

Параметры

{"utf8"=>"✓", "authenticity_token"=>"asa", "user"=>{"first_name"=>"anikeeet", "last_name"=>"tiwariii", "friend_attributes"=>{"players"=>"50589,50590", "leaders"=>"16,6,18", "phone_number"=>"", "title"=>"aasdassd", "role"=>"abcdef"}}}

Я пробовал вот так

(friend_params.dig(:friend_attributes) || []).each do |_, attributes|
      attributes['players'] = attributes['players'].split(',').map(&:to_i)
      attributes['leaders'] = attributes['leaders'].split(',').map(&:to_i)
    end

так

(friend_params.dig(:friend_attributes) || []).each do |key, val|
  friend_params["friend_attributes"]["#{key}"] = val.split(',').map(&:to_i) if key == 'players' || key == 'leaders'
end

этопуть

(params.dig(:user, :friend_attributes) || []).each do |key, val|
  params["user"]["friend_attributes"]["#{key}"] = val.split(',').map(&:to_i) if key == 'players' || key == 'leaders'
end

и так

 if (attributes = params.dig(:user, :friend_attributes))
      %i[players leaders].each do |key|
        next unless attributes.has_key?(key)
        attributes[key] = attributes[key].split(',').map(&:to_i)
      end
    end

Но ни один из способов не сработал для меня. Я делюсь своим полным кодом контроллера

class FriendsController < ApplicationController

  def update
    # (friend_params.dig(:friend_attributes) || []).each do |_, attributes|
    #   attributes['players'] = attributes['players'].split(',').map(&:to_i)
    #   attributes['leaders'] = attributes['leaders'].split(',').map(&:to_i)
    # end

    # (friend_params.dig(:friend_attributes) || []).each do |key, val|
    #   friend_params["friend_attributes"]["#{key}"] = val.split(',').map(&:to_i) if key == 'players' || key == 'leaders'
    # end

    # (params.dig(:user, :friend_attributes) || []).each do |key, val|
    #   params["user"]["friend_attributes"]["#{key}"] = val.split(',').map(&:to_i) if key == 'players' || key == 'leaders'
    # end

     if (attributes = params.dig(:user, :friend_attributes))
       %i[players leaders].each do |key|
         next unless attributes.has_key?(key)
         attributes[key] = attributes[key].split(',').map(&:to_i)
       end
     end


    if current_user.update(friend_params)
      render json: { success: true }
    else
      render json: {error: "something went wrong"}
    end
  end

  private
  def friend_params
    params.require(:user).permit(:first_name, :last_name, friend_attributes: [:phone_number, :title, :role, :players, :leaders])
  end
end

Ассоциация

Class User < ApplicationRecord 
  has_one :friend, foreign_key: :user_id, dependent: :destroy
  accepts_nested_attributes_for :friend
end

class Friend < ApplicationRecord
  self.table_name = 'schema.friends'
  belongs_to :user
end

Игроки и лидеры - это поле массива, хранящееся в таблице друзей. Кто-нибудь может сказать, что я делаю неправильно?

Ответы [ 2 ]

2 голосов
/ 14 октября 2019

Примерно так будет работать:

if (attributes = params.dig(:user, :friend_attributes))
  %i[players leaders].each do |key|
    next unless attributes.has_key?(key)
    attributes[key] = attributes[key].split(',').map(&:to_i)
  end
end

В настоящее время проблема заключается в (friend_params.dig(:friend_attributes) || []).each, который проходит через пары ключ-значение или отсутствует в пустом массиве. Затем вы вызываете метод #[] для значения (которое является строкой). например. "50589,50590"['players'] пытается найти подстроку 'players' внутри "50589,50590" результат должен быть nil. Затем следует исключение «NoMethodError: undefined метод` split »для nil: NilClass».

Вы должны просто использовать возвращенную коллекцию, а не циклически перебирать пары ключ-значение.


Лучший вопрос: зачем вам вообще нужно преобразовывать параметры?

Разве представление не может быть организовано таким образом, чтобы обеспечить параметры в формате массива?

<input name="user[friend_attributes][players][]" type="checkbox" value="1" />
<input name="user[friend_attributes][players][]" type="checkbox" value="2" />
<input name="user[friend_attributes][players][]" type="checkbox" value="3" />

Отправит массив чисел в контроллер для начала, исключая необходимость преобразования параметров в правильный формат.

Примечание: Если вы предоставите параметры в вышеуказанном формате, вам следуетобновите ваши разрешенные параметры:

params.require(:user).permit(:first_name, :last_name, friend_attributes: [:phone_number, :title, :role, players: [], leaders: []])
# players and leaders are now expecting an array instead of a scalar value
0 голосов
/ 14 октября 2019

Ваши параметры - это хэш, метод require и allow - это метод экземпляра ActionController :: Parameters. Также вы пытаетесь копать по символу вместо строки.

params.dig('user', 'friend_attributes')

Или, если вы хотите продолжить использовать символ, вы можете написать его так:

params.with_indifferent_access.dig(:user, :friend_attributes)

Пожалуйста, прочитайте больше о методе with_indifferent_access.

:)

...