redmine_extensions 0.1.13 → 0.1.14
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +5 -1
- data/app/assets/javascripts/redmine_extensions/redmine_extensions.js +1 -1
- data/app/helpers/redmine_extensions/application_helper.rb +2 -2
- data/app/presenters/redmine_extensions/issue_query_presenter.rb +0 -0
- data/app/views/common/_closing_modal.html.erb +2 -2
- data/app/views/common/close_modal.js.erb +4 -4
- data/app/views/easy_queries/_easy_query_list.html.erb +1 -0
- data/app/views/easy_queries/{_easy_query_tile.html.erb → _easy_query_tiles.html.erb} +0 -0
- data/lib/generators/redmine_extensions/entity/templates/_sidebar.html.erb.erb +8 -8
- data/lib/generators/redmine_extensions/entity/templates/context_menu.html.erb.erb +7 -7
- data/lib/generators/redmine_extensions/entity/templates/custom_field.rb.erb +7 -7
- data/lib/generators/redmine_extensions/entity/templates/edit.html.erb.erb +18 -18
- data/lib/generators/redmine_extensions/entity/templates/edit.js.erb.erb +16 -16
- data/lib/generators/redmine_extensions/entity/templates/index.api.rsb.erb +5 -5
- data/lib/generators/redmine_extensions/entity/templates/index.html.erb.erb +4 -4
- data/lib/generators/redmine_extensions/entity/templates/index.js.erb.erb +10 -10
- data/lib/generators/redmine_extensions/entity/templates/mail_added.html.erb.erb +1 -1
- data/lib/generators/redmine_extensions/entity/templates/mail_added.text.erb.erb +2 -2
- data/lib/generators/redmine_extensions/entity/templates/mail_updated.text.erb.erb +2 -2
- data/lib/generators/redmine_extensions/entity/templates/migration.rb.erb +9 -9
- data/lib/generators/redmine_extensions/entity/templates/new.html.erb.erb +18 -18
- data/lib/generators/redmine_extensions/entity/templates/new.js.erb.erb +16 -16
- data/lib/generators/redmine_extensions/entity/templates/routes.rb.erb +12 -12
- data/lib/generators/redmine_extensions/entity/templates/show.html.erb.erb +37 -37
- data/lib/generators/redmine_extensions/entity/templates/show.js.erb.erb +10 -10
- data/lib/redmine_extensions/easy_query_helpers/outputs.rb +1 -1
- data/lib/redmine_extensions/engine.rb +3 -1
- data/lib/redmine_extensions/query_output.rb +25 -9
- data/lib/redmine_extensions/query_outputs/{tile_output.rb → tiles_output.rb} +2 -2
- data/lib/redmine_extensions/redmine_patches/patches.rb +2 -1
- data/lib/redmine_extensions/version.rb +1 -1
- data/spec/features/autocomplete_spec.rb +13 -0
- data/spec/rails_helper.rb +40 -0
- data/spec/support/plugin_generator.rb +51 -0
- metadata +30 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 51dcad00b5efb1ea9c707d9e06d040ebe017106c
|
4
|
+
data.tar.gz: 2dc9c7cff300292d0ca6ccda7628ea0806dbd4c8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 774834037c521abc40ea86661b503069105d1a0eb71e0bfafd00af055c8c35ef90cb81aa294250f22cab452a60f5ab26d957d683244100d3d557bd1ce8687985
|
7
|
+
data.tar.gz: 3309f376782ac951b5f2bb16bba2a653d06bef46a4f1c3defadac89f7bbec3f624feb0fd27a7ca7c0ba2d84d468240dbcd63b1ba9c5b4a65fa589bb4808d1783
|
data/Rakefile
CHANGED
@@ -33,7 +33,11 @@ require 'rspec/core/rake_task'
|
|
33
33
|
|
34
34
|
desc "Run all specs in spec directory (excluding plugin specs)"
|
35
35
|
|
36
|
-
|
36
|
+
task :generate_test_plugin do
|
37
|
+
require RedmineExtensions::Engine.root.join('spec', 'support', 'plugin_generator').to_s
|
38
|
+
PluginGenerator.generate_test_plugin!
|
39
|
+
end
|
40
|
+
RSpec::Core::RakeTask.new(spec: :generate_test_plugin) do |spec|
|
37
41
|
spec.pattern = 'spec/**/*_spec.rb'
|
38
42
|
spec.exclude_pattern = 'spec/redmine/**/*_spec.rb'
|
39
43
|
end
|
@@ -409,7 +409,7 @@ window.closeFlashMessage = (function($element){
|
|
409
409
|
that.load(function(){
|
410
410
|
var matcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i");
|
411
411
|
response($.grep(that.possibleValues, function(val, i) {
|
412
|
-
return ( !
|
412
|
+
return ( !request.term || matcher.test(val.value) );
|
413
413
|
}));
|
414
414
|
}, function(){
|
415
415
|
response();
|
@@ -70,7 +70,7 @@ module RedmineExtensions
|
|
70
70
|
entities_count = entities.size
|
71
71
|
options[:entities_count] = entities_count
|
72
72
|
options[:module_name] ||= "entity_#{entity.class.name.underscore}_#{entity.id}_#{collection_name}"
|
73
|
-
options[:heading] ||= l("label_#{query.entity}_plural", :default => 'Heading')
|
73
|
+
options[:heading] ||= l("label_#{query.entity.name.underscore}_plural", :default => 'Heading')
|
74
74
|
|
75
75
|
if options[:context_menus_path].nil?
|
76
76
|
options[:context_menus_path] = [
|
@@ -82,7 +82,7 @@ module RedmineExtensions
|
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|
85
|
-
query.output = options[:display_style] || (entities_count > 3 ? 'list' : '
|
85
|
+
query.output = options[:display_style] || (entities_count > 3 ? 'list' : 'tiles')
|
86
86
|
|
87
87
|
render(:partial => 'easy_entity_assignments/assignments_container', :locals => {
|
88
88
|
:entity => entity,
|
File without changes
|
@@ -1,3 +1,3 @@
|
|
1
|
-
<p>
|
2
|
-
<%= l(:text_modal_is_closing) %>
|
1
|
+
<p>
|
2
|
+
<%= l(:text_modal_is_closing) %>
|
3
3
|
</p>
|
@@ -1,5 +1,5 @@
|
|
1
|
-
$("#ajax-modal").html("<%= j render(:partial => 'common/closing_modal', :formats => [:html]) %>");
|
2
|
-
$("#ajax-modal").dialog('option', {
|
3
|
-
buttons: []
|
4
|
-
});
|
1
|
+
$("#ajax-modal").html("<%= j render(:partial => 'common/closing_modal', :formats => [:html]) %>");
|
2
|
+
$("#ajax-modal").dialog('option', {
|
3
|
+
buttons: []
|
4
|
+
});
|
5
5
|
window.location = "<%= j params[:back_url] %>";
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render(partial: 'easy_queries/entities', locals: local_assigns) %>
|
File without changes
|
@@ -1,9 +1,9 @@
|
|
1
|
-
<ul>
|
2
|
-
<%% if @<%= model_name_underscored %> && !@<%= model_name_underscored %>.new_record? %>
|
3
|
-
<li><%%= link_to l(:button_edit), edit_polymorphic_path([@project, @<%= model_name_underscored %>]), title: l(:button_edit), class: 'icon icon-edit' %></li>
|
4
|
-
<%% end %>
|
5
|
-
<%% if @<%= model_name_underscored %>.nil? %>
|
6
|
-
<li><%%= link_to l(:button_<%= model_name_underscored %>_new), new_polymorphic_path([@project, :<%= model_name_underscored %>]), title: l(:title_<%= model_name_underscored %>_new), class: 'icon icon-add button button-positive' %></li>
|
7
|
-
<%% end %>
|
8
|
-
<li><%%= link_to l(:label_<%= model_name_pluralize_underscored %>), polymorphic_path([@project, :<%= model_name_pluralize_underscored %>], set_filter: '1'), title: l(:label_<%= model_name_pluralize_underscored %>), class: 'icon icon-folder button' %></li>
|
1
|
+
<ul>
|
2
|
+
<%% if @<%= model_name_underscored %> && !@<%= model_name_underscored %>.new_record? %>
|
3
|
+
<li><%%= link_to l(:button_edit), edit_polymorphic_path([@project, @<%= model_name_underscored %>]), title: l(:button_edit), class: 'icon icon-edit' %></li>
|
4
|
+
<%% end %>
|
5
|
+
<%% if @<%= model_name_underscored %>.nil? %>
|
6
|
+
<li><%%= link_to l(:button_<%= model_name_underscored %>_new), new_polymorphic_path([@project, :<%= model_name_underscored %>]), title: l(:title_<%= model_name_underscored %>_new), class: 'icon icon-add button button-positive' %></li>
|
7
|
+
<%% end %>
|
8
|
+
<li><%%= link_to l(:label_<%= model_name_pluralize_underscored %>), polymorphic_path([@project, :<%= model_name_pluralize_underscored %>], set_filter: '1'), title: l(:label_<%= model_name_pluralize_underscored %>), class: 'icon icon-folder button' %></li>
|
9
9
|
</ul>
|
@@ -1,8 +1,8 @@
|
|
1
|
-
<ul>
|
2
|
-
<%% if @<%= model_name_underscored %> -%>
|
3
|
-
<li><%%= context_menu_link l(:button_edit), edit_<%= model_name_underscored %>_path(@<%= model_name_underscored %>), class: 'icon icon-edit', disabled: !@can[:edit] %></li>
|
4
|
-
<%% end %>
|
5
|
-
<li><%%= context_menu_link l(:button_delete), <%= model_name_pluralize_underscored %>_path(ids: @<%= model_name_underscored %>_ids, back_url: @back), method: :delete, data: {confirm: l(:text_are_you_sure)}, class: 'icon icon-del', disabled: !@can[:delete] %></li>
|
6
|
-
|
7
|
-
<%%= call_hook(:view_<%= model_name_pluralize_underscored %>_context_menu_end, {<%= model_name_underscored %>: @<%= model_name_underscored %>, <%= model_name_pluralize_underscored %>: @<%= model_name_pluralize_underscored %>, can: @can, back: @back, project: @project}) %>
|
1
|
+
<ul>
|
2
|
+
<%% if @<%= model_name_underscored %> -%>
|
3
|
+
<li><%%= context_menu_link l(:button_edit), edit_<%= model_name_underscored %>_path(@<%= model_name_underscored %>), class: 'icon icon-edit', disabled: !@can[:edit] %></li>
|
4
|
+
<%% end %>
|
5
|
+
<li><%%= context_menu_link l(:button_delete), <%= model_name_pluralize_underscored %>_path(ids: @<%= model_name_underscored %>_ids, back_url: @back), method: :delete, data: {confirm: l(:text_are_you_sure)}, class: 'icon icon-del', disabled: !@can[:delete] %></li>
|
6
|
+
|
7
|
+
<%%= call_hook(:view_<%= model_name_pluralize_underscored %>_context_menu_end, {<%= model_name_underscored %>: @<%= model_name_underscored %>, <%= model_name_pluralize_underscored %>: @<%= model_name_pluralize_underscored %>, can: @can, back: @back, project: @project}) %>
|
8
8
|
</ul>
|
@@ -1,7 +1,7 @@
|
|
1
|
-
class <%= model_name %>CustomField < CustomField
|
2
|
-
|
3
|
-
def type_name
|
4
|
-
:label_<%= @model_name_pluralize_underscored %>
|
5
|
-
end
|
6
|
-
|
7
|
-
end
|
1
|
+
class <%= model_name %>CustomField < CustomField
|
2
|
+
|
3
|
+
def type_name
|
4
|
+
:label_<%= @model_name_pluralize_underscored %>
|
5
|
+
end
|
6
|
+
|
7
|
+
end
|
@@ -1,19 +1,19 @@
|
|
1
|
-
<%%= title l(:heading_<%= model_name_underscored %>_edit) %>
|
2
|
-
|
3
|
-
<%%= form_for([@project, @<%= model_name_underscored %>], html: {multipart: <%= acts_as_attachable? %>, id: '<%= model_name_underscored %>_form', class: 'tabular', remote: request.xhr?}) do |f| %>
|
4
|
-
<%%= error_messages_for @<%= model_name_underscored %> %>
|
5
|
-
|
6
|
-
<div class="box">
|
7
|
-
<%%= render partial: 'form', locals: {<%= model_name_underscored %>: @<%= model_name_underscored %>} %>
|
8
|
-
</div>
|
9
|
-
|
10
|
-
<%% if !request.xhr? %>
|
11
|
-
<p>
|
12
|
-
<%%= submit_tag l(:button_update), title: l(:button_update) %>
|
13
|
-
</p>
|
14
|
-
<%% end %>
|
15
|
-
<%% end %>
|
16
|
-
<%% ### PAGE CUSTOMS ########################################################## %>
|
17
|
-
<%% content_for :sidebar do %>
|
18
|
-
<%%= render :partial => '<%= model_name_pluralize_underscored %>/sidebar' %>
|
1
|
+
<%%= title l(:heading_<%= model_name_underscored %>_edit) %>
|
2
|
+
|
3
|
+
<%%= form_for([@project, @<%= model_name_underscored %>], html: {multipart: <%= acts_as_attachable? %>, id: '<%= model_name_underscored %>_form', class: 'tabular', remote: request.xhr?}) do |f| %>
|
4
|
+
<%%= error_messages_for @<%= model_name_underscored %> %>
|
5
|
+
|
6
|
+
<div class="box">
|
7
|
+
<%%= render partial: 'form', locals: {<%= model_name_underscored %>: @<%= model_name_underscored %>} %>
|
8
|
+
</div>
|
9
|
+
|
10
|
+
<%% if !request.xhr? %>
|
11
|
+
<p>
|
12
|
+
<%%= submit_tag l(:button_update), title: l(:button_update) %>
|
13
|
+
</p>
|
14
|
+
<%% end %>
|
15
|
+
<%% end %>
|
16
|
+
<%% ### PAGE CUSTOMS ########################################################## %>
|
17
|
+
<%% content_for :sidebar do %>
|
18
|
+
<%%= render :partial => '<%= model_name_pluralize_underscored %>/sidebar' %>
|
19
19
|
<%% end %>
|
@@ -1,17 +1,17 @@
|
|
1
|
-
$("#ajax-modal").html("<%%= j render(:template => '<%= model_name_pluralize_underscored %>/edit', :formats => [:html]) %>");
|
2
|
-
showModal('ajax-modal');
|
3
|
-
var submitButton = {
|
4
|
-
text:"<%=j l(:button_update) -%>",
|
5
|
-
title:"<%=j l(:button_update) -%>",
|
6
|
-
click: function() {$(this).find('form').submit()},
|
7
|
-
'class': 'button-positive'
|
8
|
-
}
|
9
|
-
var closeButton = {
|
10
|
-
text: "<%=j l(:button_close) -%>",
|
11
|
-
title: "<%=j l(:button_close) -%>",
|
12
|
-
click: function() {$(this).dialog('close');},
|
13
|
-
'class': 'button'
|
14
|
-
}
|
15
|
-
$("#ajax-modal").dialog('option', {
|
16
|
-
buttons: [closeButton, submitButton]
|
1
|
+
$("#ajax-modal").html("<%%= j render(:template => '<%= model_name_pluralize_underscored %>/edit', :formats => [:html]) %>");
|
2
|
+
showModal('ajax-modal');
|
3
|
+
var submitButton = {
|
4
|
+
text:"<%=j l(:button_update) -%>",
|
5
|
+
title:"<%=j l(:button_update) -%>",
|
6
|
+
click: function() {$(this).find('form').submit()},
|
7
|
+
'class': 'button-positive'
|
8
|
+
}
|
9
|
+
var closeButton = {
|
10
|
+
text: "<%=j l(:button_close) -%>",
|
11
|
+
title: "<%=j l(:button_close) -%>",
|
12
|
+
click: function() {$(this).dialog('close');},
|
13
|
+
'class': 'button'
|
14
|
+
}
|
15
|
+
$("#ajax-modal").dialog('option', {
|
16
|
+
buttons: [closeButton, submitButton]
|
17
17
|
});
|
@@ -1,5 +1,5 @@
|
|
1
|
-
api.array :<%= model_name_pluralize_underscored %>, api_meta(total_count: @entity_count, offset: @offset, limit: @limit) do
|
2
|
-
@entities.each do |<%= model_name_underscored %>|
|
3
|
-
render_api_<%= model_name_underscored %>(api, <%= model_name_underscored %>)
|
4
|
-
end
|
5
|
-
end
|
1
|
+
api.array :<%= model_name_pluralize_underscored %>, api_meta(total_count: @entity_count, offset: @offset, limit: @limit) do
|
2
|
+
@entities.each do |<%= model_name_underscored %>|
|
3
|
+
render_api_<%= model_name_underscored %>(api, <%= model_name_underscored %>)
|
4
|
+
end
|
5
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
<%%= render @query %>
|
2
|
-
<%% ### PAGE CUSTOMS ########################################################## %>
|
3
|
-
<%% content_for :sidebar do %>
|
4
|
-
<%%= render :partial => '<%= model_name_pluralize_underscored %>/sidebar' %>
|
1
|
+
<%%= render @query %>
|
2
|
+
<%% ### PAGE CUSTOMS ########################################################## %>
|
3
|
+
<%% content_for :sidebar do %>
|
4
|
+
<%%= render :partial => '<%= model_name_pluralize_underscored %>/sidebar' %>
|
5
5
|
<%% end %>
|
@@ -1,11 +1,11 @@
|
|
1
|
-
$("#ajax-modal").html("<%%= j render(:template => '<%= model_name_pluralize_underscored %>/index', :formats => [:html]) %>");
|
2
|
-
showModal('ajax-modal');
|
3
|
-
var closeButton = {
|
4
|
-
text: "<%=j l(:button_close) -%>",
|
5
|
-
title: "<%=j l(:button_close) -%>",
|
6
|
-
click: function() {$(this).dialog('close');},
|
7
|
-
'class': 'button'
|
8
|
-
}
|
9
|
-
$("#ajax-modal").dialog('option', {
|
10
|
-
buttons: [closeButton, submitButton]
|
1
|
+
$("#ajax-modal").html("<%%= j render(:template => '<%= model_name_pluralize_underscored %>/index', :formats => [:html]) %>");
|
2
|
+
showModal('ajax-modal');
|
3
|
+
var closeButton = {
|
4
|
+
text: "<%=j l(:button_close) -%>",
|
5
|
+
title: "<%=j l(:button_close) -%>",
|
6
|
+
click: function() {$(this).dialog('close');},
|
7
|
+
'class': 'button'
|
8
|
+
}
|
9
|
+
$("#ajax-modal").dialog('option', {
|
10
|
+
buttons: [closeButton, submitButton]
|
11
11
|
});
|
@@ -1 +1 @@
|
|
1
|
-
<h1><%%= link_to(@<%= model_name_underscored %>.to_s, @<%= model_name_underscored %>_url) %></h1>
|
1
|
+
<h1><%%= link_to(@<%= model_name_underscored %>.to_s, @<%= model_name_underscored %>_url) %></h1>
|
@@ -1,2 +1,2 @@
|
|
1
|
-
<%%= @<%= model_name_underscored %>.to_s %>
|
2
|
-
<%%= @<%= model_name_underscored %>_url %>
|
1
|
+
<%%= @<%= model_name_underscored %>.to_s %>
|
2
|
+
<%%= @<%= model_name_underscored %>_url %>
|
@@ -1,2 +1,2 @@
|
|
1
|
-
<%%= @<%= model_name_underscored %>.to_s %>
|
2
|
-
<%%= @<%= model_name_underscored %>_url %>
|
1
|
+
<%%= @<%= model_name_underscored %>.to_s %>
|
2
|
+
<%%= @<%= model_name_underscored %>_url %>
|
@@ -1,9 +1,9 @@
|
|
1
|
-
class Create<%= model_name_pluralize_underscored.camelize %> < ActiveRecord::Migration
|
2
|
-
def change
|
3
|
-
create_table :<%= model_name_pluralize_underscored %>, force: true do |t|
|
4
|
-
<%- db_columns.each do |column_name, column_attrs| -%>
|
5
|
-
t.<%= column_attrs[:type] %> :<%= column_name %>, null: <%= column_attrs[:null] %>
|
6
|
-
<%- end -%>
|
7
|
-
end
|
8
|
-
end
|
9
|
-
end
|
1
|
+
class Create<%= model_name_pluralize_underscored.camelize %> < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :<%= model_name_pluralize_underscored %>, force: true do |t|
|
4
|
+
<%- db_columns.each do |column_name, column_attrs| -%>
|
5
|
+
t.<%= column_attrs[:type] %> :<%= column_name %>, null: <%= column_attrs[:null] %>
|
6
|
+
<%- end -%>
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
@@ -1,19 +1,19 @@
|
|
1
|
-
<%%= title l(:heading_<%= model_name_underscored %>_new) %>
|
2
|
-
|
3
|
-
<%%= form_for([@project, @<%= model_name_underscored %>], html: {multipart: <%= acts_as_attachable? %>, id: '<%= model_name_underscored %>_form', class: 'tabular', remote: request.xhr?}) do |f| %>
|
4
|
-
<%%= error_messages_for @<%= model_name_underscored %> %>
|
5
|
-
|
6
|
-
<div class="box">
|
7
|
-
<%%= render partial: 'form', locals: {<%= model_name_underscored %>: @<%= model_name_underscored %>} %>
|
8
|
-
</div>
|
9
|
-
|
10
|
-
<%% if !request.xhr? %>
|
11
|
-
<p>
|
12
|
-
<%%= submit_tag l(:button_create), title: l(:button_create) %>
|
13
|
-
</p>
|
14
|
-
<%% end %>
|
15
|
-
<%% end %>
|
16
|
-
<%% ### PAGE CUSTOMS ########################################################## %>
|
17
|
-
<%% content_for :sidebar do %>
|
18
|
-
<%%= render :partial => '<%= model_name_pluralize_underscored %>/sidebar' %>
|
1
|
+
<%%= title l(:heading_<%= model_name_underscored %>_new) %>
|
2
|
+
|
3
|
+
<%%= form_for([@project, @<%= model_name_underscored %>], html: {multipart: <%= acts_as_attachable? %>, id: '<%= model_name_underscored %>_form', class: 'tabular', remote: request.xhr?}) do |f| %>
|
4
|
+
<%%= error_messages_for @<%= model_name_underscored %> %>
|
5
|
+
|
6
|
+
<div class="box">
|
7
|
+
<%%= render partial: 'form', locals: {<%= model_name_underscored %>: @<%= model_name_underscored %>} %>
|
8
|
+
</div>
|
9
|
+
|
10
|
+
<%% if !request.xhr? %>
|
11
|
+
<p>
|
12
|
+
<%%= submit_tag l(:button_create), title: l(:button_create) %>
|
13
|
+
</p>
|
14
|
+
<%% end %>
|
15
|
+
<%% end %>
|
16
|
+
<%% ### PAGE CUSTOMS ########################################################## %>
|
17
|
+
<%% content_for :sidebar do %>
|
18
|
+
<%%= render :partial => '<%= model_name_pluralize_underscored %>/sidebar' %>
|
19
19
|
<%% end %>
|
@@ -1,17 +1,17 @@
|
|
1
|
-
$("#ajax-modal").html("<%%= j render(:template => '<%= model_name_pluralize_underscored %>/new', :formats => [:html]) %>");
|
2
|
-
showModal('ajax-modal');
|
3
|
-
var submitButton = {
|
4
|
-
text:"<%=j l(:button_create) -%>",
|
5
|
-
title:"<%=j l(:button_create) -%>",
|
6
|
-
click: function() {$(this).find('form').submit()},
|
7
|
-
'class': 'button-positive'
|
8
|
-
}
|
9
|
-
var closeButton = {
|
10
|
-
text: "<%=j l(:button_close) -%>",
|
11
|
-
title: "<%=j l(:button_close) -%>",
|
12
|
-
click: function() {$(this).dialog('close');},
|
13
|
-
'class': 'button'
|
14
|
-
}
|
15
|
-
$("#ajax-modal").dialog('option', {
|
16
|
-
buttons: [closeButton, submitButton]
|
1
|
+
$("#ajax-modal").html("<%%= j render(:template => '<%= model_name_pluralize_underscored %>/new', :formats => [:html]) %>");
|
2
|
+
showModal('ajax-modal');
|
3
|
+
var submitButton = {
|
4
|
+
text:"<%=j l(:button_create) -%>",
|
5
|
+
title:"<%=j l(:button_create) -%>",
|
6
|
+
click: function() {$(this).find('form').submit()},
|
7
|
+
'class': 'button-positive'
|
8
|
+
}
|
9
|
+
var closeButton = {
|
10
|
+
text: "<%=j l(:button_close) -%>",
|
11
|
+
title: "<%=j l(:button_close) -%>",
|
12
|
+
click: function() {$(this).dialog('close');},
|
13
|
+
'class': 'button'
|
14
|
+
}
|
15
|
+
$("#ajax-modal").dialog('option', {
|
16
|
+
buttons: [closeButton, submitButton]
|
17
17
|
});
|
@@ -1,13 +1,13 @@
|
|
1
|
-
<% if project? %>
|
2
|
-
resources :projects do
|
3
|
-
resources :<%= model_name_pluralize_underscored %>
|
4
|
-
end
|
5
|
-
<% end %>
|
6
|
-
resources :<%= model_name_pluralize_underscored %> do
|
7
|
-
collection do
|
8
|
-
get 'autocomplete'
|
9
|
-
get 'bulk_edit'
|
10
|
-
post 'bulk_update'
|
11
|
-
get 'context_menu'
|
12
|
-
end
|
1
|
+
<% if project? %>
|
2
|
+
resources :projects do
|
3
|
+
resources :<%= model_name_pluralize_underscored %>
|
4
|
+
end
|
5
|
+
<% end %>
|
6
|
+
resources :<%= model_name_pluralize_underscored %> do
|
7
|
+
collection do
|
8
|
+
get 'autocomplete'
|
9
|
+
get 'bulk_edit'
|
10
|
+
post 'bulk_update'
|
11
|
+
get 'context_menu'
|
12
|
+
end
|
13
13
|
end
|
@@ -1,38 +1,38 @@
|
|
1
|
-
<%%= title @<%= model_name_underscored %> %>
|
2
|
-
<div class="issue">
|
3
|
-
<table class="attributes">
|
4
|
-
<%%= issue_fields_rows do |rows| %>
|
5
|
-
<%- safe_columns.each_with_index do |column, idx| -%>
|
6
|
-
<%- next if description_column? && column[0] == description_column -%>
|
7
|
-
<%- if idx % 2 == 0 -%>
|
8
|
-
<%% rows.left ::<%= model_name %>.human_attribute_name(:<%= column[0] %>), format_object(@<%= model_name_underscored %>.<%= column[0] %>) %>
|
9
|
-
<%- else -%>
|
10
|
-
<%% rows.right ::<%= model_name %>.human_attribute_name(:<%= column[0] %>), format_object(@<%= model_name_underscored %>.<%= column[0] %>) %>
|
11
|
-
<%- end -%>
|
12
|
-
<%- end -%>
|
13
|
-
<%% end %>
|
14
|
-
<%%= render_custom_fields_rows(@<%= model_name_underscored %>) %>
|
15
|
-
<%%= call_hook(:view_<%= model_name_pluralize_underscored %>_show_details_bottom, :<%= model_name_underscored %> => @<%= model_name_underscored %>) %>
|
16
|
-
</table>
|
17
|
-
<%- if description_column? -%>
|
18
|
-
<%% if !@<%= model_name_underscored %>.<%= description_column %>.blank? %>
|
19
|
-
<hr />
|
20
|
-
<div class="description">
|
21
|
-
<p><strong><%%= ::<%= model_name %>.human_attribute_name(:<%= description_column %>) %></strong></p>
|
22
|
-
<div class="wiki">
|
23
|
-
<%%= textilizable @<%= model_name_underscored %>, :<%= description_column %>, attachments: @<%= model_name_underscored %>.attachments %>
|
24
|
-
</div>
|
25
|
-
</div>
|
26
|
-
<%% end %>
|
27
|
-
<%- end -%>
|
28
|
-
<%- if acts_as_attachable? -%>
|
29
|
-
<%% if @<%= model_name_underscored %>.attachments.any? -%>
|
30
|
-
<hr />
|
31
|
-
<%%= link_to_attachments @<%= model_name_underscored %>, :thumbnails => true %>
|
32
|
-
<%% end %>
|
33
|
-
<%- end -%>
|
34
|
-
</div>
|
35
|
-
<%% ### PAGE CUSTOMS ########################################################## %>
|
36
|
-
<%% content_for :sidebar do %>
|
37
|
-
<%%= render :partial => '<%= model_name_pluralize_underscored %>/sidebar' %>
|
1
|
+
<%%= title @<%= model_name_underscored %> %>
|
2
|
+
<div class="issue">
|
3
|
+
<table class="attributes">
|
4
|
+
<%%= issue_fields_rows do |rows| %>
|
5
|
+
<%- safe_columns.each_with_index do |column, idx| -%>
|
6
|
+
<%- next if description_column? && column[0] == description_column -%>
|
7
|
+
<%- if idx % 2 == 0 -%>
|
8
|
+
<%% rows.left ::<%= model_name %>.human_attribute_name(:<%= column[0] %>), format_object(@<%= model_name_underscored %>.<%= column[0] %>) %>
|
9
|
+
<%- else -%>
|
10
|
+
<%% rows.right ::<%= model_name %>.human_attribute_name(:<%= column[0] %>), format_object(@<%= model_name_underscored %>.<%= column[0] %>) %>
|
11
|
+
<%- end -%>
|
12
|
+
<%- end -%>
|
13
|
+
<%% end %>
|
14
|
+
<%%= render_custom_fields_rows(@<%= model_name_underscored %>) %>
|
15
|
+
<%%= call_hook(:view_<%= model_name_pluralize_underscored %>_show_details_bottom, :<%= model_name_underscored %> => @<%= model_name_underscored %>) %>
|
16
|
+
</table>
|
17
|
+
<%- if description_column? -%>
|
18
|
+
<%% if !@<%= model_name_underscored %>.<%= description_column %>.blank? %>
|
19
|
+
<hr />
|
20
|
+
<div class="description">
|
21
|
+
<p><strong><%%= ::<%= model_name %>.human_attribute_name(:<%= description_column %>) %></strong></p>
|
22
|
+
<div class="wiki">
|
23
|
+
<%%= textilizable @<%= model_name_underscored %>, :<%= description_column %>, attachments: @<%= model_name_underscored %>.attachments %>
|
24
|
+
</div>
|
25
|
+
</div>
|
26
|
+
<%% end %>
|
27
|
+
<%- end -%>
|
28
|
+
<%- if acts_as_attachable? -%>
|
29
|
+
<%% if @<%= model_name_underscored %>.attachments.any? -%>
|
30
|
+
<hr />
|
31
|
+
<%%= link_to_attachments @<%= model_name_underscored %>, :thumbnails => true %>
|
32
|
+
<%% end %>
|
33
|
+
<%- end -%>
|
34
|
+
</div>
|
35
|
+
<%% ### PAGE CUSTOMS ########################################################## %>
|
36
|
+
<%% content_for :sidebar do %>
|
37
|
+
<%%= render :partial => '<%= model_name_pluralize_underscored %>/sidebar' %>
|
38
38
|
<%% end %>
|
@@ -1,11 +1,11 @@
|
|
1
|
-
$("#ajax-modal").html("<%%= j render(:template => '<%= model_name_pluralize_underscored %>/show', :formats => [:html]) %>");
|
2
|
-
showModal('ajax-modal');
|
3
|
-
var closeButton = {
|
4
|
-
text: "<%=j l(:button_close) -%>",
|
5
|
-
title: "<%=j l(:button_close) -%>",
|
6
|
-
click: function() {$(this).dialog('close');},
|
7
|
-
'class': 'button'
|
8
|
-
}
|
9
|
-
$("#ajax-modal").dialog('option', {
|
10
|
-
buttons: [closeButton, submitButton]
|
1
|
+
$("#ajax-modal").html("<%%= j render(:template => '<%= model_name_pluralize_underscored %>/show', :formats => [:html]) %>");
|
2
|
+
showModal('ajax-modal');
|
3
|
+
var closeButton = {
|
4
|
+
text: "<%=j l(:button_close) -%>",
|
5
|
+
title: "<%=j l(:button_close) -%>",
|
6
|
+
click: function() {$(this).dialog('close');},
|
7
|
+
'class': 'button'
|
8
|
+
}
|
9
|
+
$("#ajax-modal").dialog('option', {
|
10
|
+
buttons: [closeButton, submitButton]
|
11
11
|
});
|
@@ -19,7 +19,7 @@ module RedmineExtensions
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def outputs
|
22
|
-
@outputs ||= enabled_outputs.map{|o| RedmineExtensions::QueryOutput.output_klass_for(o).new(@presenter, self) }.sort_by{|a| a.order}
|
22
|
+
@outputs ||= enabled_outputs.map{|o| RedmineExtensions::QueryOutput.output_klass_for(o, @query).new(@presenter, self) }.sort_by{|a| a.order}
|
23
23
|
end
|
24
24
|
|
25
25
|
def each(style = :enabled, &block)
|
@@ -2,6 +2,8 @@ require 'active_support/dependencies'
|
|
2
2
|
require 'redmine_extensions/patch_manager'
|
3
3
|
require 'redmine_extensions/redmine_patches/patches'
|
4
4
|
|
5
|
+
require 'redmine_extensions/query_output'
|
6
|
+
|
5
7
|
module RedmineExtensions
|
6
8
|
class Engine < ::Rails::Engine
|
7
9
|
|
@@ -18,7 +20,7 @@ module RedmineExtensions
|
|
18
20
|
#config.to_prepare goes after Reloader.to_prepare
|
19
21
|
ActionDispatch::Reloader.to_prepare do
|
20
22
|
RedmineExtensions::QueryOutput.register_output RedmineExtensions::QueryOutputs::ListOutput
|
21
|
-
RedmineExtensions::QueryOutput.register_output RedmineExtensions::QueryOutputs::
|
23
|
+
RedmineExtensions::QueryOutput.register_output RedmineExtensions::QueryOutputs::TilesOutput
|
22
24
|
# RedmineExtensions::BasePresenter.register 'RedmineExtensions::EasyQueryPresenter', 'EasyQuery'
|
23
25
|
# ApplicationController.send :include, RedmineExtensions::RailsPatches::ControllerQueryHelpers
|
24
26
|
ApplicationController.send :include, RedmineExtensions::RenderingHelper
|
@@ -13,20 +13,36 @@ module RedmineExtensions
|
|
13
13
|
@@registered_outputs ||= {}
|
14
14
|
end
|
15
15
|
|
16
|
-
def self.
|
17
|
-
|
16
|
+
def self.registered_per_query
|
17
|
+
@@registered_per_query ||= {}
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.register_output_for_query(klass, query_class_names, **options)
|
21
|
+
register_as ||= (options[:as] || klass.key).to_sym
|
22
|
+
Array.wrap(query_class_names).each do |query_class_name|
|
23
|
+
registered_per_query[query_class_name] ||= {}
|
24
|
+
registered_per_query[query_class_name][register_as] = klass
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.filter_registered_for(query)
|
29
|
+
res = registered_outputs.select do |_name, output|
|
18
30
|
output.available_for?(query)
|
19
|
-
end
|
31
|
+
end
|
32
|
+
res.merge(registered_per_query[query.type] || {})
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.available_outputs_for(query)
|
36
|
+
filter_registered_for(query).keys
|
20
37
|
end
|
21
38
|
|
22
39
|
def self.available_output_klasses_for(query)
|
23
|
-
|
24
|
-
output.available_for?(query)
|
25
|
-
end.values
|
40
|
+
filter_registered_for(query).values
|
26
41
|
end
|
27
42
|
|
28
|
-
def self.output_klass_for(output)
|
29
|
-
registered_outputs
|
43
|
+
def self.output_klass_for(output, query=nil)
|
44
|
+
filtered = query.nil? ? registered_outputs : filter_registered_for(query)
|
45
|
+
filtered[output.to_sym]
|
30
46
|
end
|
31
47
|
|
32
48
|
def self.key
|
@@ -36,7 +52,7 @@ module RedmineExtensions
|
|
36
52
|
|
37
53
|
# Take query and decide if it is possible to render it by this output
|
38
54
|
def self.available_for?(query)
|
39
|
-
query.
|
55
|
+
query.is_a? Query
|
40
56
|
end
|
41
57
|
|
42
58
|
def initialize(query_presenter, outputs=nil)
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
RSpec.describe 'autocomplete', type: :feature, js: true do
|
4
|
+
|
5
|
+
describe 'render' do
|
6
|
+
it 'generate default autocomplete' do
|
7
|
+
visit '/dummy_autocompletes'
|
8
|
+
expect(page).to have_css('input#default[type="text"]')
|
9
|
+
expect(page).to have_css('input[type="hidden"][name="default"][value="value1"]', visible: false)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
data/spec/rails_helper.rb
CHANGED
@@ -9,6 +9,7 @@ require 'factory_girl_rails'
|
|
9
9
|
require 'database_cleaner'
|
10
10
|
|
11
11
|
Rails.backtrace_cleaner.remove_silencers!
|
12
|
+
|
12
13
|
# Requires supporting ruby files with custom matchers and macros, etc, in
|
13
14
|
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
|
14
15
|
# run as spec files by default. This means that files in spec/support that end
|
@@ -28,6 +29,45 @@ require 'database_cleaner'
|
|
28
29
|
# If you are not using ActiveRecord, you can remove this line.
|
29
30
|
ActiveRecord::Migration.maintain_test_schema!
|
30
31
|
|
32
|
+
# warning supress for ruby 2.0 and new capybara see https://gist.github.com/ericboehs/7125105
|
33
|
+
class WarningSuppressor
|
34
|
+
IGNORES = [
|
35
|
+
/QFont::setPixelSize: Pixel size <= 0/,
|
36
|
+
/CoreText performance note:/,
|
37
|
+
/Heya! This page is using wysihtml5/,
|
38
|
+
/You must provide a success callback to the Chooser to see the files that the user selects/
|
39
|
+
]
|
40
|
+
|
41
|
+
class << self
|
42
|
+
def write(message)
|
43
|
+
if suppress?(message) then 0 else puts(message);1;end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
def suppress?(message)
|
48
|
+
IGNORES.any? { |re| message =~ re }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
require 'capybara/poltergeist'
|
54
|
+
|
55
|
+
Capybara.register_driver :poltergeist do |app|
|
56
|
+
Capybara::Poltergeist::Driver.new(app, {
|
57
|
+
inspector: 'google-chrome-stable',
|
58
|
+
js_errors: true,
|
59
|
+
timeout: 1.hour.seconds.to_i,
|
60
|
+
phantomjs_options: ['--ignore-ssl-errors=yes'],
|
61
|
+
phantomjs_logger: WarningSuppressor
|
62
|
+
})
|
63
|
+
end
|
64
|
+
|
65
|
+
Capybara.register_driver :chrome do |app|
|
66
|
+
Capybara::Selenium::Driver.new(app, :browser => :chrome)
|
67
|
+
end
|
68
|
+
|
69
|
+
Capybara.javascript_driver = ENV['JS_DRIVER'].present? ? ENV['JS_DRIVER'].downcase.to_sym : :poltergeist
|
70
|
+
|
31
71
|
RSpec.configure do |config|
|
32
72
|
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
|
33
73
|
config.fixture_path = "#{::Rails.root}/spec/fixtures"
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
|
3
|
+
module PluginGenerator
|
4
|
+
def self.generate_test_plugin!
|
5
|
+
Rails::Generators.invoke 'redmine_extensions:plugin', ['DummyPlugin'], behavior: :revoke, destination_root: Rails.root
|
6
|
+
Rails::Generators.invoke 'redmine_extensions:plugin', ['DummyPlugin'], behavior: :invoke, destination_root: Rails.root
|
7
|
+
# if Rails::VERSION::MAJOR >= 5
|
8
|
+
# Rails.application.reloader.reload!
|
9
|
+
# else
|
10
|
+
# ActionDispatch::Reloader.cleanup!
|
11
|
+
# ActionDispatch::Reloader.prepare!
|
12
|
+
# end
|
13
|
+
|
14
|
+
generate_autocomplete!
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.generate_autocomplete!
|
18
|
+
generate_autocomplete_controller!
|
19
|
+
generate_autocomplete_routes!
|
20
|
+
generate_autocomplete_view!
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.generate_autocomplete_controller!
|
24
|
+
File.open(Rails.root.join('plugins', 'dummy_plugin', 'app', 'controllers', 'dummy_autocompletes_controller.rb'), 'w') do |file|
|
25
|
+
file.write( <<-END_RUBY )
|
26
|
+
class DummyAutocompletesController < ApplicationController
|
27
|
+
def index
|
28
|
+
end
|
29
|
+
end
|
30
|
+
END_RUBY
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.generate_autocomplete_routes!
|
35
|
+
File.open(Rails.root.join('plugins', 'dummy_plugin', 'config', 'routes.rb'), 'w') do |file|
|
36
|
+
file.write("resources :dummy_autocompletes")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.generate_autocomplete_view!
|
41
|
+
dir = Rails.root.join('plugins', 'dummy_plugin', 'app', 'views', 'dummy_autocompletes')
|
42
|
+
Dir.mkdir dir
|
43
|
+
File.open(dir.join('index.html.erb'), 'w') do |file|
|
44
|
+
file.write( <<-END_RUBY )
|
45
|
+
<%= form_tag('/dummy_autocompletes', id: 'autocompletes_form') do %>
|
46
|
+
<%= autocomplete_field_tag('default', ['value1', 'value2'], ['value1']) %>
|
47
|
+
<% end %>
|
48
|
+
END_RUBY
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redmine_extensions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.14
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Easy Software Ltd
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-09-
|
11
|
+
date: 2016-09-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -94,6 +94,20 @@ dependencies:
|
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '4.6'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: poltergeist
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '1.10'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '1.10'
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
112
|
name: database_cleaner
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -131,12 +145,14 @@ files:
|
|
131
145
|
- app/presenters/easy_query_adapter_presenter.rb
|
132
146
|
- app/presenters/redmine_extensions/base_presenter.rb
|
133
147
|
- app/presenters/redmine_extensions/easy_setting_presenter.rb
|
148
|
+
- app/presenters/redmine_extensions/issue_query_presenter.rb
|
134
149
|
- app/views/common/_closing_modal.html.erb
|
135
150
|
- app/views/common/_collapsible_module_layout.html.erb
|
136
151
|
- app/views/common/close_modal.js.erb
|
137
152
|
- app/views/easy_entity_assignments/_assignments_container.html.erb
|
138
153
|
- app/views/easy_entity_assignments/_query_index.html.erb
|
139
|
-
- app/views/easy_queries/
|
154
|
+
- app/views/easy_queries/_easy_query_list.html.erb
|
155
|
+
- app/views/easy_queries/_easy_query_tiles.html.erb
|
140
156
|
- app/views/easy_queries/_entities.html.erb
|
141
157
|
- app/views/easy_queries/_index.html.erb
|
142
158
|
- app/views/easy_queries/_settings.html.erb
|
@@ -208,7 +224,7 @@ files:
|
|
208
224
|
- lib/redmine_extensions/patch_manager.rb
|
209
225
|
- lib/redmine_extensions/query_output.rb
|
210
226
|
- lib/redmine_extensions/query_outputs/list_output.rb
|
211
|
-
- lib/redmine_extensions/query_outputs/
|
227
|
+
- lib/redmine_extensions/query_outputs/tiles_output.rb
|
212
228
|
- lib/redmine_extensions/rails_patches/active_record.rb
|
213
229
|
- lib/redmine_extensions/rails_patches/route_set_generator_patch.rb
|
214
230
|
- lib/redmine_extensions/redmine_patches/controllers/application_controller_patch.rb
|
@@ -222,10 +238,12 @@ files:
|
|
222
238
|
- spec/factories/time_entries.rb
|
223
239
|
- spec/factories/trackers.rb
|
224
240
|
- spec/factories/users.rb
|
241
|
+
- spec/features/autocomplete_spec.rb
|
225
242
|
- spec/models/easy_setting_spec.rb
|
226
243
|
- spec/presenters/redmine_extensions/easy_setting_presenter_spec.rb
|
227
244
|
- spec/rails_helper.rb
|
228
245
|
- spec/spec_helper.rb
|
246
|
+
- spec/support/plugin_generator.rb
|
229
247
|
homepage: https://www.easyredmine.com
|
230
248
|
licenses:
|
231
249
|
- GPL-2.0
|
@@ -252,14 +270,16 @@ specification_version: 4
|
|
252
270
|
summary: Redmine Extensions is set of usefull features for Redmine. Main focus is
|
253
271
|
on development helpers, but many users can find it helpfull
|
254
272
|
test_files:
|
255
|
-
- spec/
|
256
|
-
- spec/
|
273
|
+
- spec/presenters/redmine_extensions/easy_setting_presenter_spec.rb
|
274
|
+
- spec/rails_helper.rb
|
275
|
+
- spec/features/autocomplete_spec.rb
|
276
|
+
- spec/models/easy_setting_spec.rb
|
257
277
|
- spec/factories/issues.rb
|
258
|
-
- spec/factories/projects.rb
|
259
278
|
- spec/factories/time_entries.rb
|
260
279
|
- spec/factories/trackers.rb
|
280
|
+
- spec/factories/easy_queries.rb
|
281
|
+
- spec/factories/projects.rb
|
261
282
|
- spec/factories/users.rb
|
262
|
-
- spec/
|
263
|
-
- spec/
|
264
|
-
- spec/rails_helper.rb
|
283
|
+
- spec/factories/easy_settings.rb
|
284
|
+
- spec/support/plugin_generator.rb
|
265
285
|
- spec/spec_helper.rb
|