将控制器中的url params hash传递给另一个方法,变为nil

时间:2013-01-25 16:13:07

标签: ruby-on-rails controller ruby-on-rails-3.2

我的路线与/edit_account => accounts#edit相匹配,因为如果帐户ID未使用当前用户ID且account#edit方法与{{1}共享}}

/accounts/[:id]/edit

我遇到的问题是class AccountController < ApplicationController ... def edit # This doesn't work: params = retrieve_id_if_missing(params) # This works: # aHash = params # params = retrieve_id_if_missing(aHash) end def retrieve_id_if_missing(params) # raise params.inpect => returns nil at this point if params[:id].nil? and !logged_in? redirect_to root_path else params[:id].nil? params[:id] = current_user.id end params end end ,当传递给类方法时,params正在变为retrieve_id_if_missing。但是,如果我将nil分配给另一个变量。例如,params,在将其传递给aHash之前,它将包含预期数据retrieve_id_if_missing

我已经尝试寻找原因但是做得很短,有人可以向我解释为什么会发生这种情况吗?

3 个答案:

答案 0 :(得分:2)

你试过吗

class AccountController < ApplicationController
  ...
  def edit

    retrieve_id_if_missing


  end

  def retrieve_id_if_missing()
    if params[:id].nil? and !logged_in?
      redirect_to root_path
    else params[:id].nil?
      params[:id] = current_user.id
    end
      params
  end
end

我很确定params将在该方法的范围内。

无论如何,请查看宝石设计。它应该拥有你想要的一切和更多

有了设计,你可以使用

before_filer :authenticate_user!

位于控制器的顶部

https://github.com/plataformatec/devise

答案 1 :(得分:0)

虽然我无法回答为什么你的params对象会被提供的代码覆盖,但这里有一些想法。

class AccountController < ApplicationController
  before_filter :retrieve_id_if_missing, only: :edit

  def edit
    # You'll find params[:id] prepopulated if it comes here,
    # else the request has been redirect
  end

protected

  # There should be no need to pass the params object around, it should be accessible everywhere
  def retrieve_id_if_missing
    if logged_in?
      params[:id] ||= current_user.id # conditional assignment will only happen if params[:id] is nil
    end

    # Redirect to root if params[:id] is still blank, 
    # i.e. user is not logged in and :id was not provided through route
    if params[:id].blank?
      flash[:alert] = 'You need to be logged in to access this resource.'
      return redirect_to root_url # early return!
    end
  end
end

答案 2 :(得分:0)

Ruby解释器将params视为局部变量,并在看到赋值时使用nil初始化它。这在执行retrieve_id_if_missing之前发生。

这就是为什么在调用方法之前显式地为局部变量赋值避免错误的原因,因为Ruby的nil初始化没有发生。

以下示例说明了这一点:

示例#1

def foo(bar)
  puts "foo bar: #{bar.class}"
end
bar = foo(bar) # => nil
puts "bar: #{bar.class}"

# Outputs: 
#     foo bar: NilClass 
#     bar: bar: NilClass 

示例#2

a = a # => nil
puts "a: #{a.class}"

# Outputs: 
#    a: NilClass

示例#3

a = 123 if a # => nil
puts "a: #{a.class}"

# Outputs: 
#    a: NilClass

参考文献:

Why is a = a nil in Ruby?

  

Ruby解释器在看到一个局部变量时用nil初始化   转让给它。它在执行之前初始化局部变量   赋值表达式,甚至在无法访问赋值时   (如下例所示)。这意味着您的代码初始化为nil   然后表达式a = nil将评估为右手值。

     

a = 1如果是假的a.nil? #=&gt; true第一个赋值表达式不是   执行,但是a用nil初始化。

Ruby: method inexplicably overwritten and set to nil

  

这是另一个例子:

     

a = 123,如果#=&gt;没有#=&gt;没有我们不能说是否a   因为我们从未设置过,但Ruby看到a = 123并初始化a,   然后到达如果a点是零

     

我真的认为这是翻译的怪癖。加里伯恩哈特   在wat(https://www.destroyallsoftware.com/talks/wat)取笑它   a = a