RubyonRails:在应用程序目录中添加子文件夹,其中包含特定于模型的文件

neskvpey  于 2021-09-29  发布在  Java
关注(0)|答案(2)|浏览(282)

我正在写一个gem,它将处理模型的各种通知(短信、手机和浏览器通知)
在应用目录下的rails项目中创建了新文件夹“notifiers”,其中包含以下文件

app/notifiers/user_notifier.rb

class UserNotifier < ApplicationNotifier
  def send_reminder
   {
     type: 'sms',
     content: 'hi everyone',
     recipients: [12134343,2342322,3434343]
   }
  end
end

此用户通知程序文件应针对用户模型。表示此方法发送提醒应可用于用户的示例/对象 User.last.send_reminder 所以,问题是
如何使notifiers文件夹的文件特定于模型(user.rb模型文件在notifiers文件夹中有user_notifier.rb文件)
该文件user_notifier.rb方法对用户模型的可用性
这在关注点和名称空间中是可能的,但这会创建混乱的代码

c90pui9n

c90pui9n1#

如何使notifiers文件夹的文件特定于模型?
app文件夹下的所有代码都是在没有任何配置的情况下加载的。您只需要遵守类的命名约定。在这种情况下 UserNotifier 这个名字对吗 app/notifiers/user_notifier.rb .
该文件user_notifier.rb方法如何可用于用户模型?


# app/models/application_record.rb

class ApplicationRecord < ActiveRecord::Base
  # your code

  def send_notification(notification_name, recipients)
    notifier = "#{self.class.name}Notifier".constantize.new()
    send(notification_name, recipients)
  end
end

# app/models/user.rb

class User < ApplicationRecord
  # your code

  # a method where you want to send a notification
  def foo
    send_notification(:reminder, [id])
  end
end

# app/notifiers/user_notifier.rb

class UserNotifier < ApplicationNotifier
  def reminder(recipients)
   {
     type: 'sms',
     content: 'hi everyone',
     recipients: recipients
   }
  end
end
vxf3dgd4

vxf3dgd42#

多亏了léonard,他发布了解决方案,但在编写gem时,我们需要从gem处理这些配置。因为当有人使用我们的gem时,他/她不必手动在application_record.rb中编写任何与配置相关的逻辑。
发布它只是为了确保将来它可能对其他人有所帮助。
我是如何解决这个问题的(为了将gem附加到一个模型中,我们在希望配置它的模型中添加了act_as_notifier)
在通知程序gem的model_config.rb类中
拥有@model_类并查找相应的通知程序类
在通知程序类中添加attr_访问器,并用model对象初始化它
还定义自定义getter和setters通知程序属性


# rails_notifier/model_config.rb

    def initialize(model_class)
      @model_class = model_class

      # get model corresponding notifier class
      # for User model class, there would UserNotifier class
      # under notifiers folder of app directory
      # getting notitifer class name
      notifier_class = "#{@model_class.name}Notifier"

      # Notifier class attribute set later set with model object
      attribute_name = @model_class.name.underscore

      # register a `notifier` method in model class
      # 'method_name' is a method of notifier class
      # and options hash contain sender
      @model_class.class_eval do
        define_method(:notifier) do |method_name, options|
          # create notifier class object
          notifier_ = notifier_class.constantize.new

          # define setter for notifier attribute
          notifier_.send(:define_singleton_method, "#{attribute_name}=".to_sym) do |value|
            instance_variable_set("@" + attribute_name.to_s, value)
          end

          # define getter for notifier attribute
          notifier_.send(:define_singleton_method, attribute_name.to_sym) do
            instance_variable_get("@" + attribute_name.to_s)
          end

          # self point to the object of model
          # e.g User.last.notifier(:send_reminder), slef = User.last
          # set notifier attribute with model object
          notifier_.send("#{attribute_name}=".to_sym, self)
          notifier_hash = notifier_.send(method_name)
          RailsNotifier.notify(notifier_hash) if notifier_hash.present?
        end
      end
    end

相关问题