Skip to content

Commit

Permalink
Implemented relations export/import.
Browse files Browse the repository at this point in the history
  • Loading branch information
gaspard committed Apr 15, 2011
1 parent 447179c commit b8c4011
Show file tree
Hide file tree
Showing 13 changed files with 157 additions and 131 deletions.
30 changes: 1 addition & 29 deletions app/controllers/columns_controller.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
class ColumnsController < ApplicationController
before_filter :visitor_node
before_filter :find_column, :except => [:index, :create, :new, :import]
before_filter :find_column, :except => [:index, :create, :new]
before_filter :check_is_admin
layout :admin_layout

Expand Down Expand Up @@ -29,34 +29,6 @@ def index
end
end

def export
data = secure(Column) do
Column.export
end

### TODO
end

def import
attachment = params[:attachment]
if attachment.nil?
flass[:error] = "Upload failure: no definitions."
redirect_to :action => :index
else
data = YAML.load(attachment.read) rescue nil
if data.nil?
flash[:error] = "Could not parse yaml document"
redirect_to :action => :index
else
@columns = secure(Column) { Column.import(data) }.paginate(:per_page => 200)
@column = VirtualClass.new('')
respond_to do |format|
format.html { render :action => 'index' }
end
end
end
end

# GET /columns/1
# GET /columns/1.xml
def show
Expand Down
50 changes: 0 additions & 50 deletions app/models/column.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
class Column < ActiveRecord::Base
attr_accessor :import_result
include RubyLess
include Property::StoredColumn
TYPES_FOR_FORM = %w{string datetime integer float}
Expand Down Expand Up @@ -49,55 +48,6 @@ def add_field_index(*args)
FIELD_INDICES << idx
end
end

# Import a hash of virtual class definitions and try to build the virtual classes.
def import(data)
data.keys.map do |klass|
build_column(klass, data)
end
end

# Build a virtual class from a name and a hash of virtual class definitions. If
# the superclass is in the data hash, it is built first.
def build_column(klass, data)
# TODO
# return data[klass]['result'] if data[klass].has_key?('result')
# if virtual_class = Node.get_class(klass)
# if virtual_class.superclass.to_s == data[klass]['superclass']
# virtual_class.import_result = 'same'
# return data[klass]['result'] = virtual_class
# else
# virtual_class.errors.add(:base, 'conflict')
# return data[klass]['result'] = virtual_class
# end
# else
# superclass_name = data[klass]['superclass']
# if data[superclass_name]
# superclass = build_virtual_class(superclass_name, data)
# unless superclass.errors.empty?
# virtual_class = VirtualClass.new(:name => klass, :superclass => superclass_name, :create_group_id => current_site.public_group_id)
# virtual_class.errors.add(:base, 'conflict in superclass')
# return data[klass]['result'] = virtual_class
# end
# elsif superclass = Node.get_class(superclass_name)
# # ok
# else
# virtual_class = VirtualClass.new(:name => klass, :superclass => superclass_name, :create_group_id => current_site.public_group_id)
# virtual_class.errors.add(:base, 'missing superclass')
# return data[klass]['result'] = virtual_class
# end
#
# # build
# create_group_id = superclass.kind_of?(VirtualClass) ? superclass.create_group_id : current_site.public_group_id
# virtual_class = create(data[klass].merge(:name => klass, :create_group_id => create_group_id))
# virtual_class.import_result = 'new'
# return data[klass]['result'] = virtual_class
# end
end

def export
# TODO
end
end

def kpath
Expand Down
13 changes: 13 additions & 0 deletions app/models/relation.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
class Relation < ActiveRecord::Base
EXPORT_FIELDS = %w{target_kpath target_icon target_unique source_role source_icon source_unique rel_group}

before_validation :singularize_roles
validate :valid_relation
attr_accessor :side, :link_errors, :start, :link
Expand All @@ -16,6 +18,17 @@ def target_role
target_unique ? self[:target_role] : self[:target_role].pluralize
end

def export
res = Zafu::OrderedHash.new
EXPORT_FIELDS.each do |key|
value = self[key]
if !value.blank?
res[key] = value
end
end
res
end

private
def singularize_roles
self.source_role = self[:source_role].singularize unless self[:source_role].blank?
Expand Down
62 changes: 41 additions & 21 deletions app/models/role.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def export

