Ruby on rails 多态关联事务在Rails 5中失败

Ruby on rails 多态关联事务在Rails 5中失败,ruby-on-rails,ruby-on-rails-5,polymorphic-associations,Ruby On Rails,Ruby On Rails 5,Polymorphic Associations,我无法将我的关联保存在localhost:3000/controller\u name/new中。我相信这是因为它属于,但我不知道如何修复它,除了仅仅通过丢弃关联外,我不确定其后果。我根据这一点创建了我的关联,但它是针对rails的早期版本的 我有一个多态地址表,可以属于事件、企业、用户等。我正在尝试将其添加到事件中 地址迁移-您可以看到它引用了可寻址的: 事件形式使用简单的gem形式: <%= simple_form_for @event do |f| %> <%= f.

我无法将我的关联保存在localhost:3000/controller\u name/new中。我相信这是因为它属于,但我不知道如何修复它,除了仅仅通过丢弃关联外,我不确定其后果。我根据这一点创建了我的关联,但它是针对rails的早期版本的

我有一个多态地址表,可以属于事件、企业、用户等。我正在尝试将其添加到事件中

地址迁移-您可以看到它引用了可寻址的:

事件形式使用简单的gem形式:

<%= simple_form_for @event do |f| %>
  <%= f.input :name %>
  <%= f.input :description %>

  <%= f.simple_fields_for :address do |address| %>
    <%= render :partial => 'shared/address/form', :locals => {:f => address} %>
  <% end %>

  <%= f.button :submit %>
<% end %>
我一直在新的一页上。如果我在create和print out@event.errors中插入byebug,它会显示:

#<ActiveModel::Errors:0x007fb29c34a9a8 @base=#<Event id: nil, name: "asd", description: "asd", min_users: nil, max_users: nil, start_time: nil, recurring: nil, created_at: nil, upd
ated_at: nil>, @messages={:"address.addressable"=>["must exist"]}, @details={:"address.addressable"=>[{:error=>:blank}]}>

如何创建address.addressable?如一些SO答案所示,关闭requires验证会产生什么后果?

运行rake db:schema:dump,然后检查db/schema.rb中的文件,确保有如下两个字段 *t.integer:可寻址的\u id, *字符串:可寻址的\u类型 有关更多详细信息,请参阅下面的链接,如果您的模式有问题,则可以按如下方式运行迁移

t.references :addressable, polymorphic: true, index: true
由于事件通过多态关联具有多个地址,因此可以使用创建地址 下面是示例代码

@address = @event.addresses.build(attributes = {}, ...)

您可以使用@address而不是@event.address发现了这些问题,并写了一篇文章对此进行了深入讨论。基本上,我遇到了两个不同的问题

1.我收到的错误-address.addressable=>[必须存在]。address.addressable是“parent”表的元组ID。在我的例子中,它是事件ID。当我们试图将新地址中的外键保存到控制器的create函数中时,此错误试图告诉我该外键丢失。正如我在问题中所说,您可以将optional:true设置为忽略此问题,并且它在保存事件后以某种方式神奇地被填充。也可以在保存之前在“创建”功能中手动分配

def create
  @event = Event.new(event_params)
  @event.address.addressable = @event #<<<<<<<<<<< manually assign address.addressable
  respond_to do |format|
    if @event.save #Saves the event. Addressable has something to reference now, but validation does not know this in time
      format.html { redirect_to @event, notice: 'Event was successfully created.' }
      format.json { render :show, status: :created, location: @event }
    else
      #dont forget to remove the 'byebug' that was here
      format.html { render :new }
      format.json { render json: @event.errors, status: :unprocessable_entity }
    end
  end
end

这在博客文章中有更详细的介绍。

我还没能测试出来,但我知道地址确实有可寻址类型,而且我在其中。我在原始文本中包含了使用@event.build_address的输出。我认为问题在于这会使Id为空?如果您已经设置了连接,例如,当您使用@event.addresses.build rails提供的方法时,它会自动处理Id,您不必手动插入/键入它。当我在事件控制器的新函数中尝试`@address=@event.address.build`时,我得到了nil:NilClass的未定义方法'build'。还有未定义的方法“地址”是什么意思?地址=for@event.address.build@event.build_address可以工作,但在传递到我的表单{id=>nil,address=>nil,latitude=>nil,longitude=>nil,addressable_type=>event,addressable_id=>nil}时具有这些属性。IDK为什么id不在那里。您必须使用create创建@event!不是新的,所以之前的命令@event=event.create!事件参数。。。。通过这种方式,你的@event将首先被创建,并且有一个id。在这之前,你看到它发生在我身上,然后你必须找出导致验证失败的原因,我相信你在事件模型中有一些验证规则,然后你应该跟踪逻辑,使create不失败,这就是我所做的
<%= simple_form_for @event do |f| %>
  <%= f.input :name %>
  <%= f.input :description %>

  <%= f.simple_fields_for :address do |address| %>
    <%= render :partial => 'shared/address/form', :locals => {:f => address} %>
  <% end %>

  <%= f.button :submit %>
<% end %>
<!-- Google Maps Must be loaded -->
<% content_for :head do %>
    <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCMh8-5D3mJSXspmJrhSTtt0ToGiA-JLBc&libraries=places"></script>
<% end %>

<div id="map"></div>

<%= f.input :address %>
<%= f.input :latitude %>
<%= f.input :longitude %>
Started POST "/events" for 127.0.0.1 at 2017-07-01 16:06:23 -0400
Processing by EventsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"R0zlSs3UUNV3x8sQn5ocmE4jP12uOsFza7FezBAuhP4sw2MhF1OhixF8sAfDsLpfMEX7x5rhJ9HZfbKna8ncEA==", "event"=>{"name"=>"asd", "description"
=>"asd", "address_attributes"=>{"address"=>"asd", "latitude"=>"1", "longitude"=>"1"}}, "commit"=>"Create Event"}
   (0.1ms)  begin transaction
   (0.1ms)  rollback transaction
#<ActiveModel::Errors:0x007fb29c34a9a8 @base=#<Event id: nil, name: "asd", description: "asd", min_users: nil, max_users: nil, start_time: nil, recurring: nil, created_at: nil, upd
ated_at: nil>, @messages={:"address.addressable"=>["must exist"]}, @details={:"address.addressable"=>[{:error=>:blank}]}>
t.references :addressable, polymorphic: true, index: true
@address = @event.addresses.build(attributes = {}, ...)
def create
  @event = Event.new(event_params)
  @event.address.addressable = @event #<<<<<<<<<<< manually assign address.addressable
  respond_to do |format|
    if @event.save #Saves the event. Addressable has something to reference now, but validation does not know this in time
      format.html { redirect_to @event, notice: 'Event was successfully created.' }
      format.json { render :show, status: :created, location: @event }
    else
      #dont forget to remove the 'byebug' that was here
      format.html { render :new }
      format.json { render json: @event.errors, status: :unprocessable_entity }
    end
  end
end
t.string :addressable_id, index: true
t.string :addressable_type, index: true