由于ROR已经限定了MVC的三层架构,这样也就失去了service层,在做项目的时候会吧service层的业务逻辑写在controller层的action中,从逻辑上显得很乱,如果service层的业务逻辑简单的话还可以凑合,如果太复杂的业务逻辑就会增加代码的复杂度,减弱清晰度,增加维护的难度,处于种种原因想把service层抽象出来。
我们的大体思路是在app下面创建一个服务层(例如service)的目录,然后在里面编写相应的service层的代码,把这个目录引入rails的加载路径,并且require此目录下所有的文件。
按照这个思路,创建目录和编写service层代码都不是问题,rails的加载路径是什么,并且要在加载项目文件之前放入rails的加载路径。查看boot.rb其中
从这段代码可以得知rails调用run的时候加载的项目路径,现在有了时机,所以可以在这个方法只有添加service层的路径。rails的加载路径的全局变量时“$:”,所以只要使用
$:.push("project_path/app/service")即可,然后再require此目录下面的所有文件
然后可以启动项目测试了。
最后我又查了version=2.3.5的rails源码的Initializer.rb,其中Configuration类的方法
[color=blue]可以看到方法default_load_paths里面已经添加了app/services的路径,但是下面
File.directory?(dir) 如果存在的话即添加,这样的话就很简单了,我们直接在app下面
添加services,添加对应的service层的代码运行,当然可以了,而且路径加载以后,还做了require处理,郁闷。。。。。。。。[/color]
[color=red] :cry: 绕了一大圈rails已经提供了添加services层的功能。[/color]
[color=red] :D 希望像给你的项目添加service层的朋友不要像我一样走这么多弯路。[/color]
我们的大体思路是在app下面创建一个服务层(例如service)的目录,然后在里面编写相应的service层的代码,把这个目录引入rails的加载路径,并且require此目录下所有的文件。
按照这个思路,创建目录和编写service层代码都不是问题,rails的加载路径是什么,并且要在加载项目文件之前放入rails的加载路径。查看boot.rb其中
def run
load_initializer
Rails::Initializer.run(:set_load_path)
end
从这段代码可以得知rails调用run的时候加载的项目路径,现在有了时机,所以可以在这个方法只有添加service层的路径。rails的加载路径的全局变量时“$:”,所以只要使用
$:.push("project_path/app/service")即可,然后再require此目录下面的所有文件
Dir.foreach("project_path/app/service") do |filename|
require filename if filename.match(/\.rb$/)
end
然后可以启动项目测试了。
最后我又查了version=2.3.5的rails源码的Initializer.rb,其中Configuration类的方法
def initialize
set_root_path!
self.frameworks = default_frameworks
self.load_paths = default_load_paths
self.load_once_paths = default_load_once_paths
self.eager_load_paths = default_eager_load_paths
self.log_path = default_log_path
self.log_level = default_log_level
self.view_path = default_view_path
self.controller_paths = default_controller_paths
self.preload_frameworks = default_preload_frameworks
self.cache_classes = default_cache_classes
self.dependency_loading = default_dependency_loading
self.whiny_nils = default_whiny_nils
self.plugins = default_plugins
self.plugin_paths = default_plugin_paths
self.plugin_locators = default_plugin_locators
self.plugin_loader = default_plugin_loader
self.database_configuration_file = default_database_configuration_file
self.routes_configuration_file = default_routes_configuration_file
self.gems = default_gems
self.i18n = default_i18n
for framework in default_frameworks
self.send("#{framework}=", Rails::OrderedOptions.new)
end
self.active_support = Rails::OrderedOptions.new
end
......
def default_load_paths
paths = []
# Add the old mock paths only if the directories exists
paths.concat(Dir["#{root_path}/test/mocks/#{environment}"]) if File.exists?("#{root_path}/test/mocks/#{environment}")
# Add the app's controller directory
paths.concat(Dir["#{root_path}/app/controllers/"])
# Followed by the standard includes.
paths.concat %w(
app
app/metal
app/models
app/controllers
app/helpers
app/services
lib
vendor
).map { |dir| "#{root_path}/#{dir}" }.select { |dir| File.directory?(dir) }
paths.concat builtin_directories
end
[color=blue]可以看到方法default_load_paths里面已经添加了app/services的路径,但是下面
File.directory?(dir) 如果存在的话即添加,这样的话就很简单了,我们直接在app下面
添加services,添加对应的service层的代码运行,当然可以了,而且路径加载以后,还做了require处理,郁闷。。。。。。。。[/color]
[color=red] :cry: 绕了一大圈rails已经提供了添加services层的功能。[/color]
[color=red] :D 希望像给你的项目添加service层的朋友不要像我一样走这么多弯路。[/color]