как заставить вложенные формы работать с мастером в рельсах? - PullRequest
0 голосов
/ 10 марта 2019

У меня есть мастер, который позволяет пользователям выбирать сумму ставки (на этапе show), а затем я хочу, чтобы они указали адрес (на этапе confirmation). Я не хочу, чтобы в базе данных ничего не сохранялось до тех пор, пока не были добавлены информация о транзакциях и адресах, поэтому имеет смысл поместить эту функцию в мастер. Это сложнее, чем я думал, потому что я не уверен, как получить мастера, которого я собрал, из других источников, чтобы принять вложенные атрибуты для другой модели. Если вы посмотрите на приведенный ниже код мастера, то увидите, что я предпринял некоторую попытку (которая привела к некоторой ошибке uninitialized constant Transaction::Address), я просто ... не получаю то, что хочу , Мне не нужны точные решения, но я был бы очень признателен за любые указатели.

Мои ассоциации моделей выглядят так:

class User < ApplicationRecord
 has_many :addresses
 has_many :items
 has_many :transactions
end

class Item < ApplicationRecord
 belongs_to :user
 belongs_to :address, foreign_key: :address_id
 has_many :transactions
 accepts_nested_attributes_for :address
end

class Transaction < ApplicationRecord
 belongs_to :user
 belongs_to :item
 belongs_to :address
 accepts_nested_attributes_for :address
end

class Address < ActiveRecord::Base
 belongs_to :user, foreign_key: :user_id
 has_many :items
 has_many :transactions
end

Волшебник, которым я пользуюсь, выглядит следующим образом:

module Wizard
 module Transaction
  STEPS = %w(show confirmation).freeze

  class Base
   include ActiveModel::Model
   attr_accessor :transaction
   #do i need an attr_accessor :address?
   delegate *::Transaction.attribute_names.map { |attr| [attr, "#{attr}="] }.flatten, to: :transaction
  # delegate *::Address.attribute_names.map { |attr| [attr, "#{attr}="] }.flatten, to: :address
  #address is a child of transaction, and i need to collect its attributes in the final step. do i set that up here, or in the final step?

   def initialize(transaction_attributes)
    @transaction = ::Transaction.new(transaction_attributes)
    # @address = ::Address.new(address_attributes)
   end
  end

  class Show < Base
   validates :sender_id, :recipient_id, :item_id, :sender_agreement, presence: true
   validates :amount, presence: true, numericality: { greater_than: 0 }
  end

  class Confirmation < Show

  end
 end
end

Мой контроллер выглядит так:

class TransactionWizardsController < ApplicationController
 include TransactionWizard
 def confirm
  current_step = params[:current_step]
  @item = Item.friendly.find(params[:item_id])
  @transaction_wizard = wizard_transaction_for_step(current_step)
  @transaction_wizard.transaction.attributes = address_params
  session[:transaction_attributes] = @transaction_wizard.transaction.attributes

  if @transaction_wizard.valid?
   next_step = wizard_transaction_next_step(current_step)
   create and return unless next_step

   redirect_to action: next_step
  else
   redirect_to action: current_step
  end
 end

 def address_params
  params.require(:transaction_wizard).permit(addresses: [:name, :street, :street_2, :state, :zip_code])
 end
end

Мои маршруты выглядят так:

resources :items, path: 'art' do
 resource :transaction_wizard, only: [:new, :create], path: "bid" do
  get :confirmation
  post :add_to
  post :confirm
 end
end

И форма в моем confirmation виде выглядит так:

<%= form_for @transaction_wizard, as: :transaction_wizard, url: confirm_item_transaction_wizard_path(@item) do |f| %>
  <%= f.fields_for @address do |address| %>
   <%= address.label "Full name" %>
   <%= address.text_field :name, placeholder: "Your full name", autofocus: true %>
   <%= address.label "Street address" %>
   <%= address.text_field :street, placeholder: "Your street address" %>

   <%= address.label "Apt" %>
   <%= address.text_field :street_2, placeholder: "Your apt or suite number" %>

   <%= address.label "State" %>
   <%= address.select :state, options_for_select(states_list), {prompt: 'State'}, class: 'ui selection dropdown' %>

   <%= address.label "Zip code" %>
   <%= address.text_field :zip_code, placeholder: "Your zip code" %>

  <% end %>
  <%= hidden_field_tag :current_step, 'confirmation' %>
  <%= f.submit "Complete offer" %>
<% end %>
...