插件教程 » 历史 » 修订版66
上一页 | 修订版66/119 (diff) | 下一页
Etienne Massip, 2012-05-25 11:13
插件教程¶
注意:要跟随本教程,您需要运行Redmine devel r1786 或更高版本。
- 目录
- 插件教程
创建新的插件¶
您可能需要设置RAILS_ENV变量,以便使用以下命令
$ export RAILS_ENV="production"
在Windows上
set RAILS_ENV=production
可以使用Redmine插件生成器创建新的插件。
此生成器的语法是
ruby script/generate redmine_plugin <plugin_name>
因此,打开命令提示符,并"cd"到您的redmine目录,然后执行以下命令
% ruby script/generate redmine_plugin Polls
插件结构在vendor/plugins/redmine_polls
中创建
create vendor/plugins/redmine_polls/app/controllers create vendor/plugins/redmine_polls/app/helpers create vendor/plugins/redmine_polls/app/models create vendor/plugins/redmine_polls/app/views create vendor/plugins/redmine_polls/db/migrate create vendor/plugins/redmine_polls/lib/tasks create vendor/plugins/redmine_polls/assets/images create vendor/plugins/redmine_polls/assets/javascripts create vendor/plugins/redmine_polls/assets/stylesheets create vendor/plugins/redmine_polls/lang create vendor/plugins/redmine_polls/config/locales create vendor/plugins/redmine_polls/test create vendor/plugins/redmine_polls/README.rdoc create vendor/plugins/redmine_polls/init.rb create vendor/plugins/redmine_polls/config/locales/en.yml create vendor/plugins/redmine_polls/test/test_helper.rb
编辑vendor/plugins/redmine_polls/init.rb
以调整插件信息(名称、作者、描述和版本)
require 'redmine'
Redmine::Plugin.register :redmine_polls do
name 'Polls plugin'
author 'John Smith'
description 'A plugin for managing polls'
version '0.0.1'
end
然后重新启动应用程序,并将您的浏览器指向https://127.0.0.1:3000/admin/plugins。
登录后,您应该在插件列表中看到您的新插件
生成模型¶
目前插件不存储任何内容。让我们为我们的插件创建一个简单的Poll模型。语法是
ruby script/generate redmine_plugin_model <plugin_name> <model_name> [<fields>]
因此,转到命令提示符并运行
ruby script/generate redmine_plugin_model polls poll question:string yes:integer no:integer
这创建了一个Poll模型和相应的迁移文件。
请注意,您可能需要重命名您的迁移。实际Redmine插件引擎(Engines)不支持带时间戳的迁移。如果您的迁移名称带有时间戳,请使用"001"、"002"等来重命名它。
mv vendor/plugins/redmine_polls/db/migrate/20091009211553_create_polls.rb vendor/plugins/redmine_polls/db/migrate/001_create_polls.rb
如果您已经在插件_schema_info中创建了带有时间戳版本号的数据库表记录,您必须将其更改为反映您的新版本号,否则迁移会挂起。
使用以下命令迁移数据库
rake db:migrate_plugins
注意,每个插件都有自己的迁移集。
让我们在控制台添加一些投票,这样我们就有东西可以工作了。控制台是您可以交互式工作并检查Redmine环境的地方,非常适合探索。但现在我们只需要创建两个投票对象
script/console >> Poll.create(:question => "Can you see this poll") >> Poll.create(:question => "And can you see this other poll") >> exit
编辑您的插件目录中的 vendor/plugins/redmine_polls/app/models/poll.rb
,以添加一个 #vote 方法,该方法将由我们的控制器调用
class Poll < ActiveRecord::Base
def vote(answer)
increment(answer == 'yes' ? :yes : :no)
end
end
生成控制器¶
警告:从 1.4.0 版本开始,Redmine 将不再提供默认的通配符路由(':controller/:action/:id'
)。插件必须在它们正确的 config/routes.rb
文件中声明所需的路由。
目前,该插件没有任何功能。所以让我们为我们的插件创建一个控制器。
我们可以使用插件控制器生成器来做到这一点。语法是
ruby script/generate redmine_plugin_controller <plugin_name> <controller_name> [<actions>]
因此,返回到命令提示符并运行
% ruby script/generate redmine_plugin_controller Polls polls index vote exists app/controllers/ exists app/helpers/ create app/views/polls create test/functional/ create app/controllers/polls_controller.rb create test/functional/polls_controller_test.rb create app/helpers/polls_helper.rb create app/views/polls/index.html.erb create app/views/polls/vote.html.erb
创建了一个名为 PollsController
的控制器,包含 2 个操作(#index
和 #vote
)。
编辑 redmine_polls
目录中的 vendor/plugins/redmine_polls/app/controllers/polls_controller.rb
,以实现这两个操作。
class PollsController < ApplicationController
unloadable
def index
@polls = Poll.find(:all)
end
def vote
poll = Poll.find(params[:id])
poll.vote(params[:answer])
if poll.save
flash[:notice] = 'Vote saved.'
redirect_to :action => 'index'
end
end
end
然后编辑 vendor/plugins/redmine_polls/app/views/polls/index.html.erb
,它将显示现有的投票。
<h2>Polls</h2> <% @polls.each do |poll| %> <p> <%= poll[:question] %>? <%= link_to 'Yes', { :action => 'vote', :id => poll[:id], :answer => 'yes' }, :method => :post %> (<%= poll[:yes] %>) / <%= link_to 'No', { :action => 'vote', :id => poll[:id], :answer => 'no' }, :method => :post %> (<%= poll[:no] %>) </p> <% end %>
您可以删除 vendor/plugins/redmine_polls/app/views/polls/vote.html.erb
,因为相应的操作没有执行渲染。
现在,重新启动应用程序并将浏览器指向 https://127.0.0.1:3000/polls。
您应该看到两个投票,并且您应该能够为它们投票。
请注意,如果您不在生产模式下运行应用程序,则投票结果将在每个请求后重置,因为我们的“模型”在这个例子中存储在类变量中。
翻译¶
翻译文件 *.yml 的位置取决于正在运行的Redmine版本
版本 | 路径 |
---|---|
< 0.9 | .../redmine_polls/lang |
>= 0.9 | .../redmine_polls/config/locales |
如果您希望您的插件在两个版本上都能工作,您需要在这两个位置都有相同的翻译文件。
扩展菜单¶
我们的控制器运行良好,但用户必须知道URL才能查看投票。使用Redmine插件API,您可以扩展标准菜单。
所以让我们向应用程序菜单添加一个新项目。
扩展应用程序菜单¶
编辑插件目录根目录中的 vendor/plugins/redmine_polls/init.rb
,在插件注册块末尾添加以下行
Redmine::Plugin.register :redmine_polls do
[...]
menu :application_menu, :polls, { :controller => 'polls', :action => 'index' }, :caption => 'Polls'
end
语法是
menu(menu_name, item_name, url, options={})
您可以扩展以下五个菜单
:top_menu
- 顶部左边的菜单:account_menu
- 顶部右边的菜单,包含登录/注销链接:application_menu
- 用户不在项目内时显示的主要菜单:project_menu
- 用户在项目内时显示的主要菜单:admin_menu
- 在管理页面上显示的菜单(只能在设置之后、插件之前插入)
可用的选项是
:param
- 用于项目 id 的参数键(默认为:id
):if
- 在渲染项目之前被调用的Proc,只有当它返回true时才显示项目:caption
- 菜单标题可以是- 一个本地化的字符串Symbol
- 一个String
- 一个可以接受项目作为参数的Proc
:before
,:after
- 指定菜单项应插入的位置(例如,:after => :activity
):first
,:last
- 如果设置为true,项目将保持在菜单的开始/结束位置(例如,:last => true
):html
- 传递给link_to
渲染菜单项时的HTML选项的hash
在我们的例子中,我们已向应用程序菜单添加了一个空的项目。
重新启动应用程序并转到 https://127.0.0.1:3000
现在您可以通过点击欢迎屏幕上的“投票”标签来访问投票。
扩展项目菜单¶
现在,让我们假设投票是在项目级别定义的(即使在我们的示例投票模型中不是这样)。因此,我们希望将“投票”标签添加到项目菜单中。
打开 init.rb
并用这两行替换刚刚添加的行
Redmine::Plugin.register :redmine_polls do
[...]
permission :polls, { :polls => [:index, :vote] }, :public => true
menu :project_menu, :polls, { :controller => 'polls', :action => 'index' }, :caption => 'Polls', :after => :activity, :param => :project_id
end
第二行将我们的“投票”标签添加到项目菜单中,位于活动标签之后。
第一行是必需的,它声明我们的两个来自 PollsController
的操作是公开的。我们稍后会更详细地解释这一点。
再次重启应用程序,并转到您的一个项目
如果您点击“投票”标签,您应该会注意到项目菜单不再显示。
为了使项目菜单可见,您必须初始化控制器实例变量 @project
。
编辑您的 PollsController 以实现这一点
def index
@project = Project.find(params[:project_id])
@polls = Poll.find(:all) # @project.polls
end
由于在上述菜单项声明中的 :param => :project_id
选项,项目 ID 可在 :project_id
参数中找到。
现在,您应该会在查看投票时看到项目菜单。
添加新权限¶
到目前为止,任何人都可以为投票投票。让我们通过更改权限声明使其更具可配置性。
我们将声明两个基于项目的权限,一个用于查看投票,另一个用于投票。这些权限不再公开(移除了 :public => true
选项)。
编辑 vendor/plugins/redmine_polls/init.rb
并用这两行替换之前的权限声明
permission :view_polls, :polls => :index
permission :vote_polls, :polls => :vote
重启应用程序,并转到 https://127.0.0.1:3000/roles/report
现在,您可以将这些权限分配给现有的角色。
当然,需要在 PollsController 中添加一些代码,以便根据当前用户的权限实际保护操作。
为此,我们只需添加 :authorize
过滤器,并确保在调用此过滤器之前正确设置了 Herve Harster 实例变量。
以下是 #index
操作的示例
class PollsController < ApplicationController
unloadable
before_filter :find_project, :authorize, :only => :index
[...]
def index
@polls = Poll.find(:all) # @project.polls
end
[...]
private
def find_project
# @project variable must be set before calling the authorize filter
@project = Project.find(params[:project_id])
end
end
在 #vote
操作之前使用类似的方式检索当前项目。
在此之后,查看和投票将仅对管理员用户或在项目中具有适当角色的用户可用。
如果您想以多语言方式显示您的权限符号,则需要在一个语言文件中添加必要的文本标签。
只需在您的 Redmine 版本的正确翻译目录中创建一个 *.yml 文件,并填充类似于下面的标签
permission_view_polls: View Polls
permission_vote_polls: Vote Polls
在此示例中,创建的文件被称为 en.yml,但所有其他支持的语言文件也是可能的。
如上例所示,标签由权限符号 :view_polls
和 :vote_polls
组成,并在前面添加了 permission_
。
重启您的应用程序并指向权限部分。
创建项目模块¶
目前,投票功能已添加到您的所有项目中。但您可能只想在某些项目中启用投票。
因此,让我们创建一个“投票”项目模块。这是通过将权限声明包裹在 #project_module
调用中来完成的。
编辑 init.rb
并更改权限声明
project_module :polls do
permission :view_polls, :polls => :index
permission :vote_polls, :polls => :vote
end
重启应用程序,并转到您的一个项目设置。
点击“模块”标签。您应该会在模块列表的末尾看到“投票”模块(默认情况下禁用)
您现在可以按项目级别启用/禁用投票。
改进插件视图¶
添加样式表¶
让我们首先为我们的插件视图添加一个样式表。
在目录 vendor/plugins/redmine_polls/assets/stylesheets
中创建一个名为 voting.css
的文件
a.vote { font-size: 120%; } a.vote.yes { color: green; } a.vote.no { color: red; }
当启动应用程序时,Rails Engines 会自动将插件资源复制到 public/plugin_assets/redmine_polls/
,以便通过您的 Web 服务器提供。因此,对插件样式表或 JavaScript 的任何更改都需要重启应用程序。
然后,在 vendor/plugins/redmine_polls/app/views/polls/index.html.erb
的末尾追加以下行,以便 Redmine 将您的样式表包含在页面标题中
<% content_for :header_tags do %> <%= stylesheet_link_tag 'voting', :plugin => 'redmine_polls' %> <% end %>
请注意,在调用 stylesheet_link_tag
辅助函数时需要 :plugin => 'redmine_polls'
选项。
可以使用与 javascript_include_tag
辅助函数相同的方式在插件视图中包含 JavaScript。
设置页面标题¶
您可以使用 html_title
辅助函数在视图中设置 HTML 标题。
示例
<% html_title "Polls" %>
测试您的插件¶
test/test_helper.rb:¶
以下是我的测试辅助文件的正文
require File.expand_path(File.dirname(__FILE__) + '/../../../../test/test_helper')
示例测试:¶
requirements_controller_test.rb 的内容
require File.dirname(__FILE__) + '/../test_helper'
require 'requirements_controller'
class RequirementsControllerTest < ActionController::TestCase
fixtures :projects, :versions, :users, :roles, :members, :member_roles, :issues, :journals, :journal_details,
:trackers, :projects_trackers, :issue_statuses, :enabled_modules, :enumerations, :boards, :messages,
:attachments, :custom_fields, :custom_values, :time_entries
def setup
@skill = Skill.new(:skill_name => 'Java')
@project = Project.find(1)
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
User.current = nil
end
def test_routing
assert_routing(
{:method => :get, :path => '/requirements'},
:controller => 'requirements', :action => 'index'
)
end
end
初始化测试数据库:¶
我发现通过以下 rake 调用直接初始化测试数据库是最容易的
rake db:drop db:create db:migrate db:migrate_plugins redmine:load_default_data RAILS_ENV=test
运行测试:¶
要执行 requirements_controller_test.rb,我使用了以下命令
rake test:engines:all PLUGIN=redmine_requirements
使用权限进行测试¶
如果您的插件需要项目成员资格,请在功能测试的开始处添加以下内容
def test_index @request.session[:user_id] = 2 ... end
如果您的插件需要特定的权限,可以将该权限添加到用户角色中(在 fixtures 中查找适用于用户的角色)
def test_index Role.find(1).add_permission! :my_permission ... end
您可以通过以下方式启用/禁用特定模块
def test_index Project.find(1).enabled_module_names = [:mymodule] ... end