Pass array of ids as a single hidden field

时间:2016-10-15 17:28:24

标签: ruby-on-rails ruby forms hidden-field

I have a message that has recipients, wired this way:

class Message < ApplicationRecord
  has_many :message_recipients
  has_many :recipients, through: :message_recipients, source: :user
end

I pass the user_ids as GET param to the new message form to pre-propulate recipients:

def new
  @message = Message.new
  @message.recipients = User.where(id: params[:user_ids])
end

Have set up strong_params like so:

def message_params
  params.require(:message).permit(
    :subject,
    :body,
    recipient_ids: []
  )
end

And have set up the form like so:

= simple_form_for @message do |f|
  = f.hidden_field :recipient_ids

I expected all this to just work, but then I realized that this hidden field alone is not treated as scalar so it's ignored by strong_params (otherwise I would have to do :recipient_ids instead of recipient_ids: [] but then it would not end up as an array anyway).

So then I thought about doing this:

  = hidden_field_tag 'message[recipient_ids][]', @message.recipients.pluck(:id)

But then the controller would parse the params like this:

message_params[:recipient_ids] => ["1, 2, 3"]

instead of:

message_params[:recipient_ids] => ["1", "2", "3"]

So I had to fallback to the ugly:

- @message.recipient_ids.each do |recipient_id|
  = hidden_field_tag 'message[recipient_ids][]', recipient_id

And then it all worked.

But I feel this is far from ideal because I now have dozens of DOM elements lying around instead of potentially just one.

Do you know of any better way to achieve the same result ?

Maybe Rails should be a little bit clever when receiving a single scalar field of numbers split by commas ?

Well, what do you guys think ?

Rails version: 5.0.0

2 个答案:

答案 0 :(得分:0)

recipient_ids保留为message_params

中的简单属性
def message_params
  params.require(:message).permit(
    :subject,
    :body,
    :recipient_ids
  )
end

然后做message_params[:recipient_ids].split(","

所以它将是

"1, 2, 3".split(",")
 => ["1", " 2", " 3"] 

答案 1 :(得分:0)

yourmodel.rb

message_params=(val)
  if val.class==String #if we pass a string
    super(val.split(',')) #split back into array and assign value
  else
    super(val)
  end
end

然后在表单构建器中(假设simpleform)

f.input :message_params, 
  as: :hidden, 
  input_html { 
    value: @yourmodel.message_params.join(',') #split array back into comma separated string
  }