[#604] Add an IssueDrop with custom field support

This commit is contained in:
Eric Davis 2011-05-03 16:36:44 -07:00 committed by Holger Just
parent 6f8d8c4105
commit 7906afe6b9
9 changed files with 213 additions and 0 deletions

65
app/drops/issue_drop.rb Normal file
View 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

View File

@ -0,0 +1,3 @@
class IssueStatusDrop < BaseDrop
allowed_methods :name
end

View File

@ -0,0 +1,3 @@
class TrackerDrop < BaseDrop
allowed_methods :name
end

View File

@ -103,6 +103,10 @@ class Issue < ActiveRecord::Base
(usr || User.current).allowed_to?(:view_issues, self.project)
end
def to_liquid
IssueDrop.new(self)
end
def after_initialize
if new_record?
# set default values for new records only

View File

@ -28,6 +28,10 @@ class IssueStatus < ActiveRecord::Base
IssueStatus.update_all("is_default=#{connection.quoted_false}", ['id <> ?', id]) if self.is_default?
end
def to_liquid
IssueStatusDrop.new(self)
end
# Returns the default status for new issues
def self.default
find(:first, :conditions =>["is_default=?", true])

View File

@ -35,6 +35,10 @@ class Tracker < ActiveRecord::Base
name <=> tracker.name
end
def to_liquid
TrackerDrop.new(self)
end
def self.all
find(:all, :order => 'position')
end

View 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

View 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

View 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