首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Rails集合仅选择保存部分属性

Rails集合仅选择保存部分属性
EN

Stack Overflow用户
提问于 2016-02-19 14:40:25
回答 2查看 68关注 0票数 2

我正在尝试理解如何做一件简单的事情--从collection_select中保存id和文本。我刚刚开始使用RoR,所以我还没有很好地掌握所有的东西。我的经验主要是Java外加一些Perl,所以我可能没有选择正确的方法。

我有一个缺陷,它有一个DefectRootCause。还有另一个实体,DefaultRootCauses,我可以从中选择与缺陷相关联的DefectRootCause.root_cause。我正在尝试用它的DefectRootCause来保存这个缺陷。DefectRootCause应该将root_cause字段作为文本,即从DefaultRootCause中选择的值。问题是我只能为DefectRootCause保存一个root_cause或default_root_cause_id。此外,DefectRootCause.root_cause从DefaultRootCause而不是文本中获取id。

请告诉我,如果我试图让所有事情都“神奇地”发生,或者我是否应该在控制器中对数据进行一些处理,请让我知道这是正确的。代码见下文。

我有模型:

代码语言:javascript
复制
class Defect < ActiveRecord::Base

  has_one :defect_root_cause, :dependent => :destroy
  has_many :default_root_cause, :through => :defect_root_cause

end

class DefectRootCause < ActiveRecord::Base
  belongs_to :defect
  belongs_to :default_root_cause

end

class DefaultRootCause < ActiveRecord::Base

  has_many :defect_root_causes
  has_many :defects, :through => :defect_root_causes
end

控制器(我想我只需要修改其中的一个):

代码语言:javascript
复制
  # POST /defects
  # POST /defects.json
  def create
    #I am doing this because the attributes are not named :defect_root_cause_attribues, I don't know yet why
    @defect = Defect.new(defect_params.except(:defect_root_cause))
    @defect.defect_root_cause = DefectRootCause.new(defect_params[:defect_root_cause])
    respond_to do |format|
      if @defect.save
        format.html { redirect_to @defect, notice: 'Defect was successfully created.' }
        format.json { render :show, status: :created, location: @defect }
      else
        format.html { render :new }
        format.json { render json: @defect.errors, status: :unprocessable_entity }
      end
    end
end
  # PATCH/PUT /defects/1
  # PATCH/PUT /defects/1.json
  def update
        respond_to do |format|
        #I am doing this because the attributes are not named :defect_root_cause_attribues, I don't know yet why
      if @defect.update(defect_params.except(:defect_root_cause)) && @defect.defect_root_cause.update(defect_params[:defect_root_cause])
        format.html { redirect_to @defect, notice: 'Defect was successfully updated.' }
        format.json { render :show, status: :ok, location: @defect }
      else
        format.html { render :edit }
        format.json { render json: @defect.errors, status: :unprocessable_entity }
      end
  end
end

# Never trust parameters from the scary internet, only allow the white list through.
    def defect_params
        #I am doing this because the attributes are not named :defect_root_cause_attribues, I don't know yet why
      params.require(:defect).permit(:details, defect_root_cause: [:id, :details, :root_cause, :default_root_cause_id])
    end

现在视图:

代码语言:javascript
复制
<%= form_for @defect do |f| %>
  <% if @defect.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@defect.errors.count, "error") %> prohibited this defect from being saved:</h2>

      <ul>
      <% @defect.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :details %><br>
    <%= f.text_field :details %>
    <%= f.fields_for @defect.defect_root_cause do |drc| %>
    <%= drc.label :root_cause%>
    <%= drc.collection_select(:default_root_cause_id, DefaultRootCause.all, :id, :root_cause, :prompt => true) %>

    <%= drc.label :details%>
    <%= drc.text_field :details %>
  <% end %>
  </div>
      <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

在routes.rb中,我只有以下内容:

代码语言:javascript
复制
  resources :default_root_causes
  resources :defects
  resources :defect_root_causes

  # You can have the root of your site routed with "root"
  root 'defects#index'

最后,我的问题(root_cause为空):

代码语言:javascript
复制
irb(main):006:0> DefectRootCause.find(10)
  DefectRootCause Load (0.3ms)  SELECT  `defect_root_causes`.* FROM `defect_root_causes` WHERE `defect_root_causes`.`id` = 10 LIMIT 1
=> #<DefectRootCause id: 10, details: "sadsad", defect_id: 9, default_root_cause_id: 2, created_at: "2016-02-19 05:52:06", updated_at: "2016-02-19 05:52:06", root_cause: nil>

如果我将选择更改为:

代码语言:javascript
复制
<%= drc.collection_select(:root_cause, DefaultRootCause.all, :id, :root_cause, :prompt => true) %>

我得到如下信息(root_cause被保存,但它是一个数字,而不是文本-在本例中,我想要以下文本:"second root cause",加上default_root_cause_id为空):

代码语言:javascript
复制
irb(main):005:0> DefectRootCause.find(9)
  DefectRootCause Load (0.3ms)  SELECT  `defect_root_causes`.* FROM `defect_root_causes` WHERE `defect_root_causes`.`id` = 9 LIMIT 1
=> #<DefectRootCause id: 9, details: "das", defect_id: 8, default_root_cause_id: nil, created_at: "2016-02-19 05:42:36", updated_at: "2016-02-19 05:42:36", root_cause: "2">

编辑:

现在,我将我所做的将所有信息保存在我需要的地方。我现在将其作为答案发布,因为我仍然不知道这是不是正确的方法。所以,如果你知道应该以不同的方式来做,请让我知道。我特别关注如何从视图中发送所有信息。我看到视图“知道”所选DefaultRootCause的id和文本,但我没有在发送的params中同时获得这两个内容。

那么,现在是代码。

查看:

代码语言:javascript
复制
<%= drc.select :default_root_cause_id, DefaultRootCause.all.collect{|r| [r.root_cause, r.id]}, :prompt => true %>

defects_controller.rb
def create
@defect = Defect.new(defect_params.except(:defect_root_cause))
@defect.defect_root_cause = DefectRootCause.create(defect_params[:defect_root_cause].merge(:root_cause => DefaultRootCause.find(defect_params[:defect_root_cause][:default_root_cause_id]).root_cause))
respond_to do |format|........
def update
respond_to do |format|
  if @defect.update(defect_params.except(:defect_root_cause)) && @defect.defect_root_cause.update(defect_params[:defect_root_cause].merge(:root_cause => DefaultRootCause.find(defect_params[:defect_root_cause][:default_root_cause_id])))

有了这些,我得到了以下参数和以下插入:

代码语言:javascript
复制
 Parameters: {"utf8"=>"✓", "authenticity_token"=>"jGUQIxeXWZwg5lqsPFrE4vO9z4ioRnAN/Z1/K9scQiIeQ0MTHBTvZoDcwHKtGvrgrG53y4yr7tX4wnCShoZ/oA==", "defect"=>{"details"=>"a", "defect_root_cause"=>{"default_root_cause_id"=>"2", "details"=>"a"}}, "commit"=>"Create Defect"}
  DefaultRootCause Load (0.1ms)  SELECT  `default_root_causes`.* FROM `default_root_causes` WHERE `default_root_causes`.`id` = 2 LIMIT 1
  CACHE (0.0ms)  SELECT  `default_root_causes`.* FROM `default_root_causes` WHERE `default_root_causes`.`id` = 2 LIMIT 1  [["id", "2"]]
  CACHE (0.0ms)  SELECT  `default_root_causes`.* FROM `default_root_causes` WHERE `default_root_causes`.`id` = 2 LIMIT 1  [["id", "2"]]
   (0.1ms)  BEGIN
   SQL (0.2ms)  INSERT INTO `defect_root_causes` (`details`, `default_root_cause_id`, **`root_cause`**, `created_at`, `updated_at`) VALUES ('a', 2, **'second root cause'**, '2016-02-23 07:10:59', '2016-02-23 07:10:59')

现在,请让我知道这是不是“正确”的方法。

谢谢你,维克多

EN

回答 2

Stack Overflow用户

发布于 2016-02-19 15:00:03

您正在尝试通过父级更新关联的属性,这意味着您需要使用accepts_nested_attributes_for。将此方法添加到Defect模型中,如下所示:

类缺陷< ActiveRecord::Base

has_one :defect_root_cause,:dependent => :destroy has_many :default_root_cause,:through => :defect_root_cause

accepts_nested_attributes_for :defect_root_cause结束

完成此操作后,转到defects_controller.rb并将#defect_params方法更新为:

params.require(:defect).permit(:details, defect_root_cause_attributes: [:id, :details, :root_cause, :default_root_cause_id])

票数 0
EN

Stack Overflow用户

发布于 2016-02-19 15:03:46

您可以使用以下代码:

代码语言:javascript
复制
<%=f.select :default_root_cause_id,  DefaultRootCause.all.collect{|r| [r.route_cause,"#{r.route_cause} - #{r.id}"]} %>
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35498874

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档