【问题标题】:Rails 5 Nested Attributes not saving find_or_initialize_by methodRails 5嵌套属性不保存find_or_initialize_by方法
【发布时间】:2017-11-18 14:27:25
【问题描述】:

我确信 RoR 中的新手并使用 Rails 5.0.6 (Ruby 2.3.4p301)。以下是我在过去数小时内遇到的问题-

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

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

问题是 - 审查正在访问数据库,但所有属性的值都为零。 (当我从 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 %>

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-4 ruby-on-rails-5


    【解决方案1】:

    你可以用 create! 改变 new,下面是解释:

    new 将创建一个对象,但 rails 仍然没有记录的 init 和 id,同时创建!将创建一个对象,rails 将初始化一个 id 值到记录中。如果您构建像评论这样的“子”记录,则具有位置的初始 ID,它将获得 location_id 值

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

    编辑2,我检查了find_or_initialize_by will be deprecated,我认为你需要改变逻辑,这里有一些想法

    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
    

    【讨论】:

    • 我刚刚尝试创建!而不是新的,仍然得到相同的结果对不起。还有其他建议吗?
    • 我刚刚删除了第 10 行,参见上面的示例,我认为它是 nil,因为第 10 行
    • 嗨 @widjajayd,如果我们删除第 10 行 find_or_initialize_by 方法,我们如何查看参数是否与 location.address 匹配?
    • 感谢#edit 2。我最终使用了 .nil?方法并改变了我的逻辑。它现在正在工作:)
    • 如果您尝试为current_user.create_profile(profile_params) 创建呢?我会去谁做create 方法?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多