1

Я нуждается в функциональности практически идентичны этим:Rails 4 с simple_form_for, has_many через и вложенных атрибутов

https://robots.thoughtbot.com/accepts-nested-attributes-for-with-has-many-through

и я шел вокруг и вокруг (и вокруг), пытаясь получить он функционирует должным образом, но продолжает сталкиваться с препятствиями. Я все еще немного новичок в Ruby и Rails, и мне нужна помощь в продвижении вперед. Вот моя реализация, как она существует в настоящее время:

/models/transfer.rb 

class Transfer < ActiveRecord::Base 

    validates :name, presence: true, 
        uniqueness: { case_sensitive: false } 

    has_many :transfer_accounts, inverse_of: :transfer 
    has_many :accounts,   through: :transfer_accounts 

    accepts_nested_attributes_for :transfer_accounts 

end 


/models/transfer_account.rb 

class TransferAccount < ActiveRecord::Base 

    validates :account_transfer_role, presence: true 

    belongs_to :account, inverse_of: :transfer_accounts 
    belongs_to :transfer, inverse_of: :transfer_accounts 

    validates :account, presence: true 
    validates :transfer, presence: true 

    accepts_nested_attributes_for :account 

end 


/models/account.rb 

class Account < ActiveRecord::Base 

    validates :name,   presence: true, 
          uniqueness: { case_sensitive: false } 
    validates :user_name,  presence: true 
    validates :password,  presence: true 
    validates :account_number, presence: true, 
          uniqueness: { case_sensitive: false } 
    validates :routing_number, presence: true 

    has_many :transfer_accounts, inverse_of: :account 
    has_many :transfers,   through: :transfer_accounts 

    belongs_to :bank, inverse_of: :accounts 

end 


/models/bank.rb 

class Bank < ActiveRecord::Base 

    validates :name,  presence: true, 
          uniqueness: { case_sensitive: false } 
    validates :connect_uri, presence: true 

    has_many :accounts 

end 


/controllers/transfers_controller.rb 

class TransfersController < ApplicationController 

    def new 
    @transfer = Transfer.new 
    @transfer.transfer_accounts.build(account_transfer_role: 'source').build_account 
    @transfer.transfer_accounts.build(account_transfer_role: 'destination').build_account 
    @valid_banks = Bank.all.collect {|c| [c.name, c.id]} # available banks seeded in database 
    end 

    def index 
    @transfers = Transfer.all 
    end 

    def show 
    @transfer = resource 
    end 

    def create 
    @transfer = Transfer.new(transfer_params) 
    if @transfer.save 
     redirect_to transfers_path, notice: "Transfer Created" 
    else 
     redirect_to transfers_path, alert: "Transfer Not Created" 
    end 
    end 

    def edit 
    resource 
    end 

    def update 
    if resource.update_attributes(transfer_params) 
     redirect_to transfers_path(resource),  notice: "Transfer Updated" 
    else 
     redirect_to edit_transfer_path(resource), alert: "Transfer Not Updated" 
    end 
    end 

    def destroy 
    resource.destroy 
    end 


    private 

    def resource 
    @transfer ||= transfer.find(params[:id]) 
    end 

    def transfer_params 
    params.require(:transfer). 
     permit(:name, :description, 
      transfer_accounts_attributes: 
       [:account_transfer_role, 
       account_attributes: 
        [:name, :description, :user_name, :password, 
        :routing_number, :account_number 
        ] 
       ]) 
    end 

end 


/controllers/banks_controller.rb 

class BanksController < ApplicationController 

    def index 
    @bank = Bank.new 
    @banks = Bank.by_last_updated_at 
    end 

    def show 
    @bank = resource 
    end 

    def create 
    @bank = Bank.new(bank_params) 
    if @bank.save 
     redirect_to banks_path, notice: "Bank Created" 
    else 
     redirect_to banks_path, alert: "Bank Not Created" 
    end 
    end 

    def edit 
    resource 
    end 

    def update 
    if resource.update_attributes(bank_params) 
     redirect_to banks_path(resource), notice: "Bank Updated" 
    else 
     redirect_to edit_bank_path(resource), alert: "Bank Not Updated" 
    end 
    end 

    def destroy 
    resource.destroy 
    end 


    private 

    def resource 
    @bank ||= Bank.find(params[:id]) 
    end 

    def bank_params 
    params.require(:bank). 
     permit(:name, :description, :connection_uri) 
    end 

