0

has_many有一个关于and的快速问题belongs to。我处于 a:user has_many :accounts和a 的情况:account belongs_to the user

在我的控制器中,我首先分配@accounts = current_user.accounts. 调试 [正确] 向我报告此特定用途有 2 个帐户。在下一行中,我保存了一个无效帐户(调试也正确地告诉我它是无效的)。但是,当我检查current_user.accounts.countvs current_user.accounts.all.countvs时current_user.accounts.all(order: 'created_at DESC'),我得到以下值:

- current_user.accounts.count = 2
 - current_user.accounts.all.count = 3
 - current_user.accounts.all(order: 'created_at DESC') = 2

检查数据库确认无效模型确实没有被保存。

此外,在我提供的动态 ajax 重新加载视图中@accounts = current_user.accounts(在 if-else 循环检查if @account.save工作后设置),它循环显示 3 个帐户,包括无效帐户。

这是控制器的代码:

def create

    @account = current_user.accounts.new(account_params) 

    if @account.save
      @accounts = current_user.accounts.all(order: 'created_at DESC')
      #redirect_to accounts_path, :success => "Account successfully created."
      flash[:success] = "Account sucessfully created."
      # respond_to :js
      respond_to do |format|
        format.js {
          render :create
        }
      end


    else
      @accounts = current_user.accounts.all(order: 'created_at DESC')

      flash[:error] = "There was a problem with adding your account."
      respond_to do |format|
        format.js {
          render :create
        }
      end

    end
    puts "Final Accounts is #{@accounts.count} compared to #{current_user.accounts.all.count} compared to #{current_user.accounts.count}" # outputs 2, 3, and 2 for an invalid model being saved
  end

有人可以向我解释我应该这样做的正确方式吗?或者更好的是,Rails 引擎下发生了什么?我为遇到这个问题而感到羞怯。

我如何告诉 rails 只加载current_user.accounts保存在数据库中的那些?这与急切加载有关吗?

我在 Rails 4 上运行,如果这有所作为,则使用 postgresql。

4

1 回答 1

2

混淆的原因是CollectionProxyActiveRecord::Associations事情比他们看起来更复杂):

current_user.accounts是 CollectionProxy,而不是Array.

将 CollectionProxy 视为容器,其内部具有@ownercurrent_user、@target帐户集和-和@reflection之间的某种链接(关联)@owner@target

当您运行时current_user.accounts.new()- 您只需将另一个对象添加到@target中,因此迭代current_user.accounts您正在迭代 @target,其中包含包括新创建的对象在内的对象。

但是等等,为什么.count返回的对象更少?

因为 Rails 是惰性的,并且@target在您真正需要它的对象(=帐户)之前不会加载。因此,仅运行.count直接 SQL 请求而不是实例化所有对象@target然后计算它们会更便宜。

这就是为什么当你这样做时,你current_user.accounts.count会得到大量保存的对象。当你这样做时current_user.accounts.all.count- 它实例化 中的所有对象@target,将它们转换为Array并计算此数组中的帐户(等于current_user.accounts.size)。

顺便说一句,all在 Rails 4 中已弃用,请to_a改用

那么,我该如何处理所有这些知识,伙计?我只需要显示没有未保存的帐户。

只需强制重新加载:@accounts = current_user.accounts(force_reload = true)

或者@accounts = current_user.accounts.reload

或者@accounts = current_user.accounts.order('created_at DESC')它将自动运行重新加载,因为订单需要通过 SQL 直接请求对象

于 2013-10-23T05:38:45.420 回答