Ruby on Rails:在 app 目录中添加子文件夹,其中包含特定于模型的文件
Ruby on Rails: Add subfolder in app directory with files specific to models
我正在编写一个 gem 来处理模型的所有类型的通知(短信、手机和浏览器通知)
在 app 目录下的 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_notifier 文件应该针对用户模型。意味着此方法 send_reminder 应该可供 User
的 instance/object 使用
User.last.send_reminder
所以,问题是
- 如何将 notifiers 文件夹的文件制作为特定模型(user.rb 模型文件在 notifiers 文件夹中有 user_notifier.rb 文件)
- 此文件 user_notifier.rb 方法如何可供用户模型使用
这对于关注点和命名空间是可能的,但这会产生混乱的代码
如何将notifiers文件夹的文件制作成机型专用?
app文件夹下的所有代码都在没有任何配置的情况下加载。
您只需要遵守 class 的命名约定。
在这种情况下 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
感谢 Léonard,他发布了解决方案,但在编写 gem 时,我们需要处理来自 gem 的这些配置。因为当有人使用我们的 gem he/she 时,不必手动在 application_record.rb 中编写任何配置相关的逻辑。
张贴它只是为了确保将来它对其他人有帮助。
我为解决此问题所做的工作(将 gem 附加到我们要配置的模型中添加 act_as_notifier 的模型)
- 在 model_config.rb class 的通知 gem
- 有@model_class & 找到相应的通知程序class
- 在notifierclass中添加attr_accessor并用model对象初始化
- 同时定义自定义 getter 和设置器通知属性
#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
我正在编写一个 gem 来处理模型的所有类型的通知(短信、手机和浏览器通知)
在 app 目录下的 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_notifier 文件应该针对用户模型。意味着此方法 send_reminder 应该可供 User
的 instance/object 使用User.last.send_reminder
所以,问题是
- 如何将 notifiers 文件夹的文件制作为特定模型(user.rb 模型文件在 notifiers 文件夹中有 user_notifier.rb 文件)
- 此文件 user_notifier.rb 方法如何可供用户模型使用
这对于关注点和命名空间是可能的,但这会产生混乱的代码
如何将notifiers文件夹的文件制作成机型专用?
app文件夹下的所有代码都在没有任何配置的情况下加载。
您只需要遵守 class 的命名约定。
在这种情况下 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
感谢 Léonard,他发布了解决方案,但在编写 gem 时,我们需要处理来自 gem 的这些配置。因为当有人使用我们的 gem he/she 时,不必手动在 application_record.rb 中编写任何配置相关的逻辑。
张贴它只是为了确保将来它对其他人有帮助。
我为解决此问题所做的工作(将 gem 附加到我们要配置的模型中添加 act_as_notifier 的模型)
- 在 model_config.rb class 的通知 gem
- 有@model_class & 找到相应的通知程序class
- 在notifierclass中添加attr_accessor并用model对象初始化
- 同时定义自定义 getter 和设置器通知属性
#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