Skip to content

Commit

Permalink
Started to change [Image] filters for [Image?]. Relations introspecti…
Browse files Browse the repository at this point in the history
…on for vclass.
  • Loading branch information
gaspard committed Dec 20, 2010
1 parent 10761bc commit 5c39fed
Show file tree
Hide file tree
Showing 12 changed files with 139 additions and 25 deletions.
4 changes: 4 additions & 0 deletions app/models/relation_proxy.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
class RelationProxy < Relation
include RubyLess

safe_method :name => {:class => String, :method => 'other_role'}

attr_accessor :side, :link_errors, :start, :other_link, :last_target, :add_links
LINK_ATTRIBUTES = Zena::Use::Relations::LINK_ATTRIBUTES
LINK_ATTRIBUTES_SQL = LINK_ATTRIBUTES.map {|sym| connection.quote_column_name(sym)}.join(',')
Expand Down
8 changes: 8 additions & 0 deletions app/models/virtual_class.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ class VirtualClass < Role
include Zena::Use::ScopeIndex::VirtualClassMethods

safe_context :roles => {:class => ['Role'], :method => 'sorted_roles'}
safe_method :relations => {:class => ['RelationProxy'], :method => 'all_relations'}
safe_method [:relations, String] => {:class => ['RelationProxy'], :method => 'zafu_all_relations'}

class Cache
def initialize
Expand Down Expand Up @@ -392,6 +394,12 @@ def sorted_roles
end
end

# List all relations that can be set for this class, filtering by
# relation group.
def zafu_all_relations(group_filter)
all_relations(nil, group_filter)
end

# Cache index groups
def index_groups
@index_groups ||= super
Expand Down
9 changes: 9 additions & 0 deletions db/migrate/20101213133816_add_group_to_relation.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class AddGroupToRelation < ActiveRecord::Migration
def self.up
add_column :relations, :rel_group, :string
end

def self.down
remove_column :relations, :rel_group
end
end
2 changes: 1 addition & 1 deletion lib/zena/use/query_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def query_build_clause(key, arg)
''
elsif arg =~ /\*/
# like
"#{key} like #{arg.gsub('%','*').inspect}"
"#{key} like #{arg.gsub('*','%').inspect}"
elsif arg =~ /^(.+)\.\.(.+)$/
# interval
"#{key} >= #{$1} and #{key} <= #{$2}"
Expand Down
20 changes: 15 additions & 5 deletions lib/zena/use/relations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,21 @@ def method_missing(sym, *args)
module ClassMethods

# All relations related to the current class/virtual_class with its ancestors.
def all_relations(start=nil)
rel_as_source = RelationProxy.find(:all, :conditions => ["site_id = ? AND source_kpath IN (?)", current_site[:id], split_kpath])
rel_as_target = RelationProxy.find(:all, :conditions => ["site_id = ? AND target_kpath IN (?)", current_site[:id], split_kpath])
rel_as_source.each {|rel| rel.source = start } if start
rel_as_target.each {|rel| rel.target = start } if start
def all_relations(start=nil, group_filter=nil)
if group_filter
group_filter = "#{group_filter}%"
rel_as_source = RelationProxy.find(:all,
:conditions => ["site_id = ? AND source_kpath IN (?) AND rel_group LIKE ?", current_site[:id], split_kpath, group_filter])
rel_as_target = RelationProxy.find(:all,
:conditions => ["site_id = ? AND target_kpath IN (?) AND rel_group LIKE ?", current_site[:id], split_kpath, group_filter])
else
rel_as_source = RelationProxy.find(:all,
:conditions => ["site_id = ? AND source_kpath IN (?)", current_site[:id], split_kpath])
rel_as_target = RelationProxy.find(:all,
:conditions => ["site_id = ? AND target_kpath IN (?)", current_site[:id], split_kpath])
end
rel_as_source.each {|rel| rel.source = start }
rel_as_target.each {|rel| rel.target = start }
(rel_as_source + rel_as_target).sort {|a,b| a.other_role <=> b.other_role}
end

Expand Down
27 changes: 23 additions & 4 deletions lib/zena/use/zafu_safe_definitions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,21 @@ class ParamsDictionary

module ViewMethods
include RubyLess

# Dynamic resolution of kind_of
def self.kind_of_proc
Proc.new do |receiver, role_or_vclass|
if role_or_vclass.kind_of?(VirtualClass)
res = "#{receiver}.kpath_match?('#{role_or_vclass.kpath}')"
else
# Role
res = "#{receiver}.has_role?(#{role_or_vclass.id})"
end

