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”为零:NilClass“错误,那么我在那里做错了什么?

  2. 为什么(或为什么会)的accepts_nested_attributes_for线在transfer_account模型的工作?我的印象是,accepts_nested_attributes_for在协会的belongs_to一侧不起作用,因为它不是父母(或其他情况)。

  3. 如果我注释掉与问题#1相关的代码以避免该错误,表单将呈现,但我只获取account嵌套属性的一组输入框。具有两个transfer_accounts和两个accountstransfers_controller的“”行动(的“”与transfer_account:account_transfer_role价值观和“目的地”)建成并与它相关联,每个transfer我不应该会得到两套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]“/转让/新”的错误。所以,很明显什么是错的我的路由选择。我不知道如何transfersaccounts应该出现在routes.rb中文件。作为

    resources :transfers 
    resources :accounts 
    

    resources :transfers do 
        resources :accounts 
    end 
    

    或仍另一种方式。另外,我也不知道路由文件中是否需要transfer_accounts

如果你已经到了这一行,感谢您的耐心。>>)任何帮助,你可以提供将不胜感激。

干杯, 添

回答

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:确实在协会的belongs_to侧工作,因为它正在为我工​​作。

我希望这有助于任何人都与具有has_many, through关联的嵌套属性的表单挣扎。

干杯!

相关问题