【问题标题】:Modify ruby hash in place( rails strong params)就地修改 ruby​​ 哈希(rails strong params)
【发布时间】:2013-08-22 00:03:31
【问题描述】:

这可能更像是一个 ruby​​ 问题而不是 rails 问题,但我很确定我能够在 vanilla ruby​​ 应用程序中做到这一点。

我定义了强大的参数。

def trip_params
  params.require(:trip).permit(:name, :date)
end

现在我在控制器方法中获取这些参数。我想这样做。

def save
  trip_params[:name] = 'Modifying name in place'
  #trip_params[:name] still equals original value passed
end

这永远行不通。 名称永不改变。 BTW:trip_params 的类型是 ActionController::Parameters

如果我做一个标准的 ruby​​ 脚本,它就可以工作。

test = {}    
test[:name] = "blah"    
test[:name] = "ok"    
puts test #{:name=>"ok"}

【问题讨论】:

  • Trip 是活动记录吗?您可能需要将其显式保存在数据库中:@trip.save
  • 我参加了 Trip.new 部分。不要让这分心。我正在尝试修改 ActionController::Parameters 哈希。

标签: ruby ruby-on-rails-4


【解决方案1】:

permit 返回一个包含这些键的新哈希,因此您不会修改真正的 params 变量。您也没有保存对哈希 trip_params 返回的引用,因此您在 save 中的每次调用都会获得新鲜的。

试试这个:

def save
  tp = trip_params
  tp[:name] = 'Modifying name in place'
  # ... use tp later, it'll be in there
end

或者,如果您真的希望它像以前一样使用,请像这样修改trip_params

def trip_params
  @trip_params ||= params.require(:trip).permit(:name, :date)
end

现在该哈希被延迟缓存,并且在随后的trip_params 调用中返回相同的哈希。

【讨论】:

  • 默认值和格式应该在模型上完成。
【解决方案2】:

如果您真的想要更改控制器中的参数,您可以这样做:

def save
  params[:trip][:name] = 'Modifying name in place'
  # Now trip_params[:name] is 'Modifying name in place'
end

【讨论】:

  • 我认为这是最好和最简单的答案。只需先修改实际参数,然后调用您的强参数方法。你甚至可以用 before_action :modify_params 来做,只有 [:create, :update] 然后创建一个私有方法来防止它进入你的创建和更新方法。
【解决方案3】:

你也可以

def save
  data = trip_params.merge(name: 'new name')
  # use data later
end

如果一个新的散列被合并到一个旧的散列中,并且如果有重复的键,那么新散列的键将覆盖旧散列的匹配键。

【讨论】:

    【解决方案4】:

    这是因为没有trip_params[]=(arg, val).这样的方法

    我的意思是,当您调用trip_params 时,您将返回params.require(:trip).permit(:name, :date) 的值,因此每次您调用trip_params 时,您都会再次获取参数。

    所以,如果我是你,我会定义 trip_params 方法如下:

    def trip_params
      @trip_params ||= params.require(:trip).permit(:name, :date)
    end
    

    并且还会定义一个方法来改变trip_params

    def trip_params[]= (key,val)
      trip_params # Ensure that trip_params is called once or you will get an error
      @trip_params[key] = val
    end
    

    所以现在当您调用trip_params 时,您实际上会返回@trip_params,如果尚未设置@trip_params,它将设置为params.require(:trip).permit(:name, :date)

    然后当您调用trip_params[:name] = "Some name" 时,它将首先确保@trip_params 通过调用trip_params and then it will set the :name param to"Some name"` 被初始化`

    希望对你有所帮助

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-29
      • 1970-01-01
      • 2014-09-26
      • 2012-03-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多