RubyLess::TypedString.new(res, :class => Boolean)
end
end

safe_method :params => ParamsDictionary
safe_method :now => {:method => 'Time.now', :class => Time}
safe_method [:h, String] => {:class => String, :nil => true}
Expand All @@ -19,19 +34,23 @@ module ViewMethods
safe_method_for Number, :to_s => {:class => String, :pre_processor => true}
safe_method_for Object, :blank? => Boolean

safe_method_for Node, [:kind_of?, VirtualClass] =>
{:method => 'nil', :nil => true, :pre_processor => kind_of_proc}
safe_method_for Node, [:kind_of?, Role] =>
{:method => 'nil', :nil => true, :pre_processor => kind_of_proc}
safe_method_for Node, [:kind_of?, String] => {:method => 'kpath_match?', :class => Boolean}
safe_method_for Node, [:kind_of?, Number] => {:method => 'has_role?', :class => Boolean}
safe_method_for Array, [:index, String] => {:class => Number, :nil => true}

end # ViewMethods


module ZafuMethods

def safe_const_type(class_name)
if klass = get_class(class_name)
{:method => "'#{klass.kpath}'", :class => String}
if klass = VirtualClass[class_name]
{:method => "VirtualClass[#{class_name.inspect}]", :nil => true, :class => VirtualClass, :literal => klass}
elsif role = Node.get_role(class_name)
{:method => role.id.to_s, :class => Number}
{:method => "Role.find(#{role.id})", :nil => true, :class => Role, :literal => role}
else
nil
end
Expand Down
4 changes: 2 additions & 2 deletions test/integration/zafu_compiler/query.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,11 @@ interval_date_en:

like:
tem: "<%= query_parse('para' => %{*bar}) %>"
res: "para like \"*bar\""
res: "para like \"%bar\""

like_at_end:
tem: "<%= query_parse('para' => %{bar*}) %>"
res: "para like \"bar*\""
res: "para like \"bar%\""

literal_with_star:
tem: "<%= query_parse('para' => %{'*bar'}) %>"
Expand Down
2 changes: 1 addition & 1 deletion test/integration/zafu_compiler/relations.yml
Original file line number Diff line number Diff line change
Expand Up @@ -459,4 +459,4 @@ final_class:
count:
src: "<p do='nodes in site order by id' find='count'/>"
tem: "<p><%= Node.do_find(:count, %Q{SELECT COUNT(*) FROM nodes WHERE #{secure_scope('nodes')}}) %></p>"
res: "<p>42</p>"
res: "<p>42</p>"
28 changes: 26 additions & 2 deletions test/integration/zafu_compiler/roles.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,22 @@ vclass_column_size:
res: "Node (3), Original (3), Task (1)"

vclass_context:
src: "<r:ImageClass><r:name/></r:ImageClass>"
src: "<r:Image><r:name/></r:Image>"
tem: "<% if var1 = VirtualClass['Image'] -%><%= var1.name %><% end -%>"
res: "Image"

vclass_scope:
context:
node: bird_jpg
src: "<r:Image?>I am an image</r:Image?>"
tem: "<% if @node.kpath_match?('NDI') -%>I am an image<% end -%>"
res: "I am an image"

vclass_in_rubyless:
src: "<b do='Contact.name'/>"
tem: "<b><%= (VirtualClass[\"Contact\"] ? VirtualClass[\"Contact\"].name : nil) %></b>"
res: "<b>Contact</b>"

grid_manual:
src: |
<table do='images in site'>
Expand All @@ -91,4 +103,16 @@ grid_manual:

grid:
src: "<r:images in='site' do='grid'/>"
res: "/<table class='grid'>.*<th class='role' colspan='3'>Node.*<th class='role' colspan='3'>Original.*<th>exif</th><th>height</th><th>width</th>.*<td>image/jpeg</td><td>jpg</td>/"
res: "/<table class='grid'>.*<th class='role' colspan='3'>Node.*<th class='role' colspan='3'>Original.*<th>exif</th><th>height</th><th>width</th>.*<td>image/jpeg</td><td>jpg</td>/"

list_relations:
src: "<r:Contact do='relations' do='each' join=', ' do='name'/>"
res: "collaborator_for, favorite, favorite_for, home_for, hot_for, icon, reference, reference_for, set_tag"

list_relations_filter_group:
src: "<r:Contact do='relations(\"doc\")' do='each' join=', ' do='name'/>"
res: "reference, reference_for, set_tag"