def import(definitions, delete = false)
res = []
post_import = []
# Create everything in a transaction
transaction do
definitions.each do |name, definition|
Expand All @@ -44,30 +45,34 @@ def import(definitions, delete = false)
raise Exception.new("Importation needs to start with a real class: '#{name}' is not a real class.")
else
# start importing
res += import_all(klass, definition)
res += import_all(klass, definition, post_import)
end
end

post_import.each do |l|
l.call
end
end
res
end

private
def import_all(superclass, definitions)
def import_all(superclass, definitions, post_import)
res = []
definitions.each do |name, sub|
next unless name =~ /\A[A-Z]/

klass = VirtualClass[name]
if klass && klass.real_class?
res += import_all(klass, sub)
res += import_all(klass, sub, post_import)
elsif sub['type'] == 'Role'
res << import_role(superclass, name, sub)
elsif sub['type'] == 'Class'
# real class
raise Exception.new("Unknown real class '#{name}'.")
elsif sub['type'] == 'VirtualClass' || sub['type'].nil?
# VirtualClass
res += import_vclass(superclass, name, sub)
res += import_vclass(superclass, name, sub, post_import)
else
# Invalid type
raise Exception.new("Cannot create '#{name}': invalid type '#{sub['type']}'.")
Expand Down Expand Up @@ -98,7 +103,7 @@ def import_role(superclass, name, definition)
role
end

def import_vclass(superclass, name, definition)
def import_vclass(superclass, name, definition, post_import)
res = []
vclass = ::Role.find_by_name_and_site_id(name, current_site.id)
if vclass && vclass.class != VirtualClass
Expand All @@ -121,14 +126,19 @@ def import_vclass(superclass, name, definition)
res << vclass

# 2. create or update columns (never delete)
if !vclass.new_record? && columns = definition['columns']
if columns = definition['columns']
vclass.import_columns(columns)
end

# 3. create or update sub-classes
res += import_all(vclass, definition)
# 4. create relations
# FIXME.....
# 3. create relations when all is done
if relations = definition['relations']
post_import << lambda do
vclass.import_relations(relations)
end
end

# 4. create or update sub-classes
res += import_all(vclass, definition, post_import)
res
end
end # class << self
Expand Down Expand Up @@ -181,17 +191,27 @@ def import_columns(columns)
column.ptype = definition['ptype']
column.index = definition['index']
column.save!
# if !column.errors.empty?
# errors = []
# column.errors.each_error do |er, msg|
# errors << "#{er} #{msg}"
# end
# if column.new_record?
# raise "Could not create property '#{name}': #{errors.join(', ')}"
# else
# raise"Could not update property '#{name}': #{errors.join(', ')}"
# end
# end
end
end

def import_relations(relations)
relations.each do |name, definition|
relation = secure(::Relation) { ::Relation.first(
:conditions => ['target_role = ? AND source_kpath = ? AND site_id = ?',
name, self.kpath, self.site_id
]
)}
if !relation
# create
relation = ::Relation.new(:target_role => name, :source_kpath => self.kpath)
end
Relation::EXPORT_FIELDS.each do |key|
value = definition[key]
if !value.blank?
relation[key] = value
end
end
relation.save!
end
end

Expand Down
23 changes: 12 additions & 11 deletions app/models/virtual_class.rb
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ def build_vclass_from_real_class(real_class)
vclass.real_class = real_class
vclass.include_role real_class.schema
vclass.instance_variable_set(:@is_real_class, true)
vclass.site_id = current_site.id
vclass
end

Expand All @@ -170,13 +171,6 @@ def load_roles_and_cache(vclass)
class << self
attr_accessor :caches_by_site

# Import a hash of virtual class definitions and try to build the virtual classes.
def import(data)
data.keys.map do |klass|
build_virtual_class(klass, data)
end
end

def [](name)
find_by_name(name)
end
Expand Down Expand Up @@ -286,6 +280,17 @@ def export
res[sub.name] = sub.export
end
end

relations = Relation.all(
:conditions => ['source_kpath = ? AND site_id = ?', kpath, site_id],
:order => 'target_role ASC'
)
if !relations.empty?
res['relations'] = list = Zafu::OrderedHash.new
relations.each do |rel|
list[rel.target_role] = rel.export
end
end
res
end

Expand Down Expand Up @@ -474,10 +479,6 @@ def real_class=(klass)
@real_class = klass
end

def import_result
@import_result || errors[:base]
end

# List all relations that can be set for this class, filtering by
# relation group.
def filtered_relations(group_filter)
Expand Down
2 changes: 1 addition & 1 deletion app/views/columns/_li.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
<span class='spacer'><%= (li.role.kind_of?(VirtualClass) ? '+ ' : '<span>* </span>') %></span>
<span class='constant'><%= li.role.name %></span>
<span class='text'>p.<%= li.ptype %></span>
<span class='string'>'<%= li.name %>'<span><%= li.import_result ? " (#{li.import_result})" : ''%><% if !li.index.blank? -%>, <span class='symbol'>:index</span> =&gt; <span class='symbol'>:<%= li.index_name %></span><% end -%>
<span class='string'>'<%= li.name %>'<span><% if !li.index.blank? -%>, <span class='symbol'>:index</span> =&gt; <span class='symbol'>:<%= li.index_name %></span><% end -%>
</td>
</tr>
8 changes: 0 additions & 8 deletions app/views/columns/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,3 @@
<%= render :partial=>'columns/li', :collection=>@columns %>
<%= render :partial=>'columns/add' %>
</table>

<div class='admin_group'><h3><%= _('import definitions') %></h3>

<%= form_tag({ :controller => 'columns', :action => 'import'}, {:multipart => true} ) %>
<input style='line-height:1.5em;' name="attachment" class='file' type="file" />
<p class="btn_validate"><input type="submit" value='<%= _('import') %>'/></p>
</form>
</div>
1 change: 0 additions & 1 deletion app/views/virtual_classes/import_prepare.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

<%= form_tag({ :controller => 'virtual_classes', :action => 'import'}) %>
<p><%= hidden_field_tag(:roles, @yaml) %></p>
<p><%#= check_box_tag(:delete_roles) %> <%= _('delete roles') %></p>
<p class="btn_validate">
<%= link_to(_('cancel'), :action => 'index')%> &nbsp;
<input type="submit" value='<%= _('apply') %>'/></p>
Expand Down
3 changes: 2 additions & 1 deletion lib/zena/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ def zen_routes
:import => :post,
:export => :get,
}
resources :columns, :collection => {:import => :post}

resources :columns

resources :sites,
:member => { :clear_cache => :post }
Expand Down
9 changes: 4 additions & 5 deletions test/unit/relation_proxy_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ def test_add_links_same_target_different_alias_syntax
assert node.update_attributes_with_transformation('rel_attributes' => {'reference_attributes' => {'other_id' => 33, 'date' => '2009-7-18 8:0'}})
assert node.update_attributes_with_transformation('rel_attributes' => {'reference_attributes' => {'other_id' => 33, 'date' => '2009-7-18 9:0'}})
end

subject do
secure!(Node) { nodes(:cleanWater) }
end
Expand All @@ -517,15 +517,15 @@ def test_add_links_same_target_different_alias_syntax
assert_difference('Link.count', -1) do
# remove 9:0
assert subject.update_attributes_with_transformation('rel_attributes' => {'reference_attributes' => {'other_id' => '', 'date' => '2009-7-18 9:0'}})
end
end

assert references = subject.find(:all, 'references')
assert_equal 2, references.size
assert_equal Time.gm(2009,7,17), references.first.l_date
assert_equal Time.gm(2009,7,18,8), references.last.l_date
end
end # with many dates for a given target

def test_attr_public
assert Node.safe_method_type(['l_status'])
assert Node.safe_method_type(['l_comment'])
Expand Down Expand Up @@ -554,5 +554,4 @@ def test_attr_public
assert_equal 100, subject.find(:first, 'reference where l_status = 100').l_status
end
end # With many links

end
18 changes: 18 additions & 0 deletions test/unit/relation_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -196,5 +196,23 @@ def test_set_site_id
relation.update_attributes(:site_id => 1234)
assert_equal original_site_id, relation.site_id
end


context 'Exporting a relation' do
subject do
relations(:node_has_tags)
end

should 'create a hash' do
assert_equal({
'rel_group' => 'doc.tags',
'source_kpath' => 'N',
'source_role' => 'tagged',
'target_kpath' => 'NPT',
'target_role' => 'set_tag',
'target_icon' => "<img src='/images/tag_blue.png' alt='tag'/>",
}, subject.export)
end
end # Exporting a relation

end

0 comments on commit b8c4011

Please sign in to comment.