What is the proper way to phrase this statement in Ruby? - ruby

I'm new at this, and I'm having trouble finding the proper way to phrase this in Ruby. And I don't know if the Ruby API in SketchUp is different. But, thats what I'm trying to use it for.
def self.initialize_job_info
return{
'salesperson' => ' = $pg_settings['salespersons'[['salesperson']['id']]] if ('on' = $pg_settings['salespersons'[['salesperson']['defsales']]])'
This is what I'm basically trying to do:
This part of the code works as it should
def self.initialize_job_info
return{
'salesperson' => ''
It sets an empty form's initial value of job_info['salesperson']'s value to ' ' if no pre-existing value is found.
So, there is a value I want to place in the Hash that is being passed from $pg_settings.
The value I want is, and I hope this make sense, the value of this specific 'id'
$pg_settings['salespersons'] {//which is a list of 'salesperson'
<salesperson> id="561" name="name" phone="phone number" defsales="on" email="email" </salesperson>
if (defsales == "on") then 'salesperson' => 'value="id"'
Does this make sense?
I'm pulling my hair out, so any help you can give on this would be great.

if those names not inside the quotes are variables that you want to get the values from it should probably be:
'salesperson' => " = $pg_settings[#{salespersons}[[#{salesperson}][#{id}]]] if (#{on} = $pg_settings[#{salespersons}[[#{salesperson}][#{defsales}]]])"
but as Geo said, more detail on the actual purpose/intent would help
BTW, that construc tis called string interpolation (http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Literals#Interpolation)

If you want to interpolate the strings, as in include their value in a string, then maybe this examples can help you:
a = "a string"
b = "this is"
c = "#{b} #{a}"
In the example above, c will have the value: this is a string . Also, while interpolating, valid Ruby code is accepted. So, this is ok too:
c = "#{ b.sub("this","") } #{a}"
And in this case, c will have the value is a string . So, if you need to interpolate something, first think about how you would do it using normal code, and then just add #{} around it.

I figured it out.
Here is the working code
def self.initialize_job_info
return{
'salesperson' => self.default,
}
end
def self .default
salespersons = $pg_settings['salespersons']
salespersons.each do |salesperson|
if (salesperson['defsales'] == 'on')
return salesperson['id']
end
end
end
Looks like I was a long way off.......lol

Related

Rails: Accessing a variable where the name of the variable was passed into the function as an argument

#string = "I love long strolls on the beach"
def keyword(string)
#keyword_array = ["ball","sand","spade"]
ball = ["red","green","blue"]
sand = ["beach","playbox","sea"]
spade = ["garden","beach","cards"]
#keyword_array.each do |item|
new_array = item
puts item # on the first loop for example this returns 'ball'
end
end
As you can see in the example above when I iterate through the first loop it returns the string ball (just using the first loop as an example, its the same on all loops) but I want to assign new_array with the value of ["red","green","blue"] from the ball array as I will be passing this array to a function.
So basically instead of assigning the ball array, it assigns the name of the array as a string.
I tried a ton of things including using #{item}, instance_variable_set but nothing works. I have a feeling I do not know the correct terminology for this example so I can't find the right answer.
I had a similar situation where I was passing the method name as a variable and I did this to fix it:
return method("#{name}").call
but that was for a def/method. How would I do it for a variable?
Go easy on me, new to rails :)
I think that what you are trying to accomplish can be done using eval, but be careful about how you use it since this can execute any code within that expression, so be sure you only use it on flows where you have full control (avoid the use of this when user input is part of the eval call).
a = 'pepe'
pepe = 'pepito'
p a
p eval a
The first put will print 'pepe', the second one will print 'pepito' (the value of the pepe variable), you can test that snippet here.
Hope this helps! 👍
Do the contents of #keyword_array have to be a string?
We can avoid doing tricky things like call or send if we just store the references to the arrays in #keyword_array.
#string = "I love long strolls on the beach"
def keyword(string)
ball = ["red","green","blue"]
sand = ["beach","playbox","sea"]
spade = ["garden","beach","cards"]
#keyword_array = [ball, sand, spade]
#keyword_array.each do |item|
new_array = item
puts item
end
end

Using variables for operator/methods

How do you access an operator/method via a variable?
So instead of this:
c = Computer.new
c.computer_name = "bla"
c.operating_system = "Windows XP"
c.user_name = "joesmith"
c.save
(plus many more)
I want to use a hash and assign the values dynamically:
c = Computer.new
params.each do |key,val|
c."#{key}" = val.to_s
end
c.save
Also, what is the correct terminology here?
I didn't try it, but Computer.new params should work.
Be careful of mass assignment though (it's not specific to DataMapper).
One trivial way (not DataMapper-specific, but assumes a prop_name= method), is to use send:
c.send("#{key}=".to_sym, val.to_s)

Why does Array.to_s return brackets?

For an array, when I type:
puts array[0]
==> text
Yet when I type
puts array[0].to_s
==> ["text"]
Why the brackets and quotes? What am I missing?
ADDENDUM: my code looks like this
page = open(url) {|f| f.read }
page_array = page.scan(/regex/) #pulls partial urls into an array
partial_url = page_array[0].to_s
full_url = base_url + partial_url #adds each partial url to a consistent base_url
puts full_url
what I'm getting looks like:
http://www.stackoverflow/["questions"]
This print the array as is without brackets
array.join(", ")
to_s is just an alias to inspect for the Array class.
Not that this means a lot other than instead of expecting array.to_s to return a string it's actually returning array.inspect which, based on the name of the method, isn't really what you are looking for.
If you want just the "guts" try:
page_array.join
If there are multiple elements to the array:
page_array.join(" ")
This will make:
page_array = ["test","this","function"]
return:
"test this function"
What "to_s" on an Array returns, depends on the version of Ruby you are using as mentioned above. 1.9.X returns:
"[\"test\"]"
You need to show us the regex to really fix this properly, but this will do it:
Replace this
partial_url = page_array[0].to_s
with this
partial_url = page_array[0][0]
This doesn't necessarily fix why you are getting a doubled-up array, but you can flatten it and then call the first element like this.
page_array = page.scan(/regex/).flatten
Flattening takes out stacked arrays and creates one level, so if you had [1,2,[3,[4,5,6]]] and called flatten on it, you would get [1,2,3,4,5,6]
It is also more robust than doing array[0][0], because, if you had more than two arrays nested in the first element, you would run into the same issue.
Iain is correct though, without seeing the regex, we can't suss out the root cause.

ruby - need help understanding this inject

I'd like to understand how the following code works:
def url
#url ||= {
"basename" => self.basename,
"output_ext" => self.output_ext,
}.inject("/:basename/") { |result, token|
result.gsub(/:#{token.first}/, token.last)
}.gsub(/\/\//, "/")
end
I know what it does; somehow it returns the url corresponding to a file located o a dir on a server. So it returns strings similar to this: /path/to/my/file.html
I understand that if #url already has a value, it will be returned and the right ||= will be discarded. I also understand that this begins creating a hash of two elements.
I also think I understand the last gsub; it replaces backslashes by slashes (to cope with windows servers, I guess).
What amazes me is the inject part. I'm not able to understand it. I have used inject before, but this one is too much for me. I don't see how this be done with an each, since I don't understand what it does.
I modified the original function slightly for this question; the original comes from this jekyll file.
Cheers!
foo.inject(bar) {|result, x| f(result,x) }
Can always be written as:
result = bar
foo.each {|x| result = f(result, x)}
result
So for your case, the version with each would look like this:
result = "/:basename/"
{
"basename" => self.basename,
"output_ext" => self.output_ext,
}.each {|token|
result = result.gsub(/:#{token.first}/, token.last)
}
result
Meaning: for all key-value-pairs in the hash, each occurrence of the key in the "/:basename/" is replaced with the value.
Perhaps splitting the code and tweaking a little helps
options = { "basename" => self.basename, "output_ext" => self.output_ext }
options.inject("/:basename") do |result, key_and_kalue|
# Iterating over the hash yields an array of two elements, which I called key_and_value
result.gsub(":#{key_and_value[0]}", key_and_value[1])
end.gsub!(//\/\/, '/')
Basically, the inject code is iterating over all your options and replacing for the actual value wherever it sees a ":key"

can you define a block inline with ruby?

Is it possible to define a block in an inline statement with ruby? Something like this:
tasks.collect(&:title).to_block{|arr| "#{arr.slice(0, arr.length - 1).join(", ")} and #{arr.last}" }
Instead of this:
titles = tasks.collect(&:title)
"#{titles.slice(0, titles.length - 1).join(", ")} and #{titles.last}"
If you said tasks.collect(&:title).slice(0, this.length-1) how can you make 'this' refer to the full array that was passed to slice()?
Basically I'm just looking for a way to pass the object returned from one statement into another one, not necessarily iterating over it.
You're kind of confusing passing a return value to a method/function and calling a method on the returned value. The way to do what you described is this:
lambda {|arr| "#{arr.slice(0, arr.length - 1).join(", ")} and #{arr.last}"}.call(tasks.collect(&:title))
If you want to do it the way you were attempting, the closest match is instance_eval, which lets you run a block within the context of an object. So that would be:
tasks.collect(&:title).instance_eval {"#{slice(0, length - 1).join(", ")} and #{last}"}
However, I would not do either of those, as it's longer and less readable than the alternative.
I'm not sure exactly what you're trying to do, but:
If you said tasks.collect(&:title).slice(0, this.length-1) how can you make 'this' refer to the full array that was passed to slice()?
Use a negative number:
tasks.collect(&:title)[0..-2]
Also, in:
"#{titles.slice(0, titles.length - 1).join(", ")} and #{titles.last}"
you've got something weird going on with your quotes, I think.
I don't really understand why you would want to, but you could add a function to the ruby classes that takes a block, and passes itself as a parameter...
class Object
def to_block
yield self
end
end
At this point you would be able to call:
tasks.collect(&:title).to_block{|it| it.slice(0, it.length-1)}
Of course, modifying the Object class should not be taken lightly as there can be serious consequences when combining with other libraries.
Although there are many good answers here, perhaps you're looking for something more like this in terms of an objective:
class Array
def andjoin(separator = ', ', word = ' and ')
case (length)
when 0
''
when 1
last.to_s
when 2
join(word)
else
slice(0, length - 1).join(separator) + word + last.to_s
end
end
end
puts %w[ think feel enjoy ].andjoin # => "think, feel and enjoy"
puts %w[ mitchell webb ].andjoin # => "mitchell and webb"
puts %w[ yes ].andjoin # => "yes"
puts %w[ happy fun monkeypatch ].andjoin(', ', ', and ') # => "happy, fun, and monkeypatch"

Resources