input_relation_name:
src: "<r:select name='link[role]' values='Contact.relations(\"doc\")'/>"
tem: "xx"
5 changes: 5 additions & 0 deletions test/sites/zena/relations.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ node_has_tags:
source_role: tagged
target_role: set_tag
target_icon: "<img src='/images/tag_blue.png' alt='tag'/>"
rel_group: 'doc.tags'

node_has_references:
source_kpath: N
target_kpath: N
source_role: reference_for
target_role: reference
rel_group: 'doc.ref'

node_has_an_icon:
source_kpath: N
Expand All @@ -34,6 +36,7 @@ project_has_a_hot_element:
target_kpath: N
target_unique: yes
target_icon: "<img src='/images/lightbulb.png' alt='hot'/>"
rel_group: 'web'

project_has_a_home:
source_kpath: NPP
Expand All @@ -43,6 +46,7 @@ project_has_a_home:
source_role: home_for
target_role: home
target_icon: "<img src='/images/home.png' alt='home'/>"
rel_group: 'web'

project_has_collaborators:
source_kpath: NPP
Expand All @@ -51,6 +55,7 @@ project_has_collaborators:
source_role: collaborator_for
target_role: collaborator
target_icon: "<img src='/images/user.png' alt='collaborator'/>"
rel_group: 'people'

post_has_blogs:
source_kpath: NNP
Expand Down
24 changes: 22 additions & 2 deletions test/unit/relation_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,26 @@ class RelationTest < Zena::Unit::TestCase
assert_equal sites_id(:zena), subject.site_id
end

context 'with a relation group' do
subject do
Relation.create(
:source_role => 'wife',
:target_role => 'husband',
:source_kpath => 'NRC',
:target_kpath => 'NRC',
:rel_group => 'marital'
)
end

should 'succeed' do
assert !subject.new_record?
end

should 'store rel_group info in relation' do
assert_equal 'marital', Relation.find(subject).rel_group
end
end # with a group

context 'with blank source_role' do
subject do
Relation.create(
Expand Down Expand Up @@ -98,7 +118,7 @@ class RelationTest < Zena::Unit::TestCase
should 'singularize source role' do
assert_equal 'wife', subject[:source_role]
end

should 'show source role as plural' do
assert_equal 'wives', subject.source_role
end
Expand All @@ -122,7 +142,7 @@ class RelationTest < Zena::Unit::TestCase
should 'singularize target role' do
assert_equal 'husband', subject[:target_role]
end

should 'show target role as plural' do
assert_equal 'husbands', subject.target_role
end
Expand Down
31 changes: 23 additions & 8 deletions test/unit/virtual_class_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,22 @@ def setup_cache_test
end # on new_instance
end # A Document vclass

context 'A note vclass' do
context 'A vclass' do
context 'on relations' do
subject do
VirtualClass['Letter'].relations
end

should 'return a list of relation proxies on relations' do
assert_kind_of RelationProxy, subject.first
end

should 'return a list of relation proxies on relations' do
assert_equal %w{xx}, subject.map(&:other_role).sort
end
end # on relations


context 'on new_instance' do
subject do
VirtualClass['Letter'].new_instance(
Expand Down Expand Up @@ -557,15 +572,15 @@ def setup_cache_test
assert subject <= VirtualClass['Note']
assert !(subject <= Project)
end

should 'respond to less then' do
assert subject < Note
assert subject < Node
assert subject < VirtualClass['Note']
assert !(subject < Project)
assert !(subject < VirtualClass['Post'])
end

should 'consider role methods as safe' do
assert_equal Hash[:class=>String, :method=>"prop['assigned']", :nil=>true], subject.safe_method_type(['assigned'])
end
Expand All @@ -575,7 +590,7 @@ def setup_cache_test
setup do
login(:tiger)
end

context 'on a node' do
context 'from a class with roles' do
subject do
Expand Down Expand Up @@ -612,15 +627,15 @@ def setup_cache_test
assert_equal 'flat Eric', subject.assigned
end
end

should 'consider role methods as safe' do
assert_equal Hash[:class=>String, :method=>"prop['paper']", :nil=>true], subject.safe_method_type(['paper'])
end

should 'not consider VirtualClass own methods as safe' do
assert_nil subject.safe_method_type(['name'])
end

should 'not allow arbitrary attributes' do
assert !subject.update_attributes('assigned' => 'flat Eric', 'bad' => 'property')
end
Expand All @@ -641,7 +656,7 @@ def setup_cache_test
assert !subject.update_attributes('properties' => {'bad' => 'property'})
assert_equal 'property not declared', subject.errors[:bad]
end

end # from a class with roles
end # on a node
end # A visitor with write access
Expand Down

0 comments on commit 5c39fed

Please sign in to comment.