0

i have the following form select list with multiple set to true:

  <%= form.select(:to, options_for_select(GoContact.all.collect{|e| ["#{e.en_name} - #{e.cn_name}", e.email] }), {:include_blank => false}, {multiple: true} ) %><br>

the only problem is that the array returned always contain a blank entry as the first entry, all the other selections will be after that. how can i remove this blank entry from the array?

  this is the output:
  Parameters: {"lalaemail"=>{"from"=>"will@gmail.com", "to"=>["", "will@gmail.com", "andrew@gmail.com"], "subject"=>"tset", "body"=>"tset"}, "commit"=>"Save Lalaemail", "utf8"=>"✓", "authenticity_token"=>"[FILTERED]"}

also, when i save this to the database, the 'to' field is always empty no matter what i selected from the list. how can i fix that, i'd like all the emails selected to be saved?

gkeepa
  • 131
  • 1
  • 1
  • 10

3 Answers3

5

To remove the empty string from the array, use #reject.

params["lalaemail"]["to"].reject(&:blank?)

But let's address your second question before we clean that up:

First ensure that your Email table has to column with array set to true—if it doesn't, create a migration for it (and maybe give it a better name, like recipients):

class AddRecipientsColumnToEmail < ActiveRecord::Migration[5.1]
  def change
    add_column :emails, :recipients, :text, array: true, default: []
  end
end

After you run that migration, each instance of an email will have the ability to save as many recipients as you want.

Now, let's circle back to using #reject.

Instead of manipulating the dirty recipients array you get back from the view in your controller, let's offload removing the empty strings to the Email model:

Email.rb

class Email < ApplicationRecord
  # Your associations
  # Your validations

  # Define a before_validation hook that will sanitize your input
  # Example:
  before_validation :sanitize_recipients

  # More public model methods you may have

  private

  # Define your sanitation method; consider if there's anything else 
  # you'd want to do to clean the data--perhaps remove duplicates?
  #
  # Returns an Array.
  def sanitize_recipients
    self.recipients = recipients.reject(&:blank?)&.uniq
  end
end

If you're unfamiliar with before_validation--it's built-in to Rails and basically tells your model: "Hey wait, before you check this data, let me do this first.", where "this" can be any method you define. In this case, we defined a method to sanitize the recipients Array of any duplicate or blank values.

And voila, the empty string you get back is no longer an issue, and you have the ability to save all of an email's recipients.

  • thanks for the reply, i actually found out how to save an array using strong param: https://stackoverflow.com/questions/16549382/how-to-permit-an-array-with-strong-parameters . so there is no way to remove the blank entry via some configuration? – gkeepa Apr 11 '18 at 13:56
  • Using strong parameters isn't an alternative to what I posted above, you would need to do both. You cannot save an array to your database if you don't have the column configured to receive one. Strong parameters are just a means of filtering information sent from your view to your controller, they have no bearing on your ability to save data to the database. The only configuration to remove the blank string would be to remove `include_blank: true`, because that's all `include_blank` is doing... creating an empty string as an item in your array. – ActiveModel_Dirty Apr 11 '18 at 14:58
  • Actually, requiring the `array` field may not be necessary depending on which database you're using. I can only speak to Postgres. SQLite or MySQL might handle that differently. If that's the case, you can skip the migration step--but the rest of my answer would still apply to your case.You can still offload the task of sanitizing it to the model. – ActiveModel_Dirty Apr 11 '18 at 15:34
0

Your syntax seems to be right. It is kind of hard to read it in one line.

Could you do a database dump and paste it? Perhaps there is the problem.

A not very orthodox way could be:

 params['lalaemail']['to'].shift

I hope this works for you.

OfficeYA
  • 737
  • 8
  • 15
0

thanks all, im sure there are many other ways of achieving the same result, just want to post how i did it:

problem 1: saving array to table: how to permit an array with strong parameters

params.require(:fishemail).permit(:from, {:to=>[]}, :subject, :body)

problem 2: removing the extra blank space in the array from view list selection, added "include_hidden: false":

   <%= form.select(:to, options_for_select(GoContact.all.collect{|e| ["#{e.en_name} - #{e.cn_name}", e.email] }),
{include_hidden: false}, {multiple: true, required: true} ) %>
gkeepa
  • 131
  • 1
  • 1
  • 10