不将变量发送到另一个控制器

时间:2014-07-09 14:33:51

标签: ruby-on-rails ruby ruby-on-rails-4

我有一个小问题:

我正在尝试从控制器1向控制器2发送变量,然后将其发送回控制器1.这是逻辑:

  1. 要开始制作新模型,用户必须登录。
  2. 访客用户还必须有权访问新模型的路径。
  3. 如果未登录,则必须重定向访客用户才能登录。
  4. 登录后,用户必须返回之前尝试访问的路径。
  5. 我决定将模型的类型传递给登录屏幕,然后将其传递回新的模型操作。

    变量类型通常来自路径,因此在重定向到登录屏幕时,我只是将其传递过来。

    businesses_controller.rb

    before_filter :require_login 
    
    def require_login
      unless current_user 
        redirect_to signin_path( :type => params[:type])
      end
    end
    

    当我被重定向时,变量会被传递到我的网址 - 到目前为止,很好:

    /signin?type=ccompany
    

    当我尝试从URL中获取变量并使用其值将成功登录的用户重定向回他试图访问的位置时出现问题:

    sessions_controller.rb

    class SessionsController < ApplicationController
    before_filter :initialize_type , :only => [:new , :create]
      def new
    
      end
    
      def create
       user = User.find_by(email: params[:session][:email].downcase)
    
       if user && user.authenticate(params[:session][:password])
         sign_in user
         if defined?(@type)
    
          redirect_to send("new_#{@type}_path")
         else
          redirect_back_or user
         end
    
       else
         flash.now[:error] = t('sign.invalid')
         render 'new'
       end
      end
    
      def destroy
        sign_out
        redirect_to root_url
      end
    
     private
      def initialize_type
        @type = params[:type]
      end
    end
    

    当我将@type变量放入我的视图中时,其值呈现没有问题。但是当我尝试登录时,这是我得到的错误:

    undefined method `new__path' for #<SessionsController:0x007f76189d42f8>
    

    enter image description here

    我也试过

    redirect_to :controller => "businesses" , :action => "new" , :type => params[:type]
    

    但是类型符号没有键传递。我也试过在那里放一个变量,但仍然不起作用。

    到目前为止,它仅在我写下与路径匹配的字符串时才起作用,但这不是我需要的。我需要传递params [:type]哈希的值。我已经将变量的值放在视图中并且它都很好,但是当我尝试将它传递给函数时,它的值会以某种方式'消失'。

    我该如何做到这一点?

2 个答案:

答案 0 :(得分:4)

问题是:

if defined?(:type)

它总是返回true,因为总是定义一个符号。你想要的是:

if defined?(@type)

然而,这可能会增加“无意识的功能”。对于您的代码,因为nil在ruby中定义得很好。你应该这样做:

if @type

注:

I need to pass the value of the :type symbol. - 符号没有价值。变量有值,符号是符号,它是自己的值。

在理解了问题之后:

上述情况仍然存在。

您无法将实例变量从一个操作传递到另一个操作。对于每个请求,rails实例化新的控制器实例,并且所有实例变量都将丢失。有很多方法可以通过它。

  1. 在表单中创建隐藏字段以保存值。您需要记住,任何互联网用户都可以覆盖其价值,而对互联网的运作方式知之甚少。

  2. 在您的新操作中,将值写入会话并在创建操作中读取它。由于会话要么存储在服务器端,要么存储在加密的cookie中,所以任何人都可以使用它进行调整。

答案 1 :(得分:0)

好的,我找到了一个解决方法。它有点笨拙并可能导致安全问题,但它确实有效。我强制变量作为会话参数传递。

我将收到的变量作为隐藏字段放在新的会话表单中:

<%= form_for(:session , url: sessions_path ) do |f| %>

 <%= f.label  :email , t('session.email') %>
 <%= f.text_field :email %>


 <%= f.label  :password , t('session.password') %>
 <%= f.password_field :password%>

 <%= f.hidden_field :val , value: @type %> 
  #@type is set in the before filter as a variable passed from another controller

然后,提交后,我抓住参数并将其放入其位置:

    if user && user.authenticate(params[:session][:password])
 sign_in user
 if defined?(@type)
   params.require(:session).permit(:val)
   @type = params[:session][:val]
  redirect_to send("new_#{@type}_path")
 else
  redirect_back_or user
 end
else
  flash.now[:error] = t('sign.invalid')
  render 'new'
end
end

现在功能正常。不幸的是,我必须将视图用作传递变量的“管道”。如果有人为此编写辅助方法或更好的解决方法,我会非常高兴。

干杯。