使用帮助程序在控制器之间传递实例变量

时间:2016-12-10 19:50:42

标签: ruby-on-rails

我有三个实体:用户,联系人和订婚。 user has_many: contacts。联系belongs_to: user。用户与联系人进行交互。我还有一个参与belongs_to: contact。 在我的views/contacts/show.html.erb我希望展示特定联系人页面,并让用户通过填写​​参与表单来注册与联系人的互动。我希望在联系人页面上创建的参与度与该特定联系人相关联。 所以我展示了一个联系人:

resources :contacts
resources :engagements, only: [:create, :edit, :destroy]

class ContactsController < ApplicationController
      include ApplicationHelper
       def show
        @contact = Contact.find(params[:id])
        set_current_contact @contact.id  #pass the particular id to helper
      end
    end

在帮助器中定义方法:

module ApplicationHelper
  def set_current_contact(contact_id)
    @current_contact = Contact.find_by(id: contact_id) 
  end

  def the_current_contact
    @current_contact   #create instance variable for the other helper
  end
end

我要做的关键是让参与控制器知道&#39;联系用户正在注册订婚。即将@contact传递给EngagementsController

class EngagementsController < ApplicationController
  def create
    @engagement = the_current_contact.engagements.build(engagement_params) 
  end
end

我收到错误:

undefined method `set_current_contact' for #<EngagementsController:0x007f2c2c24f360>

第一个问题是我不明白为什么控制器无法从ApplicationHelper访问方法? 我不是故意问两个不同的问题,但第二个问题是以这种方式使用帮助是否是正确的方法。我知道HTTP是一种无状态协议,在这种情况下,帮助程序对于传递实例变量非常有用。我搜索了类似的帖子并找到了相关的Rails: Set a common instance variable across several controller actions但是虽然它推荐帮助者作为解决方案,但它没有特别解释如何使用帮助器。

编辑:我在include ApplicationHelper中添加了遗失的EngagementsController。现在错误是:

wrong number of arguments (given 0, expected 1)
Extracted source (around line #13):

  end

  13 def set_current_contact(contact_id)
  14   @current_contact = Contact.find_by(id: contact_id)
  15 end

2 个答案:

答案 0 :(得分:1)

您无法使用实例变量在两个请求之间共享数据,甚至不能在对同一控制器的两个请求之间共享数据。 Rails creates a new controller instance for every request。即便如此,您的应用可能会在负载均衡器后面,并且没有人可以保证第二个请求甚至可以由同一服务器提供服务。

实现目标的最佳方法是将contact_id作为参数传递给EngagementsController#create操作。或者使用会话数据。

答案 1 :(得分:0)

我找到了一种方法,contact_id可以访问EngagementsController,而无需通过帮助程序将变量从ContactsController传递到EngagementsController。嵌套资源:

  resources :contacts do
    resources :engagements 
  end

生成路径:

POST   /contacts/:contact_id/engagements(.:format)  engagements#create

因此,EngagementsController

可以访问互动的contact_id
def create
    @contact = Contact.find(params[:contact_id])
    @engagement = @contact.engagements.build(engagement_params)
end