Ruby on Rails:通过表单将值插入到db中的数组字段中

时间:2014-06-18 13:00:58

标签: ruby-on-rails ruby arrays postgresql

如何将表单中的值插入数据库中的数组?我使用简单的形式,rails 4.1,postgresql db。

这是我的表单,除了影响和可能性字段(两个数组)之外,所有字段都正确更新。他们是这个问题的焦点:

<%= simple_form_for(@risk) do |f| %>
  <%= render 'shared/error_messages', object: f.object %>
  <div class="form-group">
    <%= f.input :title, required: false, :error => false, input_html: { class: 'form-control' } %>
  </div>

  <div class="form-group">
    <%= f.input :description, required: false, :error => false,  as: :text, input_html: { class: 'form-control description' } %>
  </div>

  <div class="form-group">
    <%= f.input :area, :collection => ['Operations', 'IT', 'Finance'], required: false, :error => false, input_html: { class: 'form-control' } %>
  </div>

  <div class="form-group">
    <%= f.input :owner, :collection => User.all, required: false, :error => false, input_html: { class: 'form-control' } %>
  </div>

  <div class="form-group">
    <%= f.input :action, required: false, :error => false, input_html: { class: 'form-control' } %>
  </div>

  <div class="form-inline">
    <span class="date-of-action-input">
    <%= f.input :date_of_action, :as => :date, :start_year => Date.today.year - 10, :end_year => 2030,
        :order => [ :day, :month, :year], :required => false, :error => false, input_html: { class: 'form-control' } %>
    </span>
    <span class="action-completed-input">
    <%= f.input :action_completed, as: :boolean, required: false, :error => false, input_html: { class: 'form-control' } %>
    </span>

    <span class="impact-input">
    <%= f.input :impact, required: false, :error => false, input_html: { class: 'form-control' } %>
    </span>
    <span class="likelihood-input">
    <%= f.input :likelihood, required: false, :error => false, input_html: { class: 'form-control' } %>
    </span>
    <span class="submit-risk">
    <%= f.button :submit, :error => false, :error => false, input_html: { class: 'form-control' } %>
    </span>
  </div>
<% end %>

这里是关联的控制器(risks_controller.rb):

class RisksController < ApplicationController
before_action :signed_in_user
before_action :correct_user, only: [:destroy, :update]


def create
    @risk = current_user.risks.build(risk_params)
    if @risk.save
      flash[:success] = "Risk created!"
      redirect_to root_url
    else
      render 'new'
    end
end

def new
  @risk = Risk.new
end

def destroy
  @risk.destroy
  redirect_to root_url
end

def edit
  @risk = Risk.find(params[:id])
end

def update
  @risk = Risk.find(params[:id])
    @risk.assign_attributes(risk_params)
    if @risk.changed? == false
      flash[:info] = "No changes were made"
      redirect_to root_url
    elsif @risk.update_attributes(risk_params)
      flash[:success] = "The risk has been updated."
      redirect_to root_url
    else
        render 'new'
    end
end

private

    def risk_params
        params.require(:risk).permit(:description, :title, :area, :owner, :action, :date_of_action, :action_completed, :impact, :likelihood)
    end

  def correct_user
    if current_user.admin?
      @risk = Risk.find_by(id: params[:id])
      redirect_to root_url if @risk.nil?
    else
      @risk = current_user.risks.find_by(id: params[:id])
      redirect_to root_url if @risk.nil?
    end
  end

end

我的数据库模式文件:

ActiveRecord::Schema.define(version: 20140617165640) do

  create_table "risks", force: true do |t|
    t.integer  "user_id"
    t.string   "description"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.string   "title"
    t.string   "area"
    t.string   "owner"
    t.string   "action"
    t.date     "date_of_action"
    t.boolean  "action_completed", default: false
    t.integer  "impact",           default: [],    array: true
    t.integer  "likelihood",       default: [],    array: true
  end

  add_index "risks", ["user_id", "created_at"], name: "index_risks_on_user_id_and_created_at", using: :btree

  create_table "users", force: true do |t|
    t.string   "name"
    t.string   "email"
    t.boolean  "admin",           default: false
    t.datetime "created_at"
    t.datetime "updated_at"
    t.string   "password_digest"
    t.string   "remember_token"
  end

  add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
  add_index "users", ["remember_token"], name: "index_users_on_remember_token", using: :btree

end

我想象代码看起来像这样,但唉,我的第一个rails项目,我需要一些指导。在risk_controller.rb中:

def create
  @risk = current_user.risks.build(risk_params)
  @impact = risk_params[:impact]
  @userid = current_user.id
  @impacttoupdate = Risk.select(:impact).where(id: risk_params[:id])
  @impacttoupdate.insert(@userid, @impact)
    if @risk.save
      flash[:success] = "Risk created!"
      redirect_to root_url
    else
      render 'new'
    end
end

我想根据用户ID插入值。因此,如果用户标识为3,则他们提交的表单中的值应该进入数组中的第3个插槽。

2 个答案:

答案 0 :(得分:0)

你必须在强参数中定义post值是数组。

def risk_params
    params.require(:risk).permit(:description, :title, :area, :owner, :action, :date_of_action, :action_completed, {:impact => []}, {:likelihood=>[]})
end

答案 1 :(得分:0)

对于Seong和其他任何人 - 这里有一些关于我如何使用它的基本代码。它不是很优雅,那时我对Rails很新。

def update
@risk = Risk.find(params[:id])
#1. capture the existing arrays from the db before anything 
#has happened to them
@impactarray = @risk.impact
@likelihoodarray = @risk.likelihood
#2. update ALL attributes, including impact and likelihood fields incorrectly
@risk.assign_attributes(risk_params)
if @risk.changed? == false
  flash[:info] = "No changes were made"
  redirect_to root_url
elsif @risk.update_attributes(risk_params)
  #3. delete the existing value in the array, even if it is nil
  @impactarray.delete_at(current_user.id)
  #4. repeat this for the likelihood field
  @likelihoodarray.delete_at(current_user.id)
  #5. capture the value that was entered, it would be the first 
  #and only value in the incorrectly formed array
  @impactscore = @risk.impact[0]
  #6. insert the new value correctly according to user id by inserting it 
  #back into the original arrays we captured at the start of the method
  @impactarray.insert(current_user.id, @impactscore)
  #7. do the same for the likelihood column
  @likelihoodscore = @risk.likelihood[0]
  @likelihoodarray.insert(current_user.id, @likelihoodscore)
  #8. officially make these changes on the @risk object and save them
  @risk.update_column("impact", @impactarray)
  @risk.update_column("likelihood", @likelihoodarray)
  #9. update the score columns to save computation on the risk matrix
  averageimpactscore = @impactarray.compact.inject(0) {|sum,x| sum += x.to_i } / @impactarray.compact.length
  averagelikelihoodscore = @likelihoodarray.compact.inject(0) {|sum,x| sum += x.to_i } / @likelihoodarray.compact.length
  overallscore = (averageimpactscore + averagelikelihoodscore) / 2
  @risk.update_column("average_impact", averageimpactscore)
  @risk.update_column("average_likelihood", averagelikelihoodscore)
  @risk.update_column("overall_score", overallscore)
  @risk.save!
  #N.B. remember we got simple form to recall the user's values so they 
  #do not get put back to 0 when other fields are edited (see the risk form view)
  flash[:success] = "Risk #{@risk.id} has been updated."
  redirect_to root_url
else
    render 'new'
end
end