Доступ к rails flash[:notice] в модели

Я пытаюсь назначить сообщение flash[:notice] в наблюдателе модели.

Этот вопрос уже задавали: Ruby on Rails: Observers и flash[:notice] сообщения?

Однако я получаю следующее сообщение об ошибке, когда пытаюсь получить к нему доступ в своей модели:

undefined local variable or method `flash' for #<ModelObserver:0x2c1742c>

Вот мой код:

class ModelObserver < ActiveRecord::Observer
  observe A, B, C

  def after_save(model)
    puts "Model saved"
    flash[:notice] = "Model saved"
  end
end

Я знаю, что этот метод вызывается, потому что на терминал выводится сообщение «Модель сохранена».

Можно ли получить доступ к вспышке внутри обозревателя, и если да, то как?


person titaniumdecoy    schedule 23.04.2010    source источник
comment
Технически правильное решение, которое нарушает MVC: для вызова фрагмента с истекшим сроком действия из модели наблюдателя рельсов "> stackoverflow.com/questions/393395/   -  person titaniumdecoy    schedule 16.06.2012


Ответы (2)


Мне нужно было установить flash[:notice] в модели, чтобы переопределить общую @model, которая была успешно обновлена.

Это то, что я сделал

  1. Создал виртуальный атрибут в соответствующей модели с именем validation_message
  2. Затем я устанавливаю виртуальный атрибут в соответствующей модели, когда это необходимо.
  3. Использовался after_action, когда этот виртуальный атрибут не был пустым, чтобы переопределить флэш-память по умолчанию.

Ниже вы можете увидеть мой контроллер и модель того, как я этого добился:

class Reservation < ActiveRecord::Base

  belongs_to :retailer
  belongs_to :sharedorder
  accepts_nested_attributes_for :sharedorder
  accepts_nested_attributes_for :retailer

  attr_accessor :validation_code, :validation_messages

  validate :first_reservation, :if => :new_record_and_unvalidated

  def new_record_and_unvalidated
    if !self.new_record? && !self.retailer.validated?
      true
    else
      false
    end
  end

  def first_reservation
    if self.validation_code != "test" || self.validation_code.blank?
      errors.add_to_base("Validation code was incorrect") 
    else
      self.retailer.update_attribute(:validated, true)
      self.validation_message = "Your validation is successful and you will not need to do that again"
    end
  end
end

class ReservationsController < ApplicationController

  before_filter :authenticate_retailer!
  after_filter :validation_messages, :except => :index

  def validation_messages
    return unless @reservation.validation_message.present?

    flash[:notice] = @reservation.validation_message
  end
end

Одним из возможных рефакторингов может быть перемещение фактического сообщения в соответствующий файл (например, локаль) и передача в validation_message только правильного ключа.

Если вам нужно более одного уведомления, достаточно просто превратить validation_message в массив или хэш и вместо этого назвать его validation_messages.

person thenengah    schedule 29.07.2010
comment
Вы упрощаете условие if до @reservation.flash_notice.present? вместо not blank? - person Besi; 15.03.2016

Нет, вы устанавливаете его в контроллере, где происходит сохранение. flash — это метод, определенный на ActionController::Base.

person Ryan Bigg    schedule 24.04.2010
comment
Хотя Райан прав. Вы должны настроить вспышку в контроллере... это функция уровня представления представления. Ответ выше - много опасной тяжелой работы, чтобы заставить это работать. - person Toby Hede; 24.04.2010
comment
Как я уже говорил в своем посте, установка flash в контроллере нецелесообразна (если вообще возможна) в моем приложении. Мне нужно добавить сообщение во флэш-память каждый раз, когда модель обновляется; Я не знаю другого способа сделать это — по крайней мере, не швыряя в стену тарелку спагетти-кода. - person titaniumdecoy; 24.04.2010
comment
Сегодня я тоже немного поборолся с этим, но, решив свою собственную дилемму, я вижу, что вы ответили на свой вопрос в комментарии прямо над моим. Мне нужно добавить сообщение во вспышку каждый раз, когда модель обновляется. Я знаю, вы сказали, что это непрактично, но я поместил свою вспышку в метод обновления моего контроллера. (Ловил исключение, а затем выдавал ошибку.) - person Tass; 02.06.2012
comment
Иногда мир не так прост, как хотелось бы. Мне нужно установить флэш-память из исправленного расширения обезьяны на Sunspot/RSolr, которая запускается из обратного вызова модели в другом потоке во время цикла запроса. Пожалуйста, не отвечайте на вопросы с очевидным. Вы, конечно, можете упомянуть, что это обычно делается одним способом, но если это прямо не отвечает на вопрос, это вообще бесполезно. - person Chloe; 28.03.2014
comment
$0,02 – Часто, когда вы думаете, что вам должно делать что-то грязным (или немасштабируемым, или рискованным, или слишком сложным), скорее всего, у вас где-то неправильная абстракция. Архитектура, содержащая этот сценарий, нуждается в рефакторинге. Решение нарушить соглашения, потому что вы чувствуете, что должны, может привести к тому, что вы загоните себя в угол спустя месяцы или годы (и я также не сторонник того, чтобы подвергать хвостовому риску будущих разработчиков, которыми вы не являетесь). Короче говоря, то, что сказал Райан Бигг. - person Todd; 31.01.2019
comment
Я не вижу проблем с определением модели attr_accessor, например validation_messages, а затем проверкой ее в обратном вызове Controller after_action для установки flash (внутри контроллера) в соответствии со значением validation_messages. - person Darme; 28.08.2020