Rails ActiveAdmin has_one和belongs_to导致<plural_resource>&#39;

时间:2017-02-28 23:05:30

标签: ruby-on-rails ruby activerecord activeadmin

在Rails中,我有一个&#39;用户&#39;模特和钱包&#39;模型。 A&#39;用户&#39; has_one钱包和每个钱包&#39; belongs_to a&#39; User&#39;。我做了一个&#39; Show&#39; ActiveAdmin中的页面,用于查看用户的电子钱包。但是,转到该页面会返回以下错误:

undefined method `wallets' for #<User:0x007f...>

然而,当我将用户模型更新为&#39; has_many:wallets&#39;而不是&#39;:has_one wallet&#39;,一切正常。以下是我的模型和ActiveAdmin代码中的相关代码:

型号:

class User < ActiveRecord::Base
  has_one :wallet, dependent: :destroy
end


class Wallet < ActiveRecord::Base
  belongs_to :user
end

ActiveAdmin:

ActiveAdmin.register Wallet do
  belongs_to :user
  actions :all, except: :destroy

  show do
    div do
      'hello'
    end
  end
end

ActiveAdmin.register User do
  actions :all, except: :destroy
  permit_params

  action_item :wallet, only: :show do
    link_to('Wallet', admin_user_wallet_path(user, user.wallet.id))
  end

  index do...
end

关于我可能出错的地方的任何想法?

编辑1:更新以更正说明中的冒号放置错误

编辑2:

回应:

  

你能显示你的路线文件吗?另外,您能否给我们提供错误消息的完整回溯并向我们提供rake路由的输出?我怀疑他们抱怨钱包没有被定义的原因(即使你从未在上面的代码中调用钱包)是因为某些路由正在假设关系的外观。 - Glyoko 4分钟前

  1. 我的路线文件中没有提及&#39;钱包&#39;或者&#39;钱包&#39;。
  2. 我的堆栈错误更具体地如下所示:

    activemodel(4.1.15)lib / active_model / attribute_methods.rb,第435行

    如果您需要更多信息,请与我们联系。

  3. 以下是来自&#39; bin / rake路线的相关输出&#39;:

    • admin_user_wallets GET /admin/users/:user_id/wallets(.:format)admin / wallets #index

    • POST /admin/users/:user_id/wallets(.:format)admin / wallets #create

    • new_admin_user_wallet GET /admin/users/:user_id/wallets/new(.:format)admin / wallets #new

    • edit_admin_user_wallet GET /admin/users/:user_id/wallets/:id/edit(.:format)admin/wallets#edit
    • admin_user_wallet GET
      /admin/users/:user_id/wallets/:id(.:format)admin / wallets #show
    • admin_user_wallet PATCH /admin/users/:user_id/wallets/:id(.:format)admin / wallets#update
    • admin_user_wallet PUT /admin/users/:user_id/wallets/:id(.:format)admin / wallets#update

3 个答案:

答案 0 :(得分:1)

好的..所以我有同样的问题。我有一个belongs_to父母,其父母只有一个孩子模型的has_one .....似乎什么都没有,所以我决定假装它。我不确定这是否是最好的方法,但它有效。在父模型中,添加一个方法:

class User < ActiveRecord::Base
   has_one :wallet
   def wallets
     Wallet.where(user_id: id)
    end
  end

上面的代码是一个修补程序,直到我找到其他方法来实现我需要的东西。

答案 1 :(得分:1)

ActiveAdmin内部使用InheritedResources gem,belongs_to方法最终在InheritedResources内部。

可能的解决方案

ActiveAdmin.register Wallet do
  belongs_to :user, singleton: true
  actions :all, except: :destroy
end

选项singleton: true使Wallet成为User的唯一资源。

如果不需要optional: true来展示电子钱包,则另一个选择User可能会有所帮助

答案 2 :(得分:0)

即使你的路线可能没有明确地引用wallet(s),也可能会有一些关于记录如何相互关联的假设。

查看rake routes的输出,特别是:

admin_user_wallet GET
/admin/users/:user_id/wallets/:id(.:format) admin/wallets#show

当您致电admin_user_wallet_path(user, user.wallet.id)时,它与/admin/users/:user_id/wallets/:id(.:format)路线相匹配。请注意,如何在路径中同时使用用户ID和钱包ID。这是一个提示,这里有一些东西,因为如果你有用户,应该只有一个钱包与它相关联。您不应该需要同时提供用户和钱包ID。

由于钱包资源嵌套在用户下,因此您查看用户钱包的页面实际上更多的是索引页面而不是节目。如果钱包是一个独立的资源,那么你可以有一个像/admin/wallets/:id这样的路径,事情会很好。

但由于钱包是用户的子资源,理想情况下您需要/admin/users/:user_id/wallet之类的路径。由于您已拥有该用户,因此无需传递钱包ID。

tl; dr:尝试将show更改为index,然后查看它的位置。 e.g。

index do
  div do
    'hello'
  end
end

# ...

action_item :wallet, only: :index do
  link_to('Wallet', admin_user_wallets_path(user))
end