Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 805087
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 15, 20262026-05-15T00:01:35+00:00 2026-05-15T00:01:35+00:00

require ‘sketchup’ entities = Sketchup.active_model.entities summa = Hash.new for face in entities next unless

  • 0
require 'sketchup'

entities = Sketchup.active_model.entities
summa = Hash.new

for face in entities
  next unless face.kind_of? Sketchup::Face
  if (face.material)
    summa[face.material.display_name] += face.area
  end
end

I’m trying to get the structure in the array as such:

summa { "Bricks" => 500, "Planks" => 4000 }

By the way, I’m making a ruby script for Google Sketchup

But if I run this code I only get

Error: #<NoMethodError: undefined method `+' for nil:NilClass>
C:\Program Files (x86)\Google\Google SketchUp 7\Plugins\test.rb:17
C:\Program Files (x86)\Google\Google SketchUp 7\Plugins\test.rb:14:in `each'
C:\Program Files (x86)\Google\Google SketchUp 7\Plugins\test.rb:14
C:\Program Files (x86)\Google\Google SketchUp 7\Plugins\test.rb:8:in `call'

As I’m used to using PHP and just doing $array['myownassoc'] += bignumber;
But I guess this isn’t the right approach when using Ruby?

So any help in how I need to go would be nice.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-15T00:01:35+00:00Added an answer on May 15, 2026 at 12:01 am

    The problem is this:

    summa[face.material.display_name] += face.area
    

    This is (roughly) equivalent to

    summa[face.material.display_name] = summa[face.material.display_name] + face.area
    

    However, you start out with summa as an empty hash:

    summa = Hash.new
    

    Which means that whenever you encounter a specific material for the first time (and obviously, this is going to be already the case in the very first iteration of the loop), summa[face.material.display_name] simply doesn’t exist. So, you are trying to add a number to something that doesn’t exist, which obviously cannot work.

    The quick fix would be to just initialize the hash with a default value, so that it returns something useful instead of nil for a non-existing key:

    summa = Hash.new(0)
    

    There are, however, a lot of other improvements that could be made to the code. Here’s how I would do it:

    require 'sketchup'
    
    Sketchup.active_model.entities.grep(Sketchup::Face).select(&:material).
    reduce(Hash.new(0)) {|h, face|
      h.tap {|h| h[face.material.display_name] += face.area }
    }
    

    I find that much easier to read, instead of “loop over this, but skip one iteration if that thing happens, and also don’t do this if that happens”.

    This is actually a common pattern, that pretty much every Rubyist has already written a dozen times, so I actually had a code snippet lying around that I only needed to slightly adapt. However, I am going to show you how I could have refactored your original code step-by-step if I hadn’t already had the solution.

    First, let’s start with coding style. I know it’s boring, but it is important. What the actual coding style is, is not important, the important thing is that the code is consistent, which means that one piece of code should look the same as any other piece of code. In this particular instance, you are asking the Ruby community to provide you with unpaid support, so it is polite to at least format the code in a style that members of that community are used to. This means standard Ruby coding style: 2 spaces for indentation, snake_case for method and variable names, CamelCase for constants which refer to modules or classes, ALL_CAPS for constants, and so on. Don’t use parentheses unless they clear up the precedence.

    In your code, for example, you use sometimes 3 spaces, sometimes 4 spaces, sometimes 5 spaces and sometimes 6 spaces for indentation, and all of that in just 9 non-empty lines of code! Your coding style is not only inconsistent with the rest of the community, it isn’t even consistent with its own next line!

    Let’s fix that first:

    require 'sketchup'
    entities = Sketchup.active_model.entities
    summa = {}
    
    for face in entities
      next unless face.kind_of? Sketchup::Face
      if face.material
        summa[face.material.display_name] += face.area
      end
    end
    

    Ah, much better.

    As I already mentioned, the first thing we need to do, is fix the obvious problem: replace summa = {} (which BTW would be the idiomatic way to write it) with summa = Hash.new(0). Now, the code at least works.

    As a next step, I would switch the assignment of the two local variables: first you assign entities, then you assign summa, then you do something with entities and you have to look three lines up to figure out what entities was. If you switch the two, the usage and the assignment of entities are right next to each other.

    As a result, we see that entities is assigned, then immediately used and then never used again. I don’t think this improves readability much, so we can get rid of it altogether:

    for face in Sketchup.active_model.entities
    

    Next comes the for loop. Those are highly un-idiomatic in Ruby; Rubyists strongly prefer internal iterators. So, let’s switch to one:

    Sketchup.active_model.entities.each {|face|
      next unless face.kind_of? Sketchup::Face
      if face.material
        summa[face.material.display_name] += face.area
      end
    }
    

    One advantage this has, is that now face is local to the body of the loop, whereas before, it was leaking out into the surrounding scope. (In Ruby, only module bodies, class bodies, method bodies, block bodies and script bodies have their own scope; for and while loop bodies as well as if/unless/case expressions don’t.)

    Let’s get on to the body of the loop.

    The first line is a guard clause. That’s good, I like guard clauses 🙂

    The second line is, well, if face.material is true-ish, it does something otherwise it does nothing, which means the loop is over. So, it’s another guard clause! However, it is written in a totally different style than the first guard clause, directly one line above it! Again, consistency is important:

    Sketchup.active_model.entities.each {|face|
      next unless face.kind_of? Sketchup::Face
      next unless face.material
      summa[face.material.display_name] += face.area
    }
    

    Now we have two guard clauses right next to each other. Let’s simplify the logic:

    Sketchup.active_model.entities.each {|face|
      next unless face.kind_of? Sketchup::Face && face.material
      summa[face.material.display_name] += face.area
    }
    

    But now there is only one single guard clause guarding only one single expression. So, we can just make the whole expression itself conditional:

    Sketchup.active_model.entities.each {|face|
      summa[face.material.display_name] += face.area if
        face.kind_of? Sketchup::Face && face.material
    }
    

    However, that’s still kind of ugly: we are looping over some collection, and then inside the loop we skip over all the items we don’t want to loop over. So, if we don’t want to loop over them, we do we loop over them in the first place? We don’t we just select the “interesting” items first and then loop over just them?

    Sketchup.active_model.entities.select {|e|
      e.kind_of? Sketchup::Face && e.material
    }.each {|face|
      summa[face.material.display_name] += face.area
    }
    

    We can do some simplification on this. If we realize that o.kind_of? C is the same as C === o, then we can use the grep filter which uses === to pattern match, instead of select:

    Sketchup.active_model.entities.grep(Sketchup::Face).select {|e| e.material
    }.each { … }
    

    Our select filter can further be simplified by using Symbol#to_proc:

    Sketchup.active_model.entities.grep(Sketchup::Face).select(&:material).each { … }
    

    Now let’s get back to the loop. Anybody who has some experience in a higher-order language such as Ruby, JavaScript, Python, C++ STL, C#, Visual Basic.NET, Smalltalk, Lisp, Scheme, Clojure, Haskell, Erlang, F#, Scala, … basically any modern language at all, will immediately recognize this pattern as a catamorphism, reduce, fold, inject:into:, inject or whatever your language of choice happens to call it.

    What a reduce does, is basically it “reduces” several things into just one thing. The most obvious example is the sum of a list of numbers: it reduces several numbers into just one number:

    [4, 8, 15, 16, 23, 42].reduce(0) {|accumulator, number| accumulator += number }
    

    [Note: in idiomatic Ruby, this would be written just as [4, 8, 15, 16, 23, 42].reduce(:+).]

    One way to spot a reduce lurking behind a loop is to look for the following pattern:

    accumulator = something # create an accumulator before the loop
    
    collection.each {|element|
      # do something with the accumulator
    }
    
    # now, accumulator contains the result of what we were looking for
    

    In this case, the accumulator is the summa hash.

    Sketchup.active_model.entities.grep(Sketchup::Face).select(&:material).
    reduce(Hash.new(0)) {|h, face|
      h[face.material.display_name] += face.area
      h
    }
    

    Last but not least, I don’t like this explicit returning of h at the end of block. We could obviously write it on the same line:

    h[face.material.display_name] += face.area; h
    

    But I prefer the use of Object#tap (aka the K-combinator) instead:

    Sketchup.active_model.entities.grep(Sketchup::Face).select(&:material).
    reduce(Hash.new(0)) {|h, face|
      h.tap {|h| h[face.material.display_name] += face.area }
    }
    

    And, that’s it!

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

require 'rubygems' require 'mechanize' rational = Mechanize.new { |agent| agent.user_agent_alias = 'Windows Mozilla' }
require(twitteroauth/twitteroauth.php); session_start(); //Site Account $siteauth = new TwitterOAuth('{Consumer key}', '{Consumer secret}', '{Access token}', '{Access
require 'ruby2ruby' require 'parsetree' code = puts(var) sexp = SexpProcessor.new.process(ParseTree.translate(code)) # => s(:fcall, :puts,
require 'rubygems' require 'mechanize' agent = Mechanize.new page = agent.get(http://google.com/) This simple script works
require 'mechanize' agent = Mechanize.new login = agent.get('http://www.schoolnet.ch/DE/HomeDE.htm') agent.click login.link_with text: /Login/ And I
require 'facebook.php'; $app_id =11111111111111111; $app_secret = 11111111111111111111111111; $facebook = new facebook(array( 'appId' => $app_id,
I require to create new tables for every client that signs up for my
require 'watir' ie = Watir::Browser.new ie.goto http://www.wallpapers.com/windows/Wallpapers/Animals/Dogs ie.select(:id, ctl00_CPH1_ctl00_ddlSortExpression).flash ie.select(:id, ctl00_CPH1_ctl00_ddlSortExpression).set(Newest) C:/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-3.0.0/lib/watir-classic/element.rb:433:in `method_missing': undefined
require savon client = Savon::Client.new http://www.brenda-enzymes.org/soap2/brenda.wsdl response = client.request (:get_km_value) do |soap| soap.body =
require 'test_helper' class MyTest < ActionController::IntegrationTest test view posts from login page do visit(/logins/new)

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.