2013-10-23 43 views
0

有一个关于has_manybelongs to的快速问题。我处于:user has_many :accounts:account belongs_to the user的情况。未保存Rails has_many关系(可能与ajax相关)

在我的控制器中,我首先分配了@accounts = current_user.accounts。调试[正确]向我报告这个特定用途有2个帐户。在下一行中,我保存了一个无效的帐户(调试也会告诉我这是无效的)。然而,当我检查current_user.accounts.countcurrent_user.accounts.all.countcurrent_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引擎下发生了什么?有这个问题,我感到羞怯。

如何告诉导轨只加载保存在db中的current_user.accounts?这种急切加载是相关的吗?

我在Rails 4上运行,使用postgresql,如果这有所帮助。

回答

2

混乱的原因是CollectionProxyActiveRecord::Associations(事情比较复杂一点,比他们看了):

current_user.accounts是CollectionProxy,不是Array

想想CollectionProxy的集装箱,内部具有@owner为CURRENT_USER,@target为一组账户和@reflection的 - @owner@target

当您运行current_user.accounts.new()之间还挺链接(协会) - 你只需要添加另一个对象成@target,所以通过current_user.accounts迭代你正在遍历@target,它包含包括新创建的对象。

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

因为Rails是懒惰的,直到你确实需要它的对象(= accounts)才会加载@target。所以要运行.count运行直接SQL请求而不是实例化@target中的所有对象并计算它们会更便宜。

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

BTW,all Rails中4已被弃用,使用to_a代替

那么,我该怎么办用这些知识,人呢?我只需要显示没有未保存帐户的帐户。

正义的力量重装:@accounts = current_user.accounts(force_reload = true)

OR @accounts = current_user.accounts.reload

OR @accounts = current_user.accounts.order('created_at DESC')它将运行重载自动的,因为为了通过SQL

+0

感谢Leger的需要直接请求对象。你能解释为什么我的观点会加载未保存的无效账户模型吗?如果没有.all(order:'created_at DESC')'部分,我通过@accounts迭代的视图管理也迭代了无效的已保存模型。 – Josiah

+0

有关更多详细信息的更新回答。简而言之 - 如果没有'.each(order:'created_at DESC')'部分,您将''.each'迭代到由帐户创建的Array上(因为'.each'在应用之前隐含'to_a')。 – Leger

+0

太棒了!非常感谢Leger。我觉得后面发生了这样的事情,只是不知道该怎么处理它,或者具体是什么。谢谢您的帮助! – Josiah