2016-03-15 3 views
1

У меня есть действие контроллера несколько похожее на это:В Rails, почему мой контроллер PARAMS модифицируется классом

def reports 
    puts params 
    @stats = Client.stats(params) 
    puts params 
end 

Исходной PARAMS может выглядеть следующим образом:

{ end: '2012-01-01 21:00:19' } 

И в моя модель клиента, у меня есть следующее:

def self.stats(opts) 
    opts[:start] = (Time.now - 30.days).to_i 
    ...do some calculations.. 
    return stats 
end 

Если я проверяю объект params, который был отправлен до и после забавы ction работает, я вижу, что он был изменен методом self.stats.

В приведенном выше примере я не отправляю «начальный» исходный параметр, метод добавляет его для вычислений - как и ожидалось.

Я не ожидал, что функция изменит исходный хэш!

Может кто-нибудь объяснить, почему это происходит?

--EDIT--

Я забыл сказать, что я пытался создать копию Params и использования, что вместо этого, тот же вопрос.

def reports 
    a = params 
    @stats = Client.stats(a) 
    puts params 
end 

Параметры все еще обновляются!

+0

Связанный: http://stackoverflow.com/questions/22827566/ruby-parameters-by-reference-or-by-value/22827949#22827949 – nathanvda

+0

Просто добавив, что, вероятно, хорошей практикой никогда не изменять параметры для метода. Это будет путать вызывающего абонента этого метода. – froderik

+0

Почему * не будет * он изменяет то, что вы проходите? Создание новой ссылки на тот же объект не создает новый объект, он создает новую ссылку. Возможно, вы хотите клонировать или глубоко клонировать объект? –

ответ

4

Это потому, что ваш вызов функции получает ссылку на параметры, а не на копию. Если вы делаете что-то вроде opts[:start] = (Time.now - 30.days).to_i, вы редактируете объект params.

a = params: теперь обе переменные указывают на одно и то же место в памяти. Вы скопировали указатель.

Google для ruby object copy или ruby deep copy или поиск в stackoverflow для этого. С первой попытки вы можете попробовать params.clone.

+0

Я попытался сделать копию, см. Править, и это тоже обновление. Как я могу сделать копию объекта тогда? –

+3

Нет, вы этого не сделали. 'params' и' a' указывают на то же место в памяти. Вы скопировали указатель. Google для «ruby object copy» или «ruby deep copy» или поиска в stackoverflow для него. С первой попытки вы можете попробовать 'params.clone'. – guitarman

+0

Я не знал об этом! Отлично, можешь добавить к своему ответу, и я соглашусь. –

1

Всякий раз, когда вы обновляете любое значение Params, возьмите копию Params как этот

а = params.clone

Это создаст новый элемент в памяти

, если вам это нравится, он не создаст новый элемент в памяти, он укажет ту же память

а = PARAMS

Попробуйте

Смежные вопросы