end 


/views/transfers/_form.html.haml 

= simple_form_for :transfer do |t| 
    .form-inputs 

    = t.input :name, label: "Transfer Name" 
    = t.input :description, required: false, label: "Transfer Description" 

    = t.simple_fields_for :transfer_accounts do |ta| 

     - role = ta.object.account_transfer_role.titleize 

     = ta.input :account_transfer_role, as: :hidden 

     = ta.simple_fields_for :account do |a| 

     = a.input :bank_id, collection: @valid_banks, 
          include_blank: 'Select bank...', 
          id:   'bank', 
          class:   'bank_selector', 
          label:   '#{role} Bank', 
          error:   '#{role} bank selection is required.' 

     = a.input :name, label: "#{role} Account Name" 
     = a.input :description, required: false, label: "#{role} Account Description" 
     = a.input :user_name, label: "#{role} Account User Name" 
     = a.input :password, label: "#{role} Account Password" 
     = a.input :account_number, label: "#{role} Account Number" 
     = a.input :routing_number, label: "#{role} Account Routing Number" 

    = t.submit 


/db/migrate/20151102001000_create_transfers.rb 

class CreateTransfers < ActiveRecord::Migration 
    def change 
    create_table :transfers do |t| 

     t.string :name, null: false, default: '' 
     t.text :description 

     t.timestamps 

    end 
    end 
end 


/db/migrate/20151102002000_create_transfer_accounts.rb 

class CreateTransferAccounts < ActiveRecord::Migration 
    def change 
    create_table :transfer_accounts do |t| 

     t.string :account_transfer_role, null: false, default: '' 

     t.references :transfer, index: true 
     t.references :account, index: true 

     t.timestamps null: false 

    end 
    end 
end 


/db/migrate/20151102003000_create_accounts.rb 

class CreateAccounts < ActiveRecord::Migration 
    def change 
    create_table :accounts do |t| 

     t.string :name,   null: false, default: '' 
     t.string :description 
     t.string :user_name,  null: false, default: '' 
     t.string :password,  null: false, default: '' 
     t.string :account_number, null: false, default: '' 
     t.string :routing_number, null: false, default: '' 

     t.references :bank, index: true 

     t.timestamps 

    end 
    end 
end 


/db/migrate/20151102004000_create_banks.rb 

class CreateBanks < ActiveRecord::Migration 
    def change 
    create_table :banks do |t| 

     t.string :name,   null: false, default: '' 
     t.string :description 
     t.string :connection_uri, null: false, default: '' 

     t.timestamps 

    end 
    end 
end 


/db/migrate/20151102005000_add_foreign_keys_to_transfer_accounts.rb 

class AddForeignKeysToTransferAccounts < ActiveRecord::Migration 
    def change 

    add_foreign_key :transfer_accounts, :accounts 
    add_foreign_key :transfer_accounts, :transfers 

    end 
end 


/db/migrate/20151102006000_add_foreign_keys_to_accounts.rb 

class AddForeignKeysToAccounts < ActiveRecord::Migration 
    def change 

    add_foreign_key :accounts, :banks 

    end 
end 


/db/seeds.rb 

Bank.create(name:   'Acme Savings and Loan', 
      description: 'The number one bank in the northeast', 
      connection_uri: 'https://www.acmesavings.com') 
Bank.create(name:   'First Bank of Anytown', 
      description: 'The first and only bank in Anytown', 
      connection_uri: 'https://www.firstbankanytown.com') 
Bank.create(name:   'Generibank', 
      description: 'The most generic bank in the country', 
      connection_uri: 'https://www.generibank.com') 


/config/routes.rb 

Rails.application.routes.draw do 

    resources :transfers 
    resources :accounts 
    resources :banks 
    root to: 'dashboard#index' 

end 

Так, в настоящее время мои вопросы:

  1. Эта строка в представлении формы - role = ta.object.account_transfer_role.titleize
    дает мне "неопределенный метод` account_transfer_role» для nil: NilClass «ошибка, так что я делаю неправильно?

  2. Почему (или почему бы) accepts_nested_attributes_for линия в transfer_account модели работы в? У меня сложилось впечатление, что accepts_nested_attributes_for не работает на стороне ассоциации belongs_to из-за того, что это не родительский (или что-то в этом роде).

  3. Если я прокомментирую код, связанный с вопросом № 1, чтобы избежать этой ошибки, форма отображает, но я получаю только один набор полей ввода для вложенных атрибутов account. С каждым transfer, имеющими два transfer_accounts и два accounts построена и связанными с ним в «нового» действий transfers_controllertransfer_account:account_transfer_role значений «источника» и «назначения»), я не должен получать два набора полей ввода вложенных атрибутов account?

  4. Являются ли единственные числа/множественные числа правильными для моих вложенных атрибутов? В принципе, я сохранил их последовательностью, начиная с их ассоциаций. Например, transferhas_many :transfer_accounts, так transfer_accounts во множественном числе во всех следующих:

    /models/transfer.rb 
    
        accepts_nested_attributes_for :transfer_accounts 
    
    
    /controllers/transfers_controller.rb 
    
        @transfer.transfer_accounts.build(account_transfer_role: 'source').build_account 
        @transfer.transfer_accounts.build(account_transfer_role: 'destination').build_account 
        . 
        . 
        . 
        def transfer_params 
        params.require(:transfer). 
         permit(:name, :description, 
          transfer_accounts_attributes: 
           [:account_transfer_role, 
           account_attributes: 
            [:name, :description, :user_name, :password, 
            :routing_number, :account_number 
            ] 
           ]) 
        end 
    
    
    /views/transfers/_form.html.haml 
    
        = m.simple_fields_for :transfer_accounts do |ma| 
    

    То же самое относится и к account, за исключением единственного числа.

  5. Если я шаг 3, заполнить форму с одним набором account атрибутов при условии, затем представить, я получаю «нет маршрута матчей [POST]«/ переводы/новый»ошибка. Таким образом, очевидно, что-то не так с моей маршрутизации. Я не был уверен, как transfers и accounts должен появиться в routes.rb файле. как

    resources :transfers 
    resources :accounts 
    

    или

    resources :transfers do 
        resources :accounts 
    end 
    

    или, как еще каким-то другим способом. Кроме того, я не знал, нужно ли в файле маршрутов transfer_accounts.

Если вы дошли до этой строки, благодарю вас за ваше терпение.:>) И любая помощь, которую вы можете предоставить, была бы весьма признательна.

Приветствия, Tim

ответ

1

Решение оказалось невероятно простым, решение каждого из вопросов, поднятых в моих вопросах 1, 3, 4 и 5.

В форме, я изменил эту строку :

= simple_form_for :transfer do |t| 

к этому:

= simple_form_for @transfer do |t| 

На вопрос 1 account_transfer_role больше не был ник.
Для вопроса 3 он начал визуализировать поля ввода для transfer_accounts.
Для вопроса 4 единства и множественные числа в сильных параметрах оказались правильными, как показано.
На вопрос 5, эта версия маршрутов оказалась правильной:

resources :transfers 
resources :accounts 

хотя я упростил его:

resources :transfers, :accounts 

Что касается вопроса 2, лучший ответ, который я придумал, что мое понимание, похоже, было неверным и что accepts_nested_attributes_for: действительно работает на стороне ассоциации, потому что он работает на меня.

Я надеюсь, что это поможет любому, кто борется с формами, которые имеют вложенные атрибуты для ассоциации has_many, through.

Cheers!

Смежные вопросы