#ruby #ruby-on-rails-3
#ruby #ruby-on-rails-3
Вопрос:
У меня есть такой метод
def method1
{
headers: { 'Content-Type' => 'application/json' }
}
end
и это другой метод для слияния другого ключа и значения в этот хэш method1, поэтому
def merge_hash
method1.merge!(body: { params: 123 }
end
итак, когда я снова вызываю method1, я ожидаю, что он вернет обведенное тело, и мои вопросы в том, почему этого не происходит или как я могу это сделать?
Комментарии:
1. Было бы крайне запутанным / плохой практикой изменять ответ метода таким образом. Я не могу дать конкретный совет, не видя большего контекста, чем эти два метода по отдельности, но в целом вам следует изменять только переменные .
2. @MatheusLima: По сути, вы хотите иметь метод без параметров, который при каждом вызове возвращает что-то другое, основываясь на том, что с ним происходило раньше. Следовательно, вам нужен метод, который содержит некоторое состояние . Это не запрещено, но я надеюсь, вы знаете, что собираетесь здесь делать. Тривиальное решение для достижения эффекта: поскольку ваш метод находится в некотором классе, вы могли бы использовать переменную экземпляра для записи информации, необходимой для вашей операции.
3. Обратите внимание на это
method1.object_id #=> 70130617670800; method1.object_id #=> 70130617701620; method1.object_id #=> 70130621059620
. Вы видите проблему?
Ответ №1:
Каждый раз, когда вы вызываете method1
, он возвращает новый объект:
> method1.object_id
=> 47220476550040
> method1.object_id
=> 47220476543700
Чтобы достичь желаемого, вы можете запомнить его после первого вызова:
def method1
@method1 ||= {
headers: { 'Content-Type' => 'application/json' }
}
end
> method1.object_id
=> 47220477154400
> method1.object_id
=> 47220477154400
Я предлагаю не изменять хэш таким образом, потому что это может привести к ошибкам.
Комментарии:
1. Что вы предлагаете делать в этом случае? поскольку мне нужно «объединить» новый ключ и значение с существующим хэшем, когда это необходимо, тело с параметрами в этом случае необязательно
2. Это зависит от вашего приложения. Я бы создал переменную для хранения всех объединенных хэшей,
my_hash = method1.merge(body: { params: 123 })
.3. Как @Tom Lord упомянул в своем комментарии к вопросу. Трудно давать вам советы без контекста.
Ответ №2:
Конечно, method1
возвращаемое значение не меняется, потому что вы не изменили сам метод.
Вы можете использовать старую и злую технику, называемую цепочкой псевдонимов методов.
# Define a new method `method1_without_body`
# whose implementation is exactly the same
# as `method1` at this moment.
alias method1_without_body method1
# Define a new method that calls `method1_without_body`.
# Make sure that it does NOT call `method1`,
# or you'll get a stack overflow.
def method1_with_body
method1_without_body.merge!(body: { params: 123 })
end
# Define a new method `method1`
# whose implementation is exactly the same
# as `method1_with_body`.
# This method shadows the previous implementation of `method1`.
alias method1 method1_with_body
или, если вы используете Rails < 5, тогда просто
def method1_with_body
method1_without_body.merge!(body: { params: 123 })
end
alias_method_chain :method1, :body
затем, когда вы вызываете method1
, он возвращает хэш как с заголовками, так и с телом.
Кстати, этот метод устарел с Rails 5 и был полностью удален позже (я забыл, в какой младшей версии).
Ответ №3:
Возможно, это близко к тому, на что вы смотрите:
class MyClass
attr_reader :method1
def initialize
@method1 = { headers: { 'Content-Type' => 'application/json' } }
end
def merge_hash
@method1.merge!(body: { params: 123 }
end
end
Следовательно, если у вас есть
o = MyClass.new
первый o.method1
вернет начальный хэш, но после
o.merge_hash
o.method1
вернет измененный хэш.