[#604] Add an IssueDrop with custom field support
This commit is contained in:
parent
6f8d8c4105
commit
7906afe6b9
65
app/drops/issue_drop.rb
Normal file
65
app/drops/issue_drop.rb
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
class IssueDrop < BaseDrop
|
||||||
|
allowed_methods :id
|
||||||
|
allowed_methods :subject
|
||||||
|
allowed_methods :description
|
||||||
|
allowed_methods :project
|
||||||
|
allowed_methods :tracker
|
||||||
|
allowed_methods :status
|
||||||
|
allowed_methods :due_date
|
||||||
|
allowed_methods :category
|
||||||
|
allowed_methods :assigned_to
|
||||||
|
allowed_methods :priority
|
||||||
|
allowed_methods :fixed_version
|
||||||
|
allowed_methods :author
|
||||||
|
allowed_methods :created_on
|
||||||
|
allowed_methods :updated_on
|
||||||
|
allowed_methods :start_date
|
||||||
|
allowed_methods :done_ratio
|
||||||
|
allowed_methods :estimated_hours
|
||||||
|
allowed_methods :parent
|
||||||
|
|
||||||
|
def custom_field(name)
|
||||||
|
return '' unless name.present?
|
||||||
|
custom_field = IssueCustomField.find_by_name(name.strip)
|
||||||
|
return '' unless custom_field.present?
|
||||||
|
custom_value = @object.custom_value_for(custom_field)
|
||||||
|
if custom_value.present?
|
||||||
|
return custom_value.value
|
||||||
|
else
|
||||||
|
return ''
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# TODO: both required, method_missing for Ruby and before_method for Liquid
|
||||||
|
|
||||||
|
# Allows accessing custom fields by their name:
|
||||||
|
#
|
||||||
|
# - issue.the_name_of_player => CustomField(:name => "The name Of Player")
|
||||||
|
#
|
||||||
|
def before_method(method_sym)
|
||||||
|
if custom_field_with_matching_name = has_custom_field_with_matching_name?(method_sym)
|
||||||
|
custom_field(custom_field_with_matching_name.name)
|
||||||
|
else
|
||||||
|
super
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Allows accessing custom fields by their name:
|
||||||
|
#
|
||||||
|
# - issue.the_name_of_player => CustomField(:name => "The name Of Player")
|
||||||
|
#
|
||||||
|
def method_missing(method_sym, *arguments, &block)
|
||||||
|
if custom_field_with_matching_name = has_custom_field_with_matching_name?(method_sym)
|
||||||
|
custom_field(custom_field_with_matching_name.name)
|
||||||
|
else
|
||||||
|
super
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def has_custom_field_with_matching_name?(method_sym)
|
||||||
|
custom_field_with_matching_name = @object.available_custom_fields.detect {|custom_field|
|
||||||
|
custom_field.name.downcase.underscore.gsub(' ','_') == method_sym.to_s
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
3
app/drops/issue_status_drop.rb
Normal file
3
app/drops/issue_status_drop.rb
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
class IssueStatusDrop < BaseDrop
|
||||||
|
allowed_methods :name
|
||||||
|
end
|
3
app/drops/tracker_drop.rb
Normal file
3
app/drops/tracker_drop.rb
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
class TrackerDrop < BaseDrop
|
||||||
|
allowed_methods :name
|
||||||
|
end
|
@ -103,6 +103,10 @@ class Issue < ActiveRecord::Base
|
|||||||
(usr || User.current).allowed_to?(:view_issues, self.project)
|
(usr || User.current).allowed_to?(:view_issues, self.project)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_liquid
|
||||||
|
IssueDrop.new(self)
|
||||||
|
end
|
||||||
|
|
||||||
def after_initialize
|
def after_initialize
|
||||||
if new_record?
|
if new_record?
|
||||||
# set default values for new records only
|
# set default values for new records only
|
||||||
|
@ -28,6 +28,10 @@ class IssueStatus < ActiveRecord::Base
|
|||||||
IssueStatus.update_all("is_default=#{connection.quoted_false}", ['id <> ?', id]) if self.is_default?
|
IssueStatus.update_all("is_default=#{connection.quoted_false}", ['id <> ?', id]) if self.is_default?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_liquid
|
||||||
|
IssueStatusDrop.new(self)
|
||||||
|
end
|
||||||
|
|
||||||
# Returns the default status for new issues
|
# Returns the default status for new issues
|
||||||
def self.default
|
def self.default
|
||||||
find(:first, :conditions =>["is_default=?", true])
|
find(:first, :conditions =>["is_default=?", true])
|
||||||
|
@ -35,6 +35,10 @@ class Tracker < ActiveRecord::Base
|
|||||||
name <=> tracker.name
|
name <=> tracker.name
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_liquid
|
||||||
|
TrackerDrop.new(self)
|
||||||
|
end
|
||||||
|
|
||||||
def self.all
|
def self.all
|
||||||
find(:all, :order => 'position')
|
find(:all, :order => 'position')
|
||||||
end
|
end
|
||||||
|
89
test/unit/issue_drop_test.rb
Normal file
89
test/unit/issue_drop_test.rb
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
require File.expand_path('../../test_helper', __FILE__)
|
||||||
|
|
||||||
|
class IssueDropTest < ActiveSupport::TestCase
|
||||||
|
include ApplicationHelper
|
||||||
|
|
||||||
|
def setup
|
||||||
|
@project = Project.generate!
|
||||||
|
@issue = Issue.generate_for_project!(@project)
|
||||||
|
User.current = @user = User.generate!
|
||||||
|
@role = Role.generate!(:permissions => [:view_issues])
|
||||||
|
Member.generate!(:principal => @user, :project => @project, :roles => [@role])
|
||||||
|
@drop = @issue.to_liquid
|
||||||
|
end
|
||||||
|
|
||||||
|
context "drop" do
|
||||||
|
should "be a IssueDrop" do
|
||||||
|
assert @drop.is_a?(IssueDrop), "drop is not a IssueDrop"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
[
|
||||||
|
:tracker,
|
||||||
|
:project,
|
||||||
|
:subject,
|
||||||
|
:description,
|
||||||
|
:due_date,
|
||||||
|
:category,
|
||||||
|
:status,
|
||||||
|
:assigned_to,
|
||||||
|
:priority,
|
||||||
|
:fixed_version,
|
||||||
|
:author,
|
||||||
|
:created_on,
|
||||||
|
:updated_on,
|
||||||
|
:start_date,
|
||||||
|
:done_ratio,
|
||||||
|
:estimated_hours,
|
||||||
|
:parent
|
||||||
|
].each do |attribute|
|
||||||
|
|
||||||
|
should "IssueDrop##{attribute} should return the actual #{attribute} attribute" do
|
||||||
|
assert @issue.respond_to?(attribute), "Issue does not have an #{attribute} method"
|
||||||
|
assert @drop.respond_to?(attribute), "IssueDrop does not have an #{attribute} method"
|
||||||
|
|
||||||
|
assert_equal @issue.send(attribute), @drop.send(attribute)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "custom fields" do
|
||||||
|
setup do
|
||||||
|
@field = IssueCustomField.generate!(:name => 'The Name', :field_format => 'string', :is_for_all => true, :trackers => @project.trackers)
|
||||||
|
@field_name_conflict = IssueCustomField.generate!(:name => 'Subject', :field_format => 'string', :is_for_all => true, :trackers => @project.trackers)
|
||||||
|
@issue.custom_fields = [{'id' => @field.id, 'value' => 'Custom field value'},
|
||||||
|
{'id' => @field_name_conflict.id, 'value' => 'Second subject'}]
|
||||||
|
assert @issue.save
|
||||||
|
assert_equal "Custom field value", @issue.reload.custom_value_for(@field).value
|
||||||
|
assert_equal "Second subject", @issue.reload.custom_value_for(@field_name_conflict).value
|
||||||
|
@drop = @issue.to_liquid
|
||||||
|
end
|
||||||
|
|
||||||
|
should "be accessible under #custom_field(name)" do
|
||||||
|
assert_equal @issue.reload.custom_value_for(@field).value, @drop.custom_field('The Name')
|
||||||
|
end
|
||||||
|
|
||||||
|
should "be accessible under the custom field name (lowercase, underscored)" do
|
||||||
|
assert_equal @issue.reload.custom_value_for(@field).value, @drop.the_name
|
||||||
|
|
||||||
|
assert textilizable("{{issue.the_name}}").include?("Custom field value")
|
||||||
|
end
|
||||||
|
|
||||||
|
should "not be accessible under the custom field name if it conflict with an existing drop method" do
|
||||||
|
assert_equal @issue.subject, @drop.subject # no confict
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
should "only load an object if it's visible to the current user" do
|
||||||
|
assert User.current.logged?
|
||||||
|
assert @issue.visible?
|
||||||
|
|
||||||
|
@private_project = Project.generate!(:is_public => false)
|
||||||
|
@private_issue = Issue.generate_for_project!(@private_project)
|
||||||
|
|
||||||
|
assert !@private_issue.visible?, "Issue is visible"
|
||||||
|
@private_drop = IssueDrop.new(@private_issue)
|
||||||
|
assert_equal nil, @private_drop.instance_variable_get("@object")
|
||||||
|
assert_equal nil, @private_drop.subject
|
||||||
|
end
|
||||||
|
end
|
21
test/unit/issue_status_drop_test.rb
Normal file
21
test/unit/issue_status_drop_test.rb
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
require File.expand_path('../../test_helper', __FILE__)
|
||||||
|
|
||||||
|
class IssueStatusDropTest < ActiveSupport::TestCase
|
||||||
|
def setup
|
||||||
|
@issue_status = IssueStatus.generate!
|
||||||
|
@drop = @issue_status.to_liquid
|
||||||
|
end
|
||||||
|
|
||||||
|
context "drop" do
|
||||||
|
should "be a IssueStatusDrop" do
|
||||||
|
assert @drop.is_a?(IssueStatusDrop), "drop is not a IssueStatusDrop"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
context "#name" do
|
||||||
|
should "return the name" do
|
||||||
|
assert_equal @issue_status.name, @drop.name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
20
test/unit/tracker_drop_test.rb
Normal file
20
test/unit/tracker_drop_test.rb
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
require File.expand_path('../../test_helper', __FILE__)
|
||||||
|
|
||||||
|
class TrackerDropTest < ActiveSupport::TestCase
|
||||||
|
def setup
|
||||||
|
@tracker = Tracker.generate!
|
||||||
|
@drop = @tracker.to_liquid
|
||||||
|
end
|
||||||
|
|
||||||
|
context "drop" do
|
||||||
|
should "be a TrackerDrop" do
|
||||||
|
assert @drop.is_a?(TrackerDrop), "drop is not a TrackerDrop"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "#name" do
|
||||||
|
should "return the name" do
|
||||||
|
assert_equal @tracker.name, @drop.name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
x
Reference in New Issue
Block a user