Revision 1298:4f746d8966dd .svn/pristine/34
| .svn/pristine/34/3426569be9b65b6dce3f0afa56586bb79fc07741.svn-base | ||
|---|---|---|
| 1 |
# Redmine - project management software |
|
| 2 |
# Copyright (C) 2006-2011 Jean-Philippe Lang |
|
| 3 |
# |
|
| 4 |
# This program is free software; you can redistribute it and/or |
|
| 5 |
# modify it under the terms of the GNU General Public License |
|
| 6 |
# as published by the Free Software Foundation; either version 2 |
|
| 7 |
# of the License, or (at your option) any later version. |
|
| 8 |
# |
|
| 9 |
# This program is distributed in the hope that it will be useful, |
|
| 10 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 11 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 12 |
# GNU General Public License for more details. |
|
| 13 |
# |
|
| 14 |
# You should have received a copy of the GNU General Public License |
|
| 15 |
# along with this program; if not, write to the Free Software |
|
| 16 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
| 17 |
|
|
| 18 |
module Redmine |
|
| 19 |
module Acts |
|
| 20 |
module Customizable |
|
| 21 |
def self.included(base) |
|
| 22 |
base.extend ClassMethods |
|
| 23 |
end |
|
| 24 |
|
|
| 25 |
module ClassMethods |
|
| 26 |
def acts_as_customizable(options = {})
|
|
| 27 |
return if self.included_modules.include?(Redmine::Acts::Customizable::InstanceMethods) |
|
| 28 |
cattr_accessor :customizable_options |
|
| 29 |
self.customizable_options = options |
|
| 30 |
has_many :custom_values, :as => :customized, |
|
| 31 |
:include => :custom_field, |
|
| 32 |
:order => "#{CustomField.table_name}.position",
|
|
| 33 |
:dependent => :delete_all |
|
| 34 |
before_validation { |customized| customized.custom_field_values if customized.new_record? }
|
|
| 35 |
# Trigger validation only if custom values were changed |
|
| 36 |
validates_associated :custom_values, :on => :update, :if => Proc.new { |customized| customized.custom_field_values_changed? }
|
|
| 37 |
send :include, Redmine::Acts::Customizable::InstanceMethods |
|
| 38 |
# Save custom values when saving the customized object |
|
| 39 |
after_save :save_custom_field_values |
|
| 40 |
end |
|
| 41 |
end |
|
| 42 |
|
|
| 43 |
module InstanceMethods |
|
| 44 |
def self.included(base) |
|
| 45 |
base.extend ClassMethods |
|
| 46 |
end |
|
| 47 |
|
|
| 48 |
def available_custom_fields |
|
| 49 |
CustomField.find(:all, :conditions => "type = '#{self.class.name}CustomField'",
|
|
| 50 |
:order => 'position') |
|
| 51 |
end |
|
| 52 |
|
|
| 53 |
# Sets the values of the object's custom fields |
|
| 54 |
# values is an array like [{'id' => 1, 'value' => 'foo'}, {'id' => 2, 'value' => 'bar'}]
|
|
| 55 |
def custom_fields=(values) |
|
| 56 |
values_to_hash = values.inject({}) do |hash, v|
|
|
| 57 |
v = v.stringify_keys |
|
| 58 |
if v['id'] && v.has_key?('value')
|
|
| 59 |
hash[v['id']] = v['value'] |
|
| 60 |
end |
|
| 61 |
hash |
|
| 62 |
end |
|
| 63 |
self.custom_field_values = values_to_hash |
|
| 64 |
end |
|
| 65 |
|
|
| 66 |
# Sets the values of the object's custom fields |
|
| 67 |
# values is a hash like {'1' => 'foo', 2 => 'bar'}
|
|
| 68 |
def custom_field_values=(values) |
|
| 69 |
@custom_field_values_changed = true |
|
| 70 |
values = values.stringify_keys |
|
| 71 |
custom_field_values.each do |custom_value| |
|
| 72 |
custom_value.value = values[custom_value.custom_field_id.to_s] if values.has_key?(custom_value.custom_field_id.to_s) |
|
| 73 |
end if values.is_a?(Hash) |
|
| 74 |
end |
|
| 75 |
|
|
| 76 |
def custom_field_values |
|
| 77 |
@custom_field_values ||= available_custom_fields.collect { |x| custom_values.detect { |v| v.custom_field == x } || custom_values.build(:customized => self, :custom_field => x, :value => nil) }
|
|
| 78 |
end |
|
| 79 |
|
|
| 80 |
def visible_custom_field_values |
|
| 81 |
custom_field_values.select(&:visible?) |
|
| 82 |
end |
|
| 83 |
|
|
| 84 |
def custom_field_values_changed? |
|
| 85 |
@custom_field_values_changed == true |
|
| 86 |
end |
|
| 87 |
|
|
| 88 |
def custom_value_for(c) |
|
| 89 |
field_id = (c.is_a?(CustomField) ? c.id : c.to_i) |
|
| 90 |
custom_values.detect {|v| v.custom_field_id == field_id }
|
|
| 91 |
end |
|
| 92 |
|
|
| 93 |
def save_custom_field_values |
|
| 94 |
self.custom_values = custom_field_values |
|
| 95 |
custom_field_values.each(&:save) |
|
| 96 |
@custom_field_values_changed = false |
|
| 97 |
@custom_field_values = nil |
|
| 98 |
end |
|
| 99 |
|
|
| 100 |
def reset_custom_values! |
|
| 101 |
@custom_field_values = nil |
|
| 102 |
@custom_field_values_changed = true |
|
| 103 |
values = custom_values.inject({}) {|h,v| h[v.custom_field_id] = v.value; h}
|
|
| 104 |
custom_values.each {|cv| cv.destroy unless custom_field_values.include?(cv)}
|
|
| 105 |
end |
|
| 106 |
|
|
| 107 |
module ClassMethods |
|
| 108 |
end |
|
| 109 |
end |
|
| 110 |
end |
|
| 111 |
end |
|
| 112 |
end |
|
| .svn/pristine/34/342bfb95b19c2d2bc64485e9d4d12de5afbbc42e.svn-base | ||
|---|---|---|
| 1 |
Return-Path: <JSmith@somenet.foo> |
|
| 2 |
Received: from osiris ([127.0.0.1]) |
|
| 3 |
by OSIRIS |
|
| 4 |
with hMailServer ; Sun, 22 Jun 2008 12:28:07 +0200 |
|
| 5 |
Message-ID: <000501c8d452$a95cd7e0$0a00a8c0@osiris> |
|
| 6 |
From: "John Smith" <JSmith@somenet.foo> |
|
| 7 |
To: <redmine@somenet.foo> |
|
| 8 |
Subject: New ticket on a given project with a very long subject line which exceeds 255 chars and should not be ignored but chopped off. And if the subject line is still not long enough, we just add more text. And more text. Wow, this is really annoying. Especially, if you have nothing to say... |
|
| 9 |
Date: Sun, 22 Jun 2008 12:28:07 +0200 |
|
| 10 |
MIME-Version: 1.0 |
|
| 11 |
Content-Type: text/plain; |
|
| 12 |
format=flowed; |
|
| 13 |
charset="iso-8859-1"; |
|
| 14 |
reply-type=original |
|
| 15 |
Content-Transfer-Encoding: 7bit |
|
| 16 |
X-Priority: 3 |
|
| 17 |
X-MSMail-Priority: Normal |
|
| 18 |
X-Mailer: Microsoft Outlook Express 6.00.2900.2869 |
|
| 19 |
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.2869 |
|
| 20 |
|
|
| 21 |
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas imperdiet |
|
| 22 |
turpis et odio. Integer eget pede vel dolor euismod varius. Phasellus |
|
| 23 |
blandit eleifend augue. Nulla facilisi. Duis id diam. Class aptent taciti |
|
| 24 |
sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. In |
|
| 25 |
in urna sed tellus aliquet lobortis. Morbi scelerisque tortor in dolor. Cras |
|
| 26 |
sagittis odio eu lacus. Aliquam sem tortor, consequat sit amet, vestibulum |
|
| 27 |
id, iaculis at, lectus. Fusce tortor libero, congue ut, euismod nec, luctus |
|
| 28 |
eget, eros. Pellentesque tortor enim, feugiat in, dignissim eget, tristique |
|
| 29 |
sed, mauris --- Pellentesque habitant morbi tristique senectus et netus et |
|
| 30 |
malesuada fames ac turpis egestas. Quisque sit amet libero. In hac habitasse |
|
| 31 |
platea dictumst. |
|
| 32 |
|
|
| 33 |
--- This line starts with a delimiter and should not be stripped |
|
| 34 |
|
|
| 35 |
This paragraph is before delimiters. |
|
| 36 |
|
|
| 37 |
BREAK |
|
| 38 |
|
|
| 39 |
This paragraph is between delimiters. |
|
| 40 |
|
|
| 41 |
--- |
|
| 42 |
|
|
| 43 |
This paragraph is after the delimiter so it shouldn't appear. |
|
| 44 |
|
|
| 45 |
Nulla et nunc. Duis pede. Donec et ipsum. Nam ut dui tincidunt neque |
|
| 46 |
sollicitudin iaculis. Duis vitae dolor. Vestibulum eget massa. Sed lorem. |
|
| 47 |
Nullam volutpat cursus erat. Cras felis dolor, lacinia quis, rutrum et, |
|
| 48 |
dictum et, ligula. Sed erat nibh, gravida in, accumsan non, placerat sed, |
|
| 49 |
massa. Sed sodales, ante fermentum ultricies sollicitudin, massa leo |
|
| 50 |
pulvinar dui, a gravida orci mi eget odio. Nunc a lacus. |
|
| 51 |
|
|
| 52 |
Project: onlinestore |
|
| 53 |
Status: Resolved |
|
| 54 |
due date: 2010-12-31 |
|
| 55 |
Start Date:2010-01-01 |
|
| 56 |
Assigned to: John Smith |
|
| 57 |
|
|
| .svn/pristine/34/345b699f46121e103fdce4587bf3ec87db1cc445.svn-base | ||
|---|---|---|
| 1 |
module ActiveRecord |
|
| 2 |
module Acts |
|
| 3 |
module Tree |
|
| 4 |
def self.included(base) |
|
| 5 |
base.extend(ClassMethods) |
|
| 6 |
end |
|
| 7 |
|
|
| 8 |
# Specify this +acts_as+ extension if you want to model a tree structure by providing a parent association and a children |
|
| 9 |
# association. This requires that you have a foreign key column, which by default is called +parent_id+. |
|
| 10 |
# |
|
| 11 |
# class Category < ActiveRecord::Base |
|
| 12 |
# acts_as_tree :order => "name" |
|
| 13 |
# end |
|
| 14 |
# |
|
| 15 |
# Example: |
|
| 16 |
# root |
|
| 17 |
# \_ child1 |
|
| 18 |
# \_ subchild1 |
|
| 19 |
# \_ subchild2 |
|
| 20 |
# |
|
| 21 |
# root = Category.create("name" => "root")
|
|
| 22 |
# child1 = root.children.create("name" => "child1")
|
|
| 23 |
# subchild1 = child1.children.create("name" => "subchild1")
|
|
| 24 |
# |
|
| 25 |
# root.parent # => nil |
|
| 26 |
# child1.parent # => root |
|
| 27 |
# root.children # => [child1] |
|
| 28 |
# root.children.first.children.first # => subchild1 |
|
| 29 |
# |
|
| 30 |
# In addition to the parent and children associations, the following instance methods are added to the class |
|
| 31 |
# after calling <tt>acts_as_tree</tt>: |
|
| 32 |
# * <tt>siblings</tt> - Returns all the children of the parent, excluding the current node (<tt>[subchild2]</tt> when called on <tt>subchild1</tt>) |
|
| 33 |
# * <tt>self_and_siblings</tt> - Returns all the children of the parent, including the current node (<tt>[subchild1, subchild2]</tt> when called on <tt>subchild1</tt>) |
|
| 34 |
# * <tt>ancestors</tt> - Returns all the ancestors of the current node (<tt>[child1, root]</tt> when called on <tt>subchild2</tt>) |
|
| 35 |
# * <tt>root</tt> - Returns the root of the current node (<tt>root</tt> when called on <tt>subchild2</tt>) |
|
| 36 |
module ClassMethods |
|
| 37 |
# Configuration options are: |
|
| 38 |
# |
|
| 39 |
# * <tt>foreign_key</tt> - specifies the column name to use for tracking of the tree (default: +parent_id+) |
|
| 40 |
# * <tt>order</tt> - makes it possible to sort the children according to this SQL snippet. |
|
| 41 |
# * <tt>counter_cache</tt> - keeps a count in a +children_count+ column if set to +true+ (default: +false+). |
|
| 42 |
def acts_as_tree(options = {})
|
|
| 43 |
configuration = { :foreign_key => "parent_id", :dependent => :destroy, :order => nil, :counter_cache => nil }
|
|
| 44 |
configuration.update(options) if options.is_a?(Hash) |
|
| 45 |
|
|
| 46 |
belongs_to :parent, :class_name => name, :foreign_key => configuration[:foreign_key], :counter_cache => configuration[:counter_cache] |
|
| 47 |
has_many :children, :class_name => name, :foreign_key => configuration[:foreign_key], :order => configuration[:order], :dependent => configuration[:dependent] |
|
| 48 |
|
|
| 49 |
scope :roots, where("#{configuration[:foreign_key]} IS NULL").order(configuration[:order])
|
|
| 50 |
|
|
| 51 |
send :include, ActiveRecord::Acts::Tree::InstanceMethods |
|
| 52 |
end |
|
| 53 |
end |
|
| 54 |
|
|
| 55 |
module InstanceMethods |
|
| 56 |
# Returns list of ancestors, starting from parent until root. |
|
| 57 |
# |
|
| 58 |
# subchild1.ancestors # => [child1, root] |
|
| 59 |
def ancestors |
|
| 60 |
node, nodes = self, [] |
|
| 61 |
nodes << node = node.parent while node.parent |
|
| 62 |
nodes |
|
| 63 |
end |
|
| 64 |
|
|
| 65 |
# Returns list of descendants. |
|
| 66 |
# |
|
| 67 |
# root.descendants # => [child1, subchild1, subchild2] |
|
| 68 |
def descendants(depth=nil) |
|
| 69 |
depth ||= 0 |
|
| 70 |
result = children.dup |
|
| 71 |
unless depth == 1 |
|
| 72 |
result += children.collect {|child| child.descendants(depth-1)}.flatten
|
|
| 73 |
end |
|
| 74 |
result |
|
| 75 |
end |
|
| 76 |
|
|
| 77 |
# Returns list of descendants and a reference to the current node. |
|
| 78 |
# |
|
| 79 |
# root.self_and_descendants # => [root, child1, subchild1, subchild2] |
|
| 80 |
def self_and_descendants(depth=nil) |
|
| 81 |
[self] + descendants(depth) |
|
| 82 |
end |
|
| 83 |
|
|
| 84 |
# Returns the root node of the tree. |
|
| 85 |
def root |
|
| 86 |
node = self |
|
| 87 |
node = node.parent while node.parent |
|
| 88 |
node |
|
| 89 |
end |
|
| 90 |
|
|
| 91 |
# Returns all siblings of the current node. |
|
| 92 |
# |
|
| 93 |
# subchild1.siblings # => [subchild2] |
|
| 94 |
def siblings |
|
| 95 |
self_and_siblings - [self] |
|
| 96 |
end |
|
| 97 |
|
|
| 98 |
# Returns all siblings and a reference to the current node. |
|
| 99 |
# |
|
| 100 |
# subchild1.self_and_siblings # => [subchild1, subchild2] |
|
| 101 |
def self_and_siblings |
|
| 102 |
parent ? parent.children : self.class.roots |
|
| 103 |
end |
|
| 104 |
end |
|
| 105 |
end |
|
| 106 |
end |
|
| 107 |
end |
|
| .svn/pristine/34/34e888bcdeab7ab62509c340e12806f908468391.svn-base | ||
|---|---|---|
| 1 |
author: James Adam |
|
| 2 |
email: james.adam@gmail.com |
|
| 3 |
homepage: http://www.rails-engines.org |
|
| 4 |
summary: Enhances the plugin mechanism to perform more flexible sharing |
|
| 5 |
description: The Rails Engines plugin allows the sharing of almost any type of code or asset that you could use in a Rails application, including controllers, models, stylesheets, and views. |
|
| 6 |
license: MIT |
|
| 7 |
version: 2.3.2 |
|
Also available in: Unified diff