tlinder Posted July 26, 2022 Share Posted July 26, 2022 I'm trying to run a .rb file that's on my local in CA by using a marco. Right now I can only get it to read the file. Does anyone have any insight on how I might be able to to this or where I need to look? Macro: In CA File.read("C:/Users - Desktop/scope1.rb") Output: from text stored on a local drive rafter_length = (length.to_f.round / 12) + 1 convert_to_int = rafter_length.even? case when convert_to_int == true resut = rafter_length when convert_to_int == false result = rafter_length +1 end Link to comment Share on other sites More sharing options...
Joe_Carrick Posted July 26, 2022 Share Posted July 26, 2022 You should just make this an evaluated macro in chief, context: owner rafter_length = (length.to_f.round / 12) + 1 convert_to_int = rafter_length.even? case when convert_to_int == true result = rafter_length when convert_to_int == false result = rafter_length +1 end Using an rb in this case is superfluous. IAE, to use one you would need to "require" it in your chief macro and then call any specific "defined" function within that rb file. The only reason for using an rb file is for utility functions that aren't otherwise available that you would need in many different user macros. This one is object specific to any object that has a "length" attribute. Link to comment Share on other sites More sharing options...
tlinder Posted July 26, 2022 Author Share Posted July 26, 2022 3 minutes ago, Joe_Carrick said: You should just make this an evaluated macro in chief, context: owner rafter_length = (length.to_f.round / 12) + 1 convert_to_int = rafter_length.even? case when convert_to_int == true result = rafter_length when convert_to_int == false result = rafter_length +1 end Using an rb in this case is superfluous. IAE, to use one you would need to "require" it in your chief macro and then call the "defined" function within that rb file. Thanks Joe The macro works in evaluated, just trying to take it one step further and save the company a lot of time. I'm am trying to read it from my local so I don't have to open every CA file and update them 1 by 1. We have hundreds of files. Link to comment Share on other sites More sharing options...
Joe_Carrick Posted July 26, 2022 Share Posted July 26, 2022 9 minutes ago, tlinder said: Thanks Joe The macro works in evaluated, just trying to take it one step further and save the company a lot of time. I'm am trying to read it from my local so I don't have to open every CA file and update them 1 by 1. We have hundreds of files. You don't read the rb file. You "require" it. Within that file you need to define the function"int_length"and then in your macro you call the function. ie: result = int_length(length) Link to comment Share on other sites More sharing options...
Joe_Carrick Posted July 26, 2022 Share Posted July 26, 2022 Here's a sample rb file that has a series of defined methods. Note that I no longer use this since it's problematical to update with each new version of chief. #================================================= # Joe's Macro Subscription Service # Ruby script: Float Class # Copyright October 1, 2015 by Joseph P. Carrick #================================================= # The contents of this Ruby Macro is not to be # revealed to any other Chief Architect user or # employee. If a violation of this requirement # is found, the offending subscriber's # subscription will be immediately terminated. #================================================= # Place this file in Chief Architect/Data/Scripts # folder. Then place the following: # require "Float Class.rb" # at the beginning of any macro where you want to # use these methods #================================================= class Float #================================================================= # Display a numerical value formatted according the the current # units of the Plan. Requires $Units to be either "Imperial" or # "Metric" to recognize the units. #================================================================= def format_number(n) if $Units.nil? result = self.sig(3) elsif $Units == "Imperial" result = self.ftin(32) elsif $Units == "Metric" result = self.meters(n) else nvalue = self.sig(3) end return result end #================================================================= # Display a value (decimal inches) formatted as a text string # syntax: nvalue.ftin(denominator) # example: n = 64.125 # s = n.ftin(8) -> 5'-4 1/8" #================================================================= def ftin(denominator) if $Units.nil? nvalue = self elsif $Units == "Imperial" nvalue = self elsif $Units == "Metric" nvalue = self/2.54 else nvalue = self end arr = self.divmod(12) if arr[1] >= 11.96875 arr[0] = arr[0]+1 arr[1] = 0.00 end inch_frac = ((arr[1]-arr[1].floor)*denominator).round.quo(denominator) if arr[0].floor < 1 if inch_frac == 1.0 result = "#{arr[1].ceil}"+'"' elsif inch_frac == 0.0 result = "#{arr[1].floor}"+'"' elsif inch_frac < 1 and arr[1].floor > 0 result = "#{arr[1].floor} #{inch_frac}"+'"' elsif inch_frac < 1 result = "#{inch_frac}"+'"' else result = "#{arr[1].floor} #{inch_frac}"+'"' end else if inch_frac == 1.0 result = "#{arr[0]}'-#{arr[1].ceil}"+'"' elsif inch_frac == 0.0 result = "#{arr[0]}'-#{arr[1].floor}"+'"' else result = "#{arr[0].floor}'-#{arr[1].floor} #{inch_frac}"+'"' end end return result end #======================================= # Convert Float to Feet # rounded to nearest foot #======================================= def feet feet = (self/12).round(0).to_s result = feet +"'-0" return result+'"' end #======================================= # Convert Float to Decimal Feet # rounded to 3 decimal places #======================================= def decimal_feet feet = (self/12).round(3).to_s + "'" return feet end #======================================= # Convert Float to Inches-Fractions # Formats are: # 1/16" # 1 1/16" # 1" # nDivisor can be any integer between # 1 and 32. Most common are: # 1,2,4,8,16 & 32 #======================================= def inches(nDivisor) inches = self.floor if inches > 0.00 frac = (self.remainder(inches)*nDivisor).round.quo(nDivisor) else frac = (self * nDivisor).round.quo(nDivisor) end if frac == 1 result = "#{inches + 1}" elsif frac == 0 result = "#{inches}" else result = "#{inches} #{frac}" end return result.gsub(" ","-")+'"' end #================================================================= # Get the SqRt of a number to n significant places #================================================================= def sqrt(n) a = self x = 1.00000 while (x*x) < a x = x+0.00001 end return x.round(n) end #================================================================= # Display a decimal value as a text string to (n) significant places # syntax: nvalue.sig(n) # example: x = 65.375 # s = x.sig(4) -> '65.3750' # example: x = 65.25 # s = x.sig(3) -> '65.250' #================================================================= def sig(n) nPad = self.round().to_s.length + n + 1 result = self.round(n).to_s.ljust(nPad,"0") return result end #================================================================= # Convert millimeters to meters & display to (n) significant places # syntax: nvalue.meters(n) # example: x = 6543 # s = x.meters(3) -> '65.430 m' # example: x = 650 # s = x.meters(3) -> '6.500 m' #================================================================= def meters(n) if $Units.nil? nvalue = self elsif $Units == "Imperial" nvalue = self*2.54 elsif $Units == "Metric" nvalue = self else nvalue = self end if n > 3 n = 3 elsif n < 0 n = 0 end m = nvalue/100 result = m.sig(n).to_s + " m" return result end end 1 Link to comment Share on other sites More sharing options...
SHCanada2 Posted July 26, 2022 Share Posted July 26, 2022 40 minutes ago, tlinder said: I'm am trying to read it from my local so I don't have to open every CA file and update them 1 by 1. We have hundreds of files. wouldn't you have to open every file anyway to actually use the new functions you wish to define in the .rb file? Link to comment Share on other sites More sharing options...
tlinder Posted July 26, 2022 Author Share Posted July 26, 2022 Quote Here's a sample rb file that has a series of defined methods. Note that I no longer use this since it's problematical to update with each new version of chief. Thank you Joe I will do some more research I this. I appreciate all your help! Link to comment Share on other sites More sharing options...
tlinder Posted July 26, 2022 Author Share Posted July 26, 2022 1 hour ago, jasonn1234 said: wouldn't you have to open every file anyway to actually use the new functions you wish to define in the .rb file? Initially yes, but for future updates I can just change the macro on the .rb file and it automatically updates the file when they are opened. Link to comment Share on other sites More sharing options...
Solution Alaskan_Son Posted July 26, 2022 Solution Share Posted July 26, 2022 I would suggest making a handful of changes to your current approach: Add your desired folder to the $LOAD_PATH OR place the desired file inside your currently defined $LOAD_PATH. This way you can just use a file name instead of having to use the whole folder structure. Define a method inside your rb file Use require as Joe already mentioned instead of using File.read Call your defined method inside your Chief macro. All said and done, it would look more like this (using your originally supplied example): Macro: In CA require 'scope1' my_method Output: from text stored on a local drive def my_method rafter_length = (length.to_f.round / 12) + 1 convert_to_int = rafter_length.even? case when convert_to_int == true resut = rafter_length when convert_to_int == false result = rafter_length +1 end end NOTE: There are other potential approaches and corrections that could be made as well, but I wanted to stay as close as reasonably possible to your original attempt. Link to comment Share on other sites More sharing options...
Joe_Carrick Posted July 26, 2022 Share Posted July 26, 2022 I think there's a bit more that needs to be done to make it work correctly: Macro: In CA require 'scope1' my_method(length) Output: from text stored on a local drive def my_method(x) rafter_length = (self.to_f.round / 12) + 1 convert_to_int = rafter_length.even? case when convert_to_int == true result = rafter_length when convert_to_int == false result = rafter_length +1 end end Unless I'm wrong, the parmeter length needs to be passed to my_method in order for the method to know what's being analyzed. Link to comment Share on other sites More sharing options...
tlinder Posted July 26, 2022 Author Share Posted July 26, 2022 3 hours ago, solver said: rafter_length = (length.to_f.round / 12) + 1 rafter_length.even? ? rafter_length : rafter_length + 1 Thank you for the easier format and the YouTube videos. You gained yourself a new subscriber! Quote Are you looking for standard lumber lengths? Yes I'm just trying to have the standard lumber lengths populate in the rafter labels. Link to comment Share on other sites More sharing options...
tlinder Posted July 26, 2022 Author Share Posted July 26, 2022 14 minutes ago, Joe_Carrick said: Macro: In CA require 'scope1' my_method(length) Output: from text stored on a local drive def my_method(x) rafter_length = (self.to_f.round / 12) + 1 convert_to_int = rafter_length.even? case when convert_to_int == true result = rafter_length when convert_to_int == false result = rafter_length +1 end end Joe and Michael I tried both of those approaches and I wasn't able to get the right output in Chief. Link to comment Share on other sites More sharing options...
Alaskan_Son Posted July 26, 2022 Share Posted July 26, 2022 Just now, tlinder said: Joe and Michael I tried both of those approaches and I wasn't able to get the right output in Chief. Did you set the macro to Evaluated:Owner? And did you move your script to a folder in the $LOAD_PATH or adjust the $LOAD_PATH to add your desired folder? Link to comment Share on other sites More sharing options...
tlinder Posted July 26, 2022 Author Share Posted July 26, 2022 5 minutes ago, Alaskan_Son said: Did you set the macro to Evaluated:Owner? And did you move your script to a folder in the $LOAD_PATH or adjust the $LOAD_PATH to add your desired folder? Are you saying to create a folder and name it $LOAD_PATH? I'm not sure what you mean. Link to comment Share on other sites More sharing options...
tlinder Posted July 26, 2022 Author Share Posted July 26, 2022 2 minutes ago, solver said: What did you get? Evaluation Error: Ruby SecurityError: Insecure operation - require Stack Trace: from (eval):2:in `block (3 levels) in <main>' from (eval):1:in `instance_eval' from (eval):1:in `block (2 levels) in <main>' from eval:9:in `eval' from eval:9:in `block (2 levels) in <main>' from eval:3:in `loop' from eval:3:in `block in <main>' Link to comment Share on other sites More sharing options...
Joe_Carrick Posted July 26, 2022 Share Posted July 26, 2022 You probably need to set the Ruby Safe Level to 1. CA by default sets it at 2 which doesn't allow some things to work. Link to comment Share on other sites More sharing options...
Alaskan_Son Posted July 26, 2022 Share Posted July 26, 2022 33 minutes ago, Joe_Carrick said: Unless I'm wrong, the parmeter length needs to be passed to my_method in order for the method to know what's being analyzed. 1 minute ago, Joe_Carrick said: You probably need to set the Ruby Safe Level to 1. CA by default sets it at 2 which doesn't allow some things to work. Neither of these things are true. You can indeed define and call a method with no arguments, and if the file is a valid rb file located within the $LOAD_PATH, you can even have a Safe Level of 4 and it should still work. Link to comment Share on other sites More sharing options...
Joe_Carrick Posted July 26, 2022 Share Posted July 26, 2022 8 minutes ago, Alaskan_Son said: Neither of these things are true. You can indeed define and call a method with no arguments, and if the file is a valid rb file located within the $LOAD_PATH, you can even have a Safe Level of 4 and it should still work. Agreed- except that AFAIK, Chief's default Safe Level has always been 2 I do have some macros that create, read and write files. Some of those require a Safe Level of "0". Link to comment Share on other sites More sharing options...
Joe_Carrick Posted July 26, 2022 Share Posted July 26, 2022 For rb files that you wish to use in multiple versions of Chief you will need to make sure you copy them to the current version's $LOAD_PATH. -or- put them in a common file and edit the $LOAD_PATH in the current version of Chief. I'm pretty sure you can have multiple paths separated by simi-colons Link to comment Share on other sites More sharing options...
SHCanada2 Posted July 26, 2022 Share Posted July 26, 2022 If I remember correctly, i think I tested the load path about 12 months ago and could not get it to work. Instead If I remember correctly, I put a function in the "tutorial.rb" file and it worked. Although tutorial.rb is distributed by CA so it will be overwritten on installation, probably ok for testing but not long term Link to comment Share on other sites More sharing options...
Alaskan_Son Posted July 26, 2022 Share Posted July 26, 2022 There's no good reason to be placing code into the tutorial.rb file in my opinion. Its just a messy and confusing kludge. All you're actually doing by placing code in the tutorial file is bypassing the require line because Chief is pre-programmed to automatically load that tutorial.rb file. You can easily replace the functionality by just using require in a text macro of your own though so you don't have to fool around with defining your methods in the tutorial file. Just create and display that macro somewhere in your template plan and all the methods defined inside your appropriately required rb files will be loaded into global memory just as if you had placed them in the tutorial file. Or require the desired rb file(s) inside specific macros. Either way, just load them yourself (using require) instead of using the tutorial file workaround. Link to comment Share on other sites More sharing options...
Joe_Carrick Posted July 27, 2022 Share Posted July 27, 2022 5 hours ago, jasonn1234 said: Although tutorial.rb is distributed by CA so it will be overwritten on installation, probably ok for testing but not long term Yep, every time there's an update or new version. That's why it's not a good idea. Link to comment Share on other sites More sharing options...
tlinder Posted July 27, 2022 Author Share Posted July 27, 2022 Thank you for the YouTube video Eric. Is there a way to define a new $LOAD_PATH to a different drive. I ask this because, I'm not the only one that is going to be opening these files. To my knowledge they all need to be "required" from the same file path. Link to comment Share on other sites More sharing options...
tlinder Posted July 27, 2022 Author Share Posted July 27, 2022 54 minutes ago, solver said: I still do not understand what you are trying to accomplish -- big picture, not how to run ruby from outside a Chief file. If you could explain, you would probably get better help. My overall goal is to create a macro in Chief to require a .rb file that is stored from a folder on a shared drive. I don't want to put it in my scripts folder that is connected to Chief because that drive (C: drive) is not shared. Instead IT is creating a new drive (Z: drive) for us, so everyone will have the same file path. There are many computers that will be opening the files in Chief. I need to be specific with my file path and it needs to point to the Z: drive I hope this helps. For ex: C: drive - not shared - where Chief is currently installed Z: drive - IT created - shared - this is where I want to store my scope1.rb - same file paths on every computer Link to comment Share on other sites More sharing options...
tlinder Posted July 27, 2022 Author Share Posted July 27, 2022 21 minutes ago, solver said: Why do you want to do this rather than placing the same code in the plan file? We have over 200 template files. If I placed them in every file and that macro changes, I would have to update every macro in every file manually. I'm trying to prevent re-entry. Link to comment Share on other sites More sharing options...
Recommended Posts
Please sign in to comment
You will be able to leave a comment after signing in
Sign In Now