【问题标题】:Combining two form input into one db entry将两个表单输入组合到一个数据库条目中
【发布时间】:2017-12-21 20:19:25
【问题描述】:

我正在尝试将两个表单输入组合到一个数据库条目参数中。在我的表单中,我有几个小时(6-22)和分钟(0-55)的下拉列表,在我的数据库中,我有一个“开始”列,我希望将一个整数计算为 start_hour * 60 + start_mins。

我的表格是这样的:

<div class="form-group">
  <%= f.label :start_hour %>
  <%= f.select :start_hour, 6 .. 22, class: 'form-control' %>

  <%= f.label :start_mins %>
  <%= f.select :start_mins, 00 .. 55, class: 'form-control' %>
</div>

在我的模型中,我添加了 before_validation:

before_validation :generate_starttime

 def generate_starttime
      self.start= '#{:start_hour}' * 60 + '#{start_mins}'
 end

我的控制器有问题 - 我不知道如何将 start 传递给数据库。我将参数传递为:

def create
    @klass = Klass.new(contact_params)
    if @klass.save
        flash[:success] = "Class added"
    else
        flash[:error] = @klass.errors.full_messages.join(", ")
    end
    redirect_to new_klass_path
end

我尝试了 self.start 和 @start 和 :start 并没有真正起作用 - 但我承认我一直处于黑暗中。现在我收到错误:

#Did 的未定义方法 `start' 你的意思是?状态

对于“self.start”版本和

未定义的方法 `start_mins' 用于 # 你有没有 意思是?开始start_was

对于 ":start" 和 "@start" 版本 :D 我觉得我在这里缺少一些非常基础的东西。你能指出我正确的方向吗?

如果这很重要,那就是我的数据库架构:

create_table "klasses", force: :cascade do |t|
  t.string  "name"
  t.string  "teacher"
  t.string  "day"
  t.integer "start"
  t.integer "duration"
end

【问题讨论】:

标签: ruby-on-rails ruby database forms


【解决方案1】:

这是一种可能的解决方案。请注意,下面的代码示例假设模型名称为 Klass 并根据它命名所有内容。随意更新命名以服务您的应用程序名称

您的视图将类似于:

<%= form_with(model: klass, local: true) do |f| %>
...
<div class="form-group">
  <%= f.label :start_hour %>
  <%= f.select :start_hour, 6 .. 22, class: 'form-control' %>

  <%= f.label :start_mins %>
  <%= f.select :start_mins, 00 .. 55, class: 'form-control' %>
</div>
...
<% end %>

在你的控制器中,你定义一个 before_action 来计算起始参数

class KlassesController < ApplicationController
  before_action :fix_params, only: [:create, :update]
...

  private

    def klass_params
      params.require(:klass).permit(:name, :teacher, :day, :start, :duration)
    end

    def fix_params
      if params[:klass].blank?
        # parent not provided
        return
      end
      start_hour = params[:klass].delete(:start_hour)
      start_mins = params[:klass].delete(:start_mins)

      if start_hour.blank? || start_mins.blank?
        # consider handling this case
      else
        params[:klass][:start] = start_hour.to_i * 60 + start_mins.to_i
      end
    end

...
end

和你的创建处理程序

def create
    @klass = Klass.new(klass_params)
    if @klass.save
        flash[:success] = "Class added"
    else
        flash[:error] = @klass.errors.full_messages.join(", ")
    end
    redirect_to new_klass_path
end

希望这会有所帮助!

【讨论】:

  • 谢谢!有用!唯一的问题是:在第一行使用您的解决方案时出现错误:“未定义的局部变量或方法 `klass'”(是的,我的模型名为 Klass)。我使用 就是这样工作的,有什么区别?
  • 老实说,不确定问题出在哪里。来自 Rails 5.1 form_with is just a unification of form_for and form_tag。您是否尝试过在我的示例中提供@ 登录&lt;%= form_with(model: @klass, local: true) do |f| %&gt;
  • 是的,我试过并遇到了一些其他问题(抱歉,现在无法检查到底是哪一个,我明天再检查)。谢谢你的帮助!
【解决方案2】:

尝试将attr_accessor :start_hours, :start_mins 添加到您的模型中。此外,将您的contact_params 中的这两个字段列入白名单。您可以通过here 找到更多关于attr_accessor 的信息。

【讨论】:

  • 谢谢!这有助于摆脱我得到的错误。但是我仍然有将 :start 值传递到数据库的问题。现在该条目已添加,但该值设置为 0。
  • 我会更改模型,以便您实际上将start_hoursstart_mins 保存到数据库中。 start 然后可以简单地成为模型上的一个方法,用于计算您需要的时间。这样,您还可以使用相同的表单编辑模型,因为字段仍然是分开的。
  • 但是我在任何时候都不需要这两个单独的 val,这些只是为了使表单更具可读性(我可以使用 text_field 并需要 HH:MM 表单,只是决定它会更多idiot-proof) - 我在任何地方都使用整数形式。看不到在 db 中添加额外 col 的意义...
  • 如果您真的不需要用户编辑Klass,那么您不需要单独保存它们。尝试将您的方法更改为self.start= start_hour.to_i * 60 + start_mins.to_i
  • 请注意,通过使用回调,如果在没有start_hourstart_mins 属性的情况下加载并重新验证记录,您将收到错误消息。我会改为self.start = start_hour.to_i * 60 + start_mins.to_i if start_hour &amp;&amp; start_mins
猜你喜欢
  • 1970-01-01
  • 2011-03-14
  • 2018-06-23
  • 2012-02-27
  • 1970-01-01
  • 1970-01-01
  • 2020-06-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多