【问题标题】:How can I pass objects from one controller to another in rails?如何在 Rails 中将对象从一个控制器传递到另一个控制器?
【发布时间】:2010-11-20 04:01:10
【问题描述】:

我一直在尝试了解 render_to,但没有取得多大成功。

基本上我有控制器方法:

def first
  #I want to get the value of VAR1 here
end

def second
  VAR1 = ["Hello", "Goodbye"]
  render_to ??
end

我不知道如何做到这一点。最初我只是想渲染 first.html.erb 文件,但这似乎也不起作用。

谢谢

编辑:我很欣赏我收到的答案,但是他们都倾向于避免使用渲染方法或redirect_to。基本上是不是你不能将变量从控制器传递到控制器?我必须认为有某种方法,但我似乎找不到它。

【问题讨论】:

    标签: ruby-on-rails controller model-view-controller


    【解决方案1】:

    我通常不会让我的控制器调用彼此的操作。如果您有一个以大写字母开头的标识符,那么在 Ruby 中这是一个常量。如果你想要一个实例级变量,让它以@开头。

    @var1 = ["Hello", "Goodbye"]
    

    你能解释一下你的目标是什么吗?

    【讨论】:

    • 基本上我正在尝试执行一个多步骤过程,其中用户上传文件,然后我处理它并将其重新呈现给他们,让他们对其进行某些更改,然后最后将其插入数据库。为此,我需要能够将该对象传递给另一个控制器或至少另一个控制器视图。
    • 与其这样做,为什么不将工作的中间结果存储在数据库中并将其标记为不完整。这样你就知道你可以像往常一样通过模型访问它,并且你可以适应服务器故障。
    【解决方案2】:

    将对象分配给常量不是一个好主意。确实,这是在一个全局空间中,但它对每个人都是全局的,因此任何其他访问此请求的用户都将获得此对象。有几个解决方案。

    我假设您正在处理一个多步骤表单。在这种情况下,您可以将设置的属性作为隐藏字段传递。

    <%= f.hidden_field :name %>
    

    如果有很多字段,这可能很乏味,因此您可能需要循环通过 params[...] 哈希或 column_names 方法来确定要传递哪些属性。

    您也可以将属性存储在session

    def first
      @item = Item.new(params[:item])
      session[:item_attributes] = @item.attributes
    end
    
    def second
      @item = Item.new(session[:item_attributes])
      @item.attributes = params[:item]
    end
    

    第三,正如Paul Keeble 提到的,您可以将模型保存到数据库中,但将其标记为不完整。您可能需要为此使用state machine

    最后,你可能想看看Acts As Wizard plugin

    【讨论】:

    • 嗨 Ryan,会话选项在 Rails 3 中仍然有效吗?如果我存储 @item.attributes 它将受保护的属性(如 id 和时间戳)存储为 nil,稍后尝试从此会话构建新对象会导致 MassAssignmentSecurity 错误
    • object.attributes.slice('field1', 'field2') 似乎是只需将 field1 和 field2 替换为所需的任何字段即可。
    【解决方案3】:

    您是否考虑过使用闪存哈希?很多人仅将它用于错误消息等,它明确用于您可能感兴趣的那种瞬态数据传递。

    基本上,flash 方法返回一个哈希值。您分配给哈希中的键的任何值都将可用于下一个操作,但随后它就消失了。所以:

    def first
      flash[:var] = ["hello", "goodbye"]
      redirect_to :action => :second
    end
    
    def second
      @hello = flash[:var].first
    end
    

    【讨论】:

      【解决方案4】:
      1. 方式 1
        全局变量 (在并发请求期间失败)
      2. 方式 2
        类变量 (在并发请求期间失败)
      3. 方式 3

        • 在请求之间将对象存储在服务器上。典型的方法是将其保存在会话中,因为它会自动为您序列化/反序列化对象。
        • 序列化对象并将其包含在表单中的某处,并且 从下一个请求中的参数反序列化它。这样您就可以在会话中存储属性。

          先定义 @item = Item.new(params[:item]) 会话[:item_attributes] = @item.attributes 结尾 定义秒 @item = Item.new(session[:item_attributes]) @item.attributes = 参数[:item] 结尾
      4. 方式 4
        flash 提供了一种在动作之间传递临时对象的方法。您放入 Flash 中的任何内容都将在下一个动作中暴露出来,然后被清除。
         定义新
           @test_suite_run = TestSuiteRun.new
           @tests = Test.find(:all, :conditions => { :test_suite_id => params[:number] })
           flash[:someval] = 参数[:number]
         结尾
         定义创建
        @test_suite_run = TestSuiteRun.new(params[:test_suite_run]) @tests = Test.find(:all, :conditions => { :test_suite_id => flash[:someval] })
        结束
      5. 方式 5
        你可以使用rails缓存。

        Rails.cache.write("list",[1,2,3]) Rails.cache.read("列表") 但是当不同的会话有不同的值时会发生什么呢? 除非您确保整个会话中列表名称的唯一性,否则此解决方案将在并发请求期间失败
      6. 6路
        在一个动作中,根据会话 id 将值存储在 db 表中,其他动作可以根据会话 id 从 db 中检索它。

      7. 7路

        类 BarsController before_filter :init_foo_list

        定义方法1 渲染:方法2 结束

        定义方法2 @foo_list.each 做 |项目| # 做一点事 结尾 结束

        def init_foo_list @foo_list ||= ['钱','动物','Ummagumma'] 结尾 结束

      8. 8 路
        从动作发送到视图,再从视图发送到控制器中的其他动作。

      【讨论】:

        猜你喜欢
        • 2014-01-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多