【问题标题】:The "NoMethodError" error while saving the nested resources form in Rails 3, using DataMapper使用 DataMapper 在 Rails 3 中保存嵌套资源表单时出现“NoMethodError”错误
【发布时间】:2011-06-17 16:41:15
【问题描述】:

在我的控制器中,我有:

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 作为 HTML 处理 参数:{"utf8"=>"✓", "authenticity_token"=>"token", "转账"=>{"金额"=>"30.3", "alias_from"=>{"id"=>"我的别名"}, "alias_to"=>{"id"=>"他的别名"}, "评论"=>"评论文字"}, “提交”=>“转让”, "account_id"=>"2"} ~ SQL (0.525ms) SELECT "id", "encrypted_pa​​ssword", "remember_created_at", "reset_password_token", "reset_password_sent_at", “失败的尝试”,“解锁令牌”, "locked_at", "sign_in_count", "current_sign_in_at", "last_sign_in_at", "current_sign_in_ip", "last_sign_in_ip", "用户名", “电子邮件”、“姓名”、“国家”来自 “用户” WHERE “id” IN (2) LIMIT 1 ~ SQL (0.495ms) SELECT "id", "name", "currency", "value", "user_id" 从“帐户”WHERE(“user_id”= 2 AND "id" = 2) ORDER BY "id" LIMIT 1 ~ SQL (0.414ms) SELECT "id" FROM "aliases" WHERE "id" = 'My Alias' ORDER BY "id" 限制 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

`创建'

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

【问题讨论】:

  • 嗯,你为什么认为问题出在它里面?这个特定帐户的正确方法是什么?
  • 好吧,按照我的逻辑,@account = @owner.accounts.all(:id =&gt; :account_id) 意味着我们从该成员的所有帐户中获取具有正确 id 的帐户,params[:transfer] 是表单中的参数 - {"utf8"=&gt;"✓", "authenticity_token"=&gt;"jgZw", "transfer"=&gt;{"amount"=&gt;"30.3", "alias_from"=&gt;{"id"=&gt;"MyAlias"}, "alias_to"=&gt;{"id"=&gt;"PayMe"}, "comment"=&gt;"comment text"}, "commit"=&gt;"Transfer", "account_id"=&gt;"2"}跨度>

标签: ruby-on-rails postgresql datamapper


【解决方案1】:

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...     

【讨论】:

  • Mischa 和 Mu 是正确的。当您应该使用单个对象时,您正在使用集合。 Get 或 First 是您应该使用的方法。
  • 是的,这似乎是正确的,谢谢。但现在我有undefined method update' for nil:NilClass`。我已经编辑了代码和日志。我什至需要手动更新,还是关联自动更新?
  • @Maay,我更新了我的答案。你明白我在说什么吗?
  • 我明白你在说什么,谢谢,确实有道理。我已经更改了表格并在传输模型中添加了两列(alias_from_idalias_to_id),但现在它向我抛出了 ERROR: null value in column "alias_id" violates not-null constraint 错误,但现在我明白了,只需阅读有关关联的更多信息。感谢您的帮助和时间!
  • @Maay,不客气。您现在收到的错误消息与 alias_from_idalias_to_id 不是默认值有关。在您的别名模型中,您必须像这样指定外键的名称::child_key =&gt; :alias_from_id。请参阅我的更新答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-05
  • 1970-01-01
  • 1970-01-01
  • 2012-06-11
相关资源
最近更新 更多