Search code examples
ruby-on-railsrubygrails-controller

Saving a list of emails from a form-text input into Models email_list attribute (array)


My goal is to when adding a new product with the new product form, to have an input where one can add a list of emails separated by a space. The list of emails in this string field would be saved as an array of emails in the email_list array attribute of the Product model. This way each product has many emails. (later an email will be sent to these users to fill out questionaire, once a user fills it out there name will be taken off this list and put on completed_email_list array.

I am relatively new to rails, and have a few questions regarding implementing this. I am using postgresql, which from my understanding I do not need to serialize the model for array format because of this. Below is what I have tried so far to implement this. These may show fundamental flaws in my thinking of how everything works.

My first thinking was that I can in my controllers create action first take params[:email].split and save that directly into the email_list attribute (@product.email_list = params[:email].split. It turns out that params[:email] is always nil. Why is this? (this is a basic misunderstanding I have)(I put :email as accepted param).

After spending a long time trying to figure this out, I tried the following which it seems works, but I feel this is probably not the best way to do it (in the code below), which involves creating ANOTHER attribute of string called email, and then splitting it and saving it in the email_list array :

   @product.email_list = @product.email.split

What is the best way to actually implement this? someone can clear my thinking on this I would be very grateful.

Cheers

Products.new View

<%= simple_form_for @product do |f| %>
  <%= f.input :title, label:"Product title"  %>
  <%= f.input :description  %>
  <%= f.input :email %>
  <%= f.button :submit %>
<%end %>

Products Controller

class ProductsController < ApplicationController
  before_action :find_product, only: [:show, :edit, :update, :destroy]

  def index
    if params[:category].blank?
      @products= Product.all.order("created_at DESC")
    else
      @category_id=Category.find_by(name: params[:category]).id
      @products= Product.where(:category_id => @category_id).order("created_at DESC")
    end
  end

  def new
    @product=current_user.products.build
    @categories= Category.all.map{|c| [c.name, c.id]}
  end

  def show
  end

  def edit
    @categories= Category.all.map{|c| [c.name, c.id]}
  end

  def update
    @product.category_id = params[:category_id]

    if @product.update(product_params)
      redirect_to product_path(@product)
    else
      render 'new'
    end
  end

  def destroy
    @product.destroy
    redirect_to root_path
  end

  def create
    @product=current_user.products.build(product_params)
    @product.category_id = params[:category_id]
    @product.email_list = @product.email.split
    if @product.save
      redirect_to root_path
    else
      render 'new'
    end
  end

  private

  def product_params
    params.require(:product).permit(:title, :description, :category_id, :video, :thumbnail,:email, :email_list)
  end

  def find_product
    @product = Product.find(params[:id])
  end
end

Solution

  • To solve your original issue

    @product.email_list = params[:email].split. It turns out that params[:email] is always nil

    :email is a sub key of :product hash, so it should be:

    @product.email_list = params[:product][:email].split
    

    Demo:

    params = ActionController::Parameters.new(product: { email: "[email protected] [email protected]" })
    params[:email] # => nil
    params[:product][:email] # => "[email protected] [email protected]"