2016-10-12 3 views
1

Я просмотрел различные ответы на подобные вопросы и не совсем разобрал их. A wine модель определена с has_one :register, :dependent => :destroy и правильно или неправильно я добавил accepts_nested_attributes_for :register. A register определяется с помощью belongs_to :wine.Рельсы, заполнив базу данных ассоциированными моделями на одной форме

Код в wines_controller.rb для create является:

def new 
    @wine = Wine.new 
    @register = Register.new 

def create 
    @wine = Wine.new(wine_params) 
    @register = @wine.registers.build(register_params) 
    respond_to do |format| 
    if @wine.save 
    #success 
    else 
     format.json { render json: @wine.errors, status: :unprocessable_entity } 
     format.json { render json: @register.errors, status: :unprocessable_entity } 
    end 
    end 
end 

Моя форма для создания new wine имеет следующий код:

<%= simple_form_for @wine do |f| %> 
# various working elements 
<div class="field"> 
    <% f.fields_for :register do |r| %> 
    <%= r.label :short_name %> 
    <%= r.text_field :short_name %> 
    <%= r.label :barcode %> 
    <%= r.text_field :barcode %> 
    <% end %> 
</div> 

Когда эта форма называется вверх никакие поля не создаются из f.fields_for но этот блок выполняется, потому что я могу добавить в него тестовые кнопки, чтобы доказать, что к нему обращаются.

Если я пытаюсь создать вино, я получаю следующее сообщение об ошибке:

undefined method `registers' for #<Wine:0x007f1204375330> Did you mean? register register= register_id 

Я считаю, что использование .build есть для обеспечения целостности данных: Я не хочу, чтобы создать wine, который не имеет a соответствует register. Я пробовал думать об этом вложенных атрибутах, но многие считают, что это плохой план. Этот текущий подход кажется правильным, но, по-моему, мне не хватает понимания синтаксиса.

На более позднем этапе необходимо будет установить другие модели, связанные с register, которые не будут связаны с винами. Я рассматривал аналогичный подход, но я рад, что мне сказали переосмыслить!

ответ

2

Если я вас правильно понял у вас есть 2 проблемы:

Во-первых полей для регистра не отображаются - это отчасти потому, что @ wine.register равна нулю.

Вы должны изменить свое новое действие на:

def new 
    @wine = Wine.new 
    @wine.register = Register.new 

Кроме того, потому что вы используете simple_form_for вам нужно будет использовать simple_fields_for вместо fields_for

Вашего второго вопроса, который приводит в исключении говорит все ... вы пытаетесь получить доступ к @ wine.registers, а не @ wine.register

Изменение вашего метода создания на:

@register = @wine.register.build(register_params) 

Это исправит эту проблему ... однако ... все, что вам действительно нужно сделать, это построить объект @wine из ваших параметров - ваши параметры должны быть настроены для разрешения правильных вложенных атрибутов - если он установлен правильно, объект регистров будет также создан при построении объекта @wine.

Ваша модель уже настроена на accept_nested_attributes и, следовательно, также будет проверять и сохранять объект register при вызове @ wine.save - не нужно явно сохранять объект register.

Вы должны иметь что-то вроде:

def wine_params 
    params.require(:wine).permit(
      :attribute1, :attribute2, 
      register_attributes: [:id, :short_name, :barcode]) 
end 
+0

ОК, спасибо за вход. Первая корректировка, которую вы предлагаете, порождает 'ActiveModel :: MissingAttributeError в WinesController # new' и' не может записать неизвестный атрибут 'wine_id'' – fatherdamo

+0

Эта ошибка возникает, если я пытаюсь создать новую запись вина – fatherdamo

+0

, вы могли бы прояснить ... мы говорим о '@wine.register = Register.new' строке? Если это так, проверьте свою регистрационную таблицу ... у нее должна быть ссылка wine_id – David

0

Попробуйте

Вино и Регистрация моделям

class Wine < ApplicationRecord 
    has_one :register, inverse_of: :wine, :dependent => :destroy 
    accepts_nested_attributes_for :register 
end 

class Register < ApplicationRecord 
    belongs_to :wine, inverse_of: :register 
    validates_presence_of :wine 
end 

Wines контроллер

class WinesController < ApplicationController 
    def new 
    @wine = Wine.new 
    @wine.build_register 
    end 


    def create 
    @wine = Wine.new(wine_params) 

    if @wine.save 
     redirect_to @wine 
    else 
     render :new 
    end 
    end 

    private 
    def wine_params 
     params.require(:wine).permit(:name, register_attributes: [:simple_name]) 
    end 
end 

Мои wine_params специфичны для

rails g model wine name:string 
rails g model register name:string wine_id:integer 

Наконец форма вино должно выглядеть следующим образом

<%= form_for @wine do |f|%> 
    <p> 
     <%= f.label :name%> 
     <%= f.text_field :name%> 
    </p> 

    <%= f.fields_for :register do |r|%> 
    <p> 
     <%= r.label :simple_name%> 
     <%= r.text_field :simple_name%> 
    </p>  
    <% end %> 

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

Таким образом, вы можете изменить wine_params и формы частичной для специфических приложений

+0

регистр будет сохранен автоматически при создании вина –

+0

Также вы можете использовать simple_form_for и simple_fields_for вместо form_for и fields_for –