将表单文本输入的电子邮件列表保存到模型 email_list 属性(数组)
Saving a list of emails from a form-text input into Models email_list attribute (array)
我的目标是在使用新产品表单添加新产品时,提供一个输入,其中可以添加由 space 分隔的电子邮件列表。此字符串字段中的电子邮件列表将保存为 Product
模型的 email_list
数组属性中的电子邮件数组。这样每个产品都有很多电子邮件。 (稍后将向这些用户发送一封电子邮件以填写问卷,一旦用户填写完成,姓名将从该列表中删除并放入 completed_email_list
数组。
我对 rails 比较陌生,有几个关于实现它的问题。我正在使用 postgresql,据我所知,我不需要因此而将模型序列化为数组格式。以下是我迄今为止为实现这一目标所做的尝试。这些可能表明我对一切运作方式的思考存在根本性缺陷。
我的第一个想法是,我可以在我的控制器中创建动作,首先采用参数[:email].split 并将其直接保存到 email_list 属性中 (@product.email_list = params[:email].split
。结果是 params[:email]
总是nil
。这是为什么?(这是我的一个基本误解)(我把:email
作为接受的参数)。
在花了很长时间试图解决这个问题之后,我尝试了以下似乎可行的方法,但我觉得这可能不是最好的方法(在下面的代码中),它涉及创建另一个属性名为 email 的字符串,然后将其拆分并保存在 email_list 数组中:
@product.email_list = @product.email.split
实际实现它的最佳方法是什么?有人可以清除我对此的想法,我将不胜感激。
干杯
Products.new 查看
<%= simple_form_for @product do |f| %>
<%= f.input :title, label:"Product title" %>
<%= f.input :description %>
<%= f.input :email %>
<%= f.button :submit %>
<%end %>
产品控制器
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
我会说你拥有的东西非常好,除了你在 @product.email_list=@product.email.split
中做的额外舞蹈,这看起来很奇怪。
相反,我在表单中有一个 emails
参数,在模型中有一个 #emails=
方法(而不是 email
和 #email=
):
def emails=(val)
self.email_list = val.split
end
或者,您可以在控制器中执行此操作,而不是使用上述方便的 #emails=
方法,类似于您处理 category_id
:
的方式
@product = current_user.products.build(product_params)
@product.category_id = params[:category_id]
@product.email_list = product_params[:emails].split
因为您需要验证您的电子邮件并使其更清晰,我会创建一个 email
table,使 Product
table 接受 Email
属性并使用 cocoon gem 来获得一个带有多个电子邮件输入的动态嵌套表单。
1) 型号
class Product < ActiveRecord::Base
has_many :emails, dependent: :destroy
accepts_nested_attributes_for :emails, reject_if: :all_blank, allow_destroy: true
end
class Email < ActiveRecord::Base
belong_to :product
validates :address, presence: true
end
2) 控制器
class ProductsController < ApplicationController
def new
@product = current_user.products.build
end
def create
@product = current_user.products.build(product_params)
if @product.save
redirect_to root_path
else
render 'new'
end
end
private
def product_params
params.require(:project).permit(:title, :description, :category_id, :video, :thumbnail, emails_attributes: [:id, :address, :_destroy])
end
end
3) 查看
<%= simple_form_for @product do |f| %>
<%= f.input :title, label:"Product title" %>
<%= f.input :description %>
<%= f.association :category %>
<div id="emails">
<%= f.simple_fields_for :emails do |email| %>
<%= render 'emails_fields', f: email %>
<div class="links">
<%= link_to_add_association 'add email', f, :emails %>
</div>
<%= end %>
</div>
<%= f.button :submit %>
<% end %>
在你的 _emails_fields
部分:
<div class="nested-fields">
<%= f.input :address %>
<%= link_to_remove_association "Remove email", f %>
</div>
然后设置 cocoon 的 gem 和 javascript 就可以了。
解决您原来的问题
@product.email_list = params[:email].split. It turns out that params[:email] is always nil
:email
是:product
散列的子键,所以应该是:
@product.email_list = params[:product][:email].split
演示:
params = ActionController::Parameters.new(product: { email: "first@email.com last@email.com" })
params[:email] # => nil
params[:product][:email] # => "first@email.com last@email.com"
我的目标是在使用新产品表单添加新产品时,提供一个输入,其中可以添加由 space 分隔的电子邮件列表。此字符串字段中的电子邮件列表将保存为 Product
模型的 email_list
数组属性中的电子邮件数组。这样每个产品都有很多电子邮件。 (稍后将向这些用户发送一封电子邮件以填写问卷,一旦用户填写完成,姓名将从该列表中删除并放入 completed_email_list
数组。
我对 rails 比较陌生,有几个关于实现它的问题。我正在使用 postgresql,据我所知,我不需要因此而将模型序列化为数组格式。以下是我迄今为止为实现这一目标所做的尝试。这些可能表明我对一切运作方式的思考存在根本性缺陷。
我的第一个想法是,我可以在我的控制器中创建动作,首先采用参数[:email].split 并将其直接保存到 email_list 属性中 (@product.email_list = params[:email].split
。结果是 params[:email]
总是nil
。这是为什么?(这是我的一个基本误解)(我把:email
作为接受的参数)。
在花了很长时间试图解决这个问题之后,我尝试了以下似乎可行的方法,但我觉得这可能不是最好的方法(在下面的代码中),它涉及创建另一个属性名为 email 的字符串,然后将其拆分并保存在 email_list 数组中:
@product.email_list = @product.email.split
实际实现它的最佳方法是什么?有人可以清除我对此的想法,我将不胜感激。
干杯
Products.new 查看
<%= simple_form_for @product do |f| %>
<%= f.input :title, label:"Product title" %>
<%= f.input :description %>
<%= f.input :email %>
<%= f.button :submit %>
<%end %>
产品控制器
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
我会说你拥有的东西非常好,除了你在 @product.email_list=@product.email.split
中做的额外舞蹈,这看起来很奇怪。
相反,我在表单中有一个 emails
参数,在模型中有一个 #emails=
方法(而不是 email
和 #email=
):
def emails=(val)
self.email_list = val.split
end
或者,您可以在控制器中执行此操作,而不是使用上述方便的 #emails=
方法,类似于您处理 category_id
:
@product = current_user.products.build(product_params)
@product.category_id = params[:category_id]
@product.email_list = product_params[:emails].split
因为您需要验证您的电子邮件并使其更清晰,我会创建一个 email
table,使 Product
table 接受 Email
属性并使用 cocoon gem 来获得一个带有多个电子邮件输入的动态嵌套表单。
1) 型号
class Product < ActiveRecord::Base
has_many :emails, dependent: :destroy
accepts_nested_attributes_for :emails, reject_if: :all_blank, allow_destroy: true
end
class Email < ActiveRecord::Base
belong_to :product
validates :address, presence: true
end
2) 控制器
class ProductsController < ApplicationController
def new
@product = current_user.products.build
end
def create
@product = current_user.products.build(product_params)
if @product.save
redirect_to root_path
else
render 'new'
end
end
private
def product_params
params.require(:project).permit(:title, :description, :category_id, :video, :thumbnail, emails_attributes: [:id, :address, :_destroy])
end
end
3) 查看
<%= simple_form_for @product do |f| %>
<%= f.input :title, label:"Product title" %>
<%= f.input :description %>
<%= f.association :category %>
<div id="emails">
<%= f.simple_fields_for :emails do |email| %>
<%= render 'emails_fields', f: email %>
<div class="links">
<%= link_to_add_association 'add email', f, :emails %>
</div>
<%= end %>
</div>
<%= f.button :submit %>
<% end %>
在你的 _emails_fields
部分:
<div class="nested-fields">
<%= f.input :address %>
<%= link_to_remove_association "Remove email", f %>
</div>
然后设置 cocoon 的 gem 和 javascript 就可以了。
解决您原来的问题
@product.email_list = params[:email].split. It turns out that params[:email] is always nil
:email
是:product
散列的子键,所以应该是:
@product.email_list = params[:product][:email].split
演示:
params = ActionController::Parameters.new(product: { email: "first@email.com last@email.com" })
params[:email] # => nil
params[:product][:email] # => "first@email.com last@email.com"