在渲染视图之前,如何修改控制器中的Ruby对象?

时间:2014-03-18 04:13:06

标签: ruby-on-rails ruby ruby-on-rails-3 mongodb hash

这是一个长期以来一直想要回答的问题,因为我发现了其他方法,从不打扰。

在我对控制器的索引操作中 - 我有这一行:

@all_pos = PurchaseOrder.where(:merchant_id => session[:admin_id], :received => false).sort([sort_column,sort_direction])

所以我此时得到了一个Plucky查询 - 结果没被抓住,只是锁定了一个光标(我得到了这个部分)。

我想要做的是在将它发送到视图之前修改这个@all_pos对象(哈希)。

为什么呢?

因为我已经完成了一些关系内容(喘气),我将ObjectId存储为此对象中的一个值。

:po_vendor存储为ObjectId,指向描述供应商的文档。我不想使用MongoMapper" belongs_to"功能(无论出于何种原因我不记得 - 我只是没有),所以当我渲染我的视图时,如果我想调用@ all_pos.po_vendor我将打印一个ObjectId页。没有bueno。

现在我可以从视图中查找文档 - 但这不是很Railsy!

所以我想要做的是修改@all_pos array-hash中的每个元素。

@all_pos.each do |po|
        vn = Vendor.find_by_id(po.po_vendor).name
        po.po_vendor = vn
      end

在我的脑海中,上述工作 - 我访问po_vendor键并设置它的值。但它没有过滤到@all_pos,最大的问题是我没有Rails词汇来描述我在这里尝试做的事情。

图! ?搜集! ?如果我知道用来形容这些的话,我可以谷歌并弄明白:(

2 个答案:

答案 0 :(得分:0)

使用关联来解决您的问题 在PurchaseOrder模型中添加Vendor

的关联
class PurchaseOrder < ActiveRecord::Base
  belongs_to :vendor, foreign_key: :po_vendor
  delegate :name, to: :vendor, prefix: true, allow_nil: true
  ...
  ...
  ...
end
控制器中的

@all_pos = PurchaseOrder.includes(:vendor).where(:merchant_id => session[:admin_id], :received => false).sort([sort_column,sort_direction])

然后,在View中你可以使用

  @all_pos.each do |po|
    po.vendor_name 
  end

答案 1 :(得分:0)

主要问题是,在分配时,@ all_pos是查询而不是查询产生的文档。 在迭代查询时,您查找采购订单,然后查找供应商, 但是您没有可变的句柄来引用所提取的采购订单 (@all_pos仍然只引用查询,而不是引用的文档), 没有引用,你就无法访问它们,它们将被垃圾收集。

以下测试是我认为你想要的,有两个例子。 第一个是个别供应商db在您的问题中找到的。 第二个创建了一个本地哈希,用于从供应商的单个公共数据库查找中查找效率。

测试/单元/ purchase_order_test.rb

require 'test_helper'
require 'pp'

class PurchaseOrderTest < ActiveSupport::TestCase
  def setup
    PurchaseOrder.delete_all
  end

  test "the truth" do
    puts "\nMongoid::VERSION:#{Mongoid::VERSION}\nMoped::VERSION:#{Moped::VERSION}"
    session = {admin_id: 1}
    sort_column = :merchant_id
    sort_direction = 1
    @query = PurchaseOrder.where(:merchant_id => session[:admin_id], :received => false).sort([sort_column,sort_direction])
    assert_equal(Mongoid::Contextual::Mongo, @query.class)

    vendor = Vendor.create(name: 'Amazon')
    PurchaseOrder.create(merchant_id: 1, received: false, po_vendor: vendor._id)

    @all_pos = @query.to_a
    assert_equal(PurchaseOrder, @all_pos.first.class)
    @all_pos.each do |po|
      po.po_vendor = Vendor.find(po.po_vendor).name
    end
    puts "with individual vendor db find:\n#{@all_pos.inspect}"

    @all_pos = @query.to_a
    vendors = Vendor.find(@all_pos.collect{|po| po.po_vendor})
    vendor_hash = Hash[*vendors.collect{|v| [v._id, v.name]}.flatten]
    @all_pos.each do |po|
      po.po_vendor = vendor_hash[po.po_vendor]
    end
    puts "with single common vendor db find:\n#{@all_pos.inspect}"
  end
end

rake test

Run options:

# Running tests:

[1/1] PurchaseOrderTest#test_the_truth
Mongoid::VERSION:3.1.6
Moped::VERSION:1.5.2
with individual vendor db find:
[#<PurchaseOrder _id: 535803b87f11ba5720000002, merchant_id: 1, received: false, po_vendor: "Amazon">]
with single common vendor db find:
[#<PurchaseOrder _id: 535803b87f11ba5720000002, merchant_id: 1, received: false, po_vendor: "Amazon">]
Finished tests in 0.040748s, 24.5411 tests/s, 49.0822 assertions/s.
1 tests, 2 assertions, 0 failures, 0 errors, 0 skips