Delete a definition from the definition list with its name

Hello everyone :sun_with_face:

I want to delete some definitions from the definition list using their name.

The “purge_unused” method is not suitable because it removes all unused components.

I want to assign only the components offered by Click-Kitchen 2.

Is there a solution?

Thank you

From the Ruby API documentation for DefinitionList:

#remove(definition) ⇒ Boolean

The #remove method is used to remove a component definition from the definition list with the given component definition. This will remove all instances of the definition.

Note that you have to retrieve the Definition object first so you can pass it to this method. As usual, beware of using this method in a loop over the DefinitionList, as you risk errors whenever you modify a collection while iterating over its contents.

David go back and review your threads from last November…

you where given lots of code to do exactly what your requesting…

maybe you’ll understand it better now…

john

Deleting a definition from the list of definitions was never discussed in my topics.

If I’m wrong, tell me what topic?

Only some members tried to help me by posting codes that relate to my research.

Thanks to them, I can finally develop alone more complex projects in Ruby.

this thread of yours has all the code needed…

john

Sorry but your example does not meet the demand I’m making today.

Your example uses “Purge Unused

[defs, lays, mats].each{|a| a.purge_unused}

as I said, back then, you can comment that line out…

# [defs, lays, mats].each{|a| a.purge_unused}

john

Yes but how ?

Can you give an example to delete the definition “TOTO”, without purging all the unused definitions?

Remember that defn.remove is available only >= v2018, so it’s limiting for your user-base…
To delete a particular definition in all versions you can use defn.entities.clear!
To find a definition ‘by name’ use:
defn=model.definitions['some_name']
or some similar methods to get a matching definition…
The ...entities.clear! method works within a model.start_operation... up to model.commit_operation block...
Otherwise it is done cleanly.

1 Like

Thank you for the info!

That’s what I want to do and not delete an entity.

So there is no solution for SketchUp versions until 2018?

Reread what I wrote.
There IS a way !
Just use definition.entities.clear! inside a start...commit block…
This is basic stuff.

2 Likes

I took the time to follow your TIG tips and this example seems to work:

model = Sketchup.active_model
defn = model.definitions
model.start_operation('delete', true)
defn.each do |d|
  if d.name == "TOTO"
    d.entities.clear!
  end
end
model.commit_operation

Thank you

At the moment your code looks at every definition and clears the entities of one with a name match.
You could streamline it…
If you used something like:
match=defn['TOTO']
then
match.entiites.clear! if match

Also you don’t need to set up a separate start...commit block IF your larger code has already started an operation, then simply use that…

Here is a small example that now allows me to purge the components of Click-Cuisine 2, with a dynamic attribute.

There may be simpler methods to do the same thing!

If you have ideas do not hesitate to post your codes. :wink:

  mod = Sketchup.active_model
  defs = mod.definitions

  # create an array of all the definitions with the clc2 attribute.
  defs_lst = [] 
  mod.definitions.each do |d|
    attribut = d.get_attribute 'dynamic_attributes','clc2'
    unless attribut.nil?
      defs_lst << d
    end
  end
  
  # create an array of entities with the clc2 attribute.
  defs_mod = [] 
  mod.entities.each do |e|
    attribut = e.get_attribute 'dynamic_attributes','clc2' 
    unless attribut.nil?    
      defs_mod << e.definition
    end
  end    
  
  # subtraction to keep only unused clc2 definitions.
  defs_notused = defs_lst - defs_mod

  # delete all unused entities and definitions clc2.
  mod.start_operation('defs_purge', true)
  defs_notused.each do |defpurg|
    defs.each do |d|
      if d == defpurg
        d.entities.clear!
      end
    end
  end
  mod.commit_operation

Even better !

The example below purges the components present in the list “b”, if they are not used and takes into account all the nesting levels:

def defs_in_model_sketchup(ents, defs_mod)
  ents.grep(Sketchup::ComponentInstance).each do |e|
    defs_mod << e.definition.name
    defs_in_model_sketchup(e.definition.entities, defs_mod)
  end
end

  defs_mod = []
  mod = Sketchup.active_model
  ent = mod.entities
  defs_in_model_sketchup(ent, defs_mod)

  defs = mod.definitions 
   
  defs_lst = [] 
  mod.definitions.each{ |d| defs_lst << d.name }
  
  defs_notused = defs_lst - defs_mod
  
  defs_purge = []
  defs_notused.each do |a|
    ['BOUTEIL','BOX','DECO','BOOK','SALADIER'].each do |b|
      if a.include?(b)
        defs_purge << a 
      end
    end
  end

  mod.start_operation('defs_purge', true)
  defs_purge.each do |defpurg|
    defs.each do |d|
      if d.name == defpurg
        d.entities.clear!
      end
    end
  end
  mod.commit_operation  

if and unless can be used in “modifier posiition” at the end of a statement.
This helps make code more readable (and have less lines and less nested blocks)
when it is a simple statement …

    defs_purge << a if a.include?(b)

… or …

    defs_mod << e.definition unless attribut.nil?    

Good comment Dan
Each line in less is a victory for the one who likes to code.:stuck_out_tongue_winking_eye:

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.