Skip to content

Commit

Permalink
fixed #14: adding dynamic attributes support
Browse files Browse the repository at this point in the history
git-svn-id: https://forgetmenot-svn.cvsdude.com/main/trunk@83 a23ba2f0-501e-4c28-b130-3ad736a215ff
  • Loading branch information
Renat Akhmerov committed Jun 6, 2007
1 parent 3c6fa6f commit 497b080
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 9 deletions.
4 changes: 4 additions & 0 deletions app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,8 @@ def breadcrumbs(object)
link_to e.display_name, :id => e.id
}.push(object.display_name).join(" > ")
end

def get_dynamic_attribute_type_names
DynamicAttributeValue.content_columns.collect { |c| $1 if c.name =~ /(\w+)_value/ }.compact
end
end
37 changes: 30 additions & 7 deletions app/models/contact.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,26 @@ class Contact < ActiveRecord::Base

private

def dynamic_attribute_value(a)
if self.id.nil?
if new_dynamic_attribute_values.has_key?(a.name.to_sym)
value = new_dynamic_attribute_values[a.name.to_sym]
else
value = DynamicAttributeValue.new :dynamic_attribute_id => a.id
new_dynamic_attribute_values[a.name.to_sym] = value
end
else
if new_dynamic_attribute_values.has_key?(a.name.to_sym)
value = new_dynamic_attribute_values[a.name.to_sym]
else
value = DynamicAttributeValue.find_by_dynamic_attribute_id_and_contact_id(a.id, self.id)
value = DynamicAttributeValue.new :dynamic_attribute_id => a.id, :contact_id => self.id if value.nil?
new_dynamic_attribute_values[a.name.to_sym] = value
end
end
value
end

def self.do_acts_as_ferret(attrs = DynamicAttribute.find(:all))
acts_as_ferret :additional_fields => attrs.collect { |a| a.name.to_sym }
# FIXME: workaround here - drop following line
Expand All @@ -28,6 +48,10 @@ def self.drop_index_dir

public

def new_dynamic_attribute_values
@new_dynamic_attribute_values ||= {}
end

# moved from private part of class for test only
def self.create_attributes
attrs = DynamicAttribute.find(:all)
Expand All @@ -36,23 +60,23 @@ def self.create_attributes
end

def self.create_attribute(a, recreate_index = true)
# defining getter method
define_method a.name do
value = DynamicAttributeValue.find_by_dynamic_attribute_id_and_contact_id(a.id, self.id)
return nil unless value
value.send("#{a.type_name}_value")
dynamic_attribute_value(a).send("#{a.type_name}_value")
end

# defining setter method
define_method "#{a.name}=" do |new_value|
value = DynamicAttributeValue.find_or_create_by_dynamic_attribute_id_and_contact_id(a.id, self.id)
value.update_attribute("#{a.type_name}_value", new_value)
ferret_update
dynamic_attribute_value(a).send("#{a.type_name}_value=", new_value)
end

do_acts_as_ferret if recreate_index
end

create_attributes
acts_as_taggable
after_create { |c| c.new_dynamic_attribute_values.values.each { |v| v.contact_id = c.id; v.save } }
after_update { |c| c.new_dynamic_attribute_values.values.each { |v| v.save } }

def display_name
!self.first_name.nil? || !self.last_name.nil? ? "#{self.first_name} #{self.last_name}".strip : "contact ##{self.id}"
Expand All @@ -64,6 +88,5 @@ def column_for_attribute(method_name)
obj.nil? ? DynamicAttribute.find_by_name(method_name).column : obj
end


end

6 changes: 5 additions & 1 deletion app/views/common/_form.rhtml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
(@object.get_entity_columns + @dynamic_attributes).collect{ |column|
result = "<p><label for=\"object_#{column.name}\">#{column.name.humanize}</label>"
result += " <i>Markdown available (<a href=\"http://maruku.rubyforge.org/#features\">see syntax details</a>)</i>" if column.name == 'notes'
result += "<br/>\n#{input('object', column.name)}"
if params[:table_name] == 'dynamic_attributes' && column.name == 'type_name'
result += "<br/>\n#{select('object', column.name, get_dynamic_attribute_type_names)}"
else
result += "<br/>\n#{input('object', column.name)}"
end
result +="</p>\n"
result
}.join("\n")
Expand Down
40 changes: 39 additions & 1 deletion test/unit/contact_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ def test_dynamic_attribute_values
jid = DynamicAttribute.create :name => 'jabber_id', :type_name => 'string'
assert_nil thomas.jabber_id
assert_nothing_raised { thomas.jabber_id = 'thomas@jabber.org' }
assert_nothing_raised { thomas.save! }
assert_equal 'thomas@jabber.org', Contact.find(thomas.id).jabber_id
end

Expand All @@ -155,7 +156,9 @@ def test_search_by_dynamic_attributes
assert_equal 1, Contact.find_by_contents('skype:yura__115').total_hits

# now assign some value to new attribute ...
Contact.find(contacts(:thomas).id).jabber = 'ttttt'
thomas = Contact.find contacts(:thomas).id
thomas.jabber = 'ttttt'
thomas.save!

# ... and find by just created attribute
assert_equal 1, Contact.find_by_contents('jabber:ttttt').total_hits
Expand All @@ -164,6 +167,41 @@ def test_search_by_dynamic_attributes
# one more check of old attributes
assert_equal 1, Contact.find_by_contents('Yury').total_hits
end

def test_dynamic_attributes_for_new_object
values_count = DynamicAttributeValue.count

# creating new contact
yura = Contact.new :first_name => 'Yury', :last_name => 'Kazantsev', :skype => 'yukazan'
assert_equal 'yukazan', yura.skype
assert_equal values_count, DynamicAttributeValue.count

# saving it
assert_nothing_raised { yura.save! }
assert_equal values_count + DynamicAttribute.count, DynamicAttributeValue.count

# verifing dyn attr value
yura = Contact.find_by_last_name('Kazantsev')
assert_equal 'yukazan', yura.skype

# searching by attr value
assert_equal 1, Contact.find_by_contents('yukazan').total_hits

# changing attribute value without saving...
yura.skype = 'yurakazan'
assert_equal 'yurakazan', yura.skype
# ...should be no changes in the db ...
assert_equal 'yukazan', Contact.find(yura.id).skype
# ... as well as no changes in ferret index
assert_equal 1, Contact.find_by_contents('yukazan').total_hits
assert_equal 0, Contact.find_by_contents('yurakazan').total_hits

yura.save!

assert_equal 'yurakazan', Contact.find(yura.id).skype
assert_equal 0, Contact.find_by_contents('yukazan').total_hits
assert_equal 1, Contact.find_by_contents('yurakazan').total_hits
end

def subtest_group(group)
assert_instance_of Group, group
Expand Down

0 comments on commit 497b080

Please sign in to comment.