繁体   English   中英

Rails 5嵌套属性未保存find_or_initialize_by方法

[英]Rails 5 Nested Attributes not saving find_or_initialize_by method

我确定RoR中有新功能,并且使用Rails 5.0.6(Ruby 2.3.4p301)。 以下是我过去数小时无法解决的问题,

我有两个表-位置(属性-地址)和评论(属性-标题,持续时间,肯定,否定,location_id)。 location.rb是父模型,reviews.rb是子模型。

问题: locations_controller.rb应该检查数据库中是否已经存在location.address。 如果是,则评论将保存在相同的location_id下。 如果不存在location.address,则将创建一个新位置和评论。 这就是为什么我使用find_or_initialize_by方法。

问题是-评论正在访问数据库,但是所有属性的值为nil。 (当我从locations_controller.rb中删除第10行和第11行时,它工作正常,只是在数据库中找不到现有的location.address。问题是,由于第10行和第11行,审阅哈希没有通过,只是创建一个以'nil'为值的记录。)

app / models / location.rb

class Location < ApplicationRecord
  has_many :reviews, inverse_of: :location
  accepts_nested_attributes_for :reviews
end

app / models / review.rb

class Review < ApplicationRecord
  belongs_to :location, optional: true
end

app / controllers / locations_controller.rb

01 class LocationsController < ApplicationController
02  
03  def new
04    @location = Location.new
05    @location.reviews.build
06  end
07  
08  def create
09    @location = Location.new(location_params)
10    @location = Location.find_or_initialize_by(address: location_params[:address])
11    @location.reviews.build
12    
13    if @location.save
14      flash[:notice] = "Location has been successfully saved"
15      redirect_to location_path(@location)
16    else
17      render 'new'
18    end
19  end
20  
21  def show
22    @location = Location.find(params[:id])
23  end
24
25  private
26  def location_params
27    params.require(:location).permit(:address, reviews_attributes: [:location_id, :id, :title, :duration, :positive, :negative])
28  end
29  
30 end

app / views / locations / new.html.erb

<h1>Create a house review</h1>

<%= simple_form_for @location do |f| %>
  <%= f.input :address, label: 'Enter Address', input_html: { id: 'autocomplete', size: 100 }, placeholder: 'E.g. 1 Collins Street, Melbourne, VIC 3000' %>

    <%= f.simple_fields_for :reviews do |e| %>
      <%= e.input :title %>
      <%= e.input :duration %>
      <%= e.input :positive %>
      <%= e.input :negative %>
    <% end %>

  <%= f.button :submit %>
<% end %>

app / views / locations / show.html.erb

<h1>Showing selected location</h1>
<p>
  Location: <%= @location.address %>
</p>
<h2>Reviews (<%= @location.reviews.count %>)</h2>
<% if @location.reviews.present? %>
  <% @location.reviews.each do |review| %>
    <ul>
      <h3><%= review.title %></h3>
      <li>Duration: <%= review.duration %></li>
      <li>Positive: <%= review.positive %></li>
      <li>Negative: <%= review.negative %></li>
    </ul>
  <% end %>
<% else %>
There are no reviews for this location.
<% end %>

您可以使用create!更改新内容,以下是说明:

new会创建一个对象,但rails仍然不是用于记录的init和id,同时创建! 将创建一个对象,并且rails会将init值放入记录中。 如果您建立“子”记录(如评论),则带有位置的初始ID,它将获得location_id值

def create
  @location = Location.create!(location_params)
  @location.reviews.build
  # your other code
end

编辑2,我检查了find_or_initialize_by将被弃用 ,我认为您需要更改逻辑,这里有一些想法

def create
  @location = Location.find_by_address(location_params[:address])
  if @location.nil?
    # if nil then it's meaning @location was not found in db
    # then you create it with initial id
    @location = Location.create!(location_params)
    # @location will get address from params automatically
  end
  @location.reviews.build
end

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM