3

我有一个匹配的路由,/edit_account => accounts#edit因为没有提供帐户 ID,它应该使用当前用户 ID,并且该account#edit方法与/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它之前,它将包含预期的数据,{"action" => "edit", "controller" => "account"}

我试图寻找一个原因,但没有找到原因,有人可以向我解释为什么会发生这种情况吗?

4

3 回答 3

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

我相当确定参数将在该方法的范围内。

无论如何,请为此查看 gem 设计。它应该拥有您想要的一切以及更多

使用设计,您可以使用

before_filer :authenticate_user!

在控制器的顶部

https://github.com/plataformatec/devise

于 2013-01-25T16:23:15.573 回答
1

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

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

以下示例证明了这一点:

示例 #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

参考:

为什么a = a nil在 Ruby 中?

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

a = 1 如果为假 a.nil?# => true 第一个赋值表达式没有执行,而是用 nil 初始化 a。

Ruby:方法被莫名其妙地覆盖并设置为零

这是另一个例子:

a = 123 if a # => nil a # => nil 我们不应该说 if a 因为我们从未设置 a,但是 Ruby 看到 a = 123 并初始化 a,然后得到 if a 在该点 a是零

我认为这是解释器的一个怪癖,真的。Gary Bernhardt 在 wat ( https://www.destroyallsoftware.com/talks/wat ) 中用 a = a取笑它

于 2016-01-27T22:23:32.700 回答
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
于 2013-01-25T16:35:18.843 回答