使用DataMapper在Rails 3中保存嵌套资源窗体时出现“NoMethodError”错误

时间:2011-06-17 16:41:16

标签: ruby-on-rails postgresql datamapper

在我的控制器中我有:

def index
 @owner = current_user
 @accounts = @owner.accounts.all( :name.not => nil )
 @aliases = @owner.aliases.all( :id.not => nil )
 @transfer = @accounts.transfers.new()
end

def create 
@owner = current_user
 @account = @owner.accounts.first(:id => params[:account_id])
 @alias_out = @owner.aliases.first( :id => params[:alias_from]) 
 @alias_in = Alias.first( :id => params[:alias_to]) 

   @transfer =  @account.transfers.create(params[:transfer])  
                @alias_in.update(:transfers_in => params[:transfer]) 
                @alias_out.update(:transfers_out => params[:transfer]) 

在我看来:

<div id="accounts_list">
   <h2>Your accounts</h2>
    <% @accounts.each do |acc| %>
    <div class="each_element">
      <h3><u><%= acc.name%></u></h3>
      <b>Available money: <u><%= acc.value%> <%=acc.currency%></u></b>
      <div id="create_account">
         <h2>Create an transfer</h2>
    <%= form_for([acc, @transfer]) do |trans_form|%>
         <%= trans_form.label :amount %>
        <%= trans_form.text_field :amount %></br>
        <%= trans_form.fields_for :alias_from do |alias_from|%>
        <%= alias_from.label :alias_from %>
        <%= alias_from.collection_select :id, @aliases, :id, :id %> </br>
        <%end%>
        <%= trans_form.fields_for :alias_to do |alias_to|%>
        <%= alias_to.label :alias_to %>
        <%= alias_to.text_field :id %></br>
        <%end%>
        <%= trans_form.text_area :comment, :rows=>5 %></br>
        <%= trans_form.submit :value => "Transfer" %>
         <%end%>
        </div>
    </div>

    <% end %>
</div>
</div>

在我的模特中

class Transfer
  include DataMapper::Resource


  belongs_to :account
  belongs_to :alias_from, "Alias", :key =>true
  belongs_to :alias_to, "Alias", :key =>true 



   property :id, Serial
      property :amount, Integer, :required => true
      property :comment, Text


    end

    class Alias
  include DataMapper::Resource


  belongs_to :user
  has n, :transfers_in, "Transfer"  
  has n, :transfers_out, "Transfer"   

  property :id, String, :key => true, :unique => true

  validates_format_of :id, :with => /[0-9a-z\-]/i

end

所有这些对我来说都是

Started POST "/accounts/2/transfers" for 127.0.0.1
     

于2011-06-20 09:16:25 +0400         通过TransfersController处理#create as HTML         参数:{“utf8”=&gt;“✓”,“authenticity_token”=&gt;“令牌”,   “转移”=&GT; { “量”=&gt; “中30.3”,   “alias_from”=&gt; {“id”=&gt;“我的别名”},   “alias_to”=&gt; {“id”=&gt;“他的别名”},   “comment”=&gt;“评论文字”},   “提交”=&gt; “中传送”,   “ACCOUNT_ID”=&gt; “中2”}        ~SQL(0.525ms)SELECT“id”,“encrypted_pa​​ssword”,   “remember_created_at”   “reset_password_token”   “reset_password_sent_at”   “failed_attempts”,“unlock_token”,   “locked_at”,“sign_in_count”,   “current_sign_in_at”   “last_sign_in_at”   “current_sign_in_ip”   “last_sign_in_ip”,“用户名”,   “电子邮件”,“名称”,“国家”FROM   “用户”WHERE“id”IN(2)LIMIT 1        ~SQL(0.495ms)SELECT“id”,“name”,“currency”,“value”,“user_id”   FROM“accounts”WHERE(“user_id”= 2   AND“id”= 2)ORDER BY“id”LIMIT 1        ~SQL(0.414ms)SELECT“id”FROM“aliases”WHERE“id”=“我的别名”   订购“id”LIMIT 1        ~SQL(0.329ms)SELECT“id”FROM“aliases”WHERE“id”=   '他的别名'ORDER BY“id”LIMIT 1       在15ms完成

NoMethodError (undefined method `update' for nil:NilClass):
  app/controllers/transfers_controller.rb:10:in
     

`创建'

我不知道可能是什么问题。有什么建议?真的很感激。

1 个答案:

答案 0 :(得分:2)

mu太短是对的:all方法返回一个集合,而不是单个对象。相反,您必须使用first

@account = @owner.accounts.first(:id => :account_id)

get

@account = @owner.accounts.get(account_id)

根据评论进行更新:

您正在尝试更新别名,但这不是必需的。 transfer属于alias_fromalias_to。这意味着您的转帐表应包含两列:alias_from_idalias_to_id。这就是存储这些值的地方。

您没有使用fields_for。所以,而不是:

<%= trans_form.fields_for :alias_from do |alias_from|%>
  <%= alias_from.label :alias_from %>
  <%= alias_from.collection_select :id, @aliases, :id, :id %> </br>
<%end%>
<%= trans_form.fields_for :alias_to do |alias_to|%>
  <%= alias_to.label :alias_to %>
  <%= alias_to.text_field :id %></br>
<%end%>

你应该能够做到:

<%= trans_form.label :alias_from %>
<%= trans_form.collection_select :alias_from_id, @aliases, :id, :id %> </br>
<%= trans_form.label :alias_to %>
<%= trans_form.text_field :alias_to_id %></br>

您的控制器操作应如下所示:

def create 
  @owner = current_user
  @account = @owner.accounts.first(:id => params[:account_id])
  @transfer =  @account.transfers.create(params[:transfer])  

  # the rest of your code...
end

更新2

您可以在模型中设置正确的外键字段名称,如下所示:

class Transfer
  include DataMapper::Resource    

  belongs_to :account
  belongs_to :alias_from, "Alias", :key => true, :child_key => 'alias_from_id'
  belongs_to :alias_to, "Alias", :key => true, :child_key => 'alias_to_id'

  # Etc...