Accessing symbols within strings in Ruby - ruby

Newbie to Ruby here and I'm trying to figure something out. I've got a situation where I have something like the following:
sql = q%{select foo from bar where var1 = :ugh and var2 = :moreugh}
Now, I can print out variable "sql", but if I just use puts and #{sql} it shows the symbols as above, ":ugh".
I'd like to be able to print out string sql with the values of the symbols displayed rather than the names of the symbols.
Any pointers out there? Many thanks!

your example-code is broken, i assume you want to do a single-quoted-string %q{...}
and that is exactly what you get: one string. so there are no symbols in there, it's just ONE string. similar to '...'

I think, assuming you are using symbols instead of string, You can use following query:
sql = "select foo from bar where var1 = 'ugh' and var2 = 'moreugh'"
So using puts or #{sql} will give you correct output.
Comment in case this doesn't meet your requirement.

You probably want this:
sql = "select foo from bar where var1 = '#{ugh}' and var2 = '#{moreugh}"'
where ugh and moreugh are variables. But, you should do it that way, your system would be open to SQL Injection. Use bind variables in your DB engine instead.

You have two errors. You need to use %Q to enable interpolation, and variables are included in the string in the form #{:ugh}. So, you want:
sql = %Q{select foo from bar where var1 = #{ugh} and var2 = #{moreugh}}
puts sql
But please, please, please don't do this, even just for a small project. You are setting yourself up for a SQL injection attacj.

Related

Using one variable for multiple items data in descriptive programming

I know that with Descriptive programming you can do something like this:
Browser("StackOverflow").Page("StackOverflow").Link("text:=Go To Next Page ", "html tag:=A").Click
But is it possible to create some kind of string so I can assign more than one data value and pass it as single variable? I've tried many combinations using escape characters and I always get error.
For example in the case above, let's say I have more properties in the Page object, so I'd normally have to do something like this:
Browser("StackOverflow").Page("name:=StackOverflow", "html id:=PageID")...etc...
But I'd like to pass "name:=StackOverflow", "html id:=PageID" as a single variable, so when writing many objects I'd only have to write:
Browser(BrowserString).Page(PageString).WebEdit("name:=asdfgh")
And the first part would remain static, so if the parents' data needs to be modified I'd only have to modify two variables and not all the objects created in all libraries.
Is it possible?
If I was not clear enough please let me know.
Thank you in advance!
I think what you're looking for is UFT's Description object
This allows you finer grained control on the description since in descriptive programming all values are regular expressions but with Description you can turn the regular expression functionality off for a specific property.
Set desc = Description.Create()
desc("html tag").Value = "A"
desc("innertext").Value = "More information..."
desc("innertext").RegularExpression = False
Browser("Example Domain").Navigate "www.example.com"
Browser("Example Domain").Page("Example Domain").WebElement(desc).Click
If you want to represent this with plain string then it's a bit more of a problem, you can write a helper function but I'm not sure I would recommend it.
Function Desc(descString)
Set ret = Description.Create()
values = Split(descString, "::")
For Each value In values
keyVal = Split(value, ":=")
ret(keyVal(0)).Value = keyVal(1)
Next
Set Desc = ret
End Function
' Usage
Browser("StackOverflow").Page("StackOverflow").WebElement(Desc("html tag:=H2::innertext:=some text")).Click
Further reading about descriptive programming.
As an alternative to Motti's excellent answer, you could also Set a variable to match your initial descriptive object and then extend it as required:
Set myPage = Browser("StackOverflow").Page("name:=StackOverflow", "html id:=PageID")
after which you can then use
myPage.WebEdit("name:=asdfgh")
throughout the rest of the code, so long as the myPage object stays in scope...

Use embedded string as variable name

I have a YAML file that uses the encoding __firstname__ as a placeholder which signifies that an existing method firstname should be used, rather than the literal string in a subsequent process.
I am trying to understand the most ruby way to to do this. Basically, I need to extract the part between the underscores and send it to an object. Here is pseudocode:
variable = '__firstname__'
if variable is prefixed and suffixed with underscores
result = object.send(variable.removeunderscores)
else
result = variable
end
puts result
I was about to write this procedurally like this, but this is the type of thing that I think ruby can less clunkily if only I knew the language better.
What is a clean why to write this?
There's nothing wrong with verbose code if it's clear to read IMO.
I'd do something like this using String#start_with? and String#end_with?:
variable = '__firstname__'
if variable.start_with?("__") && variable.end_with?("__")
result = object.send(variable[2...-2])
else
result = variable
end

Rails String Interpolation in a string from a database

So here is my problem.
I want to retrieve a string stored in a model and at runtime change a part of it using a variable from the rails application. Here is an example:
I have a Message model, which I use to store several unique messages. So different users have the same message, but I want to be able to show their name in the middle of the message, e.g.,
"Hi #{user.name}, ...."
I tried to store exactly that in the database but it gets escaped before showing in the view or gets interpolated when storing in the database, via the rails console.
Thanks in advance.
I don't see a reason to define custom string helper functions. Ruby offers very nice formatting approaches, e.g.:
"Hello %s" % ['world']
or
"Hello %{subject}" % { subject: 'world' }
Both examples return "Hello world".
If you want
"Hi #{user.name}, ...."
in your database, use single quotes or escape the # with a backslash to keep Ruby from interpolating the #{} stuff right away:
s = 'Hi #{user.name}, ....'
s = "Hi \#{user.name}, ...."
Then, later when you want to do the interpolation you could, if you were daring or trusted yourself, use eval:
s = pull_the_string_from_the_database
msg = eval '"' + s + '"'
Note that you'll have to turn s into a double quoted string in order for the eval to work. This will work but it isn't the nicest approach and leaves you open to all sorts of strange and confusing errors; it should be okay as long as you (or other trusted people) are writing the strings.
I think you'd be better off with a simple micro-templating system, even something as simple as this:
def fill_in(template, data)
template.gsub(/\{\{(\w+)\}\}/) { data[$1.to_sym] }
end
#...
fill_in('Hi {{user_name}}, ....', :user_name => 'Pancakes')
You could use whatever delimiters you wanted of course, I went with {{...}} because I've been using Mustache.js and Handlebars.js lately. This naive implementation has issues (no in-template formatting options, no delimiter escaping, ...) but it might be enough. If your templates get more complicated then maybe String#% or ERB might work better.
one way I can think of doing this is to have templates stored for example:
"hi name"
then have a function in models that just replaces the template tags (name) with the passed arguments.
It can also be User who logged in.
Because this new function will be a part of model, you can use it like just another field of model from anywhere in rails, including the html.erb file.
Hope that helps, let me know if you need more description.
Adding another possible solution using Procs:
#String can be stored in the database
string = "->(user){ 'Hello ' + user.name}"
proc = eval(string)
proc.call(User.find(1)) #=> "Hello Bob"
gsub is very powerful in Ruby.
It takes a hash as a second argument so you can supply it with a whitelist of keys to replace like that:
template = <<~STR
Hello %{user_email}!
You have %{user_voices_count} votes!
Greetings from the system
STR
template.gsub(/%{.*?}/, {
"%{user_email}" => 'schmijos#example.com',
"%{user_voices_count}" => 5,
"%{release_distributable_total}" => 131,
"%{entitlement_value}" => 2,
})
Compared to ERB it's secure. And it doesn't complain about single % and unused or inexistent keys like string interpolation with %(sprintf) does.

postgresql / greenplum parameter binding on jdbc, why does it think its a column name?

I have a query that looks something like this:
SELECT A.A, A.B, B.A, B.C, B.D
FROM tableone A, tabletwo B
WHERE A.A = B.A
AND B.C = :p_name
When the param :p_name is set to FOO I get an error like this:
[42703] ERROR: column "FOO" does not exist
When I manually set it to include single quotes 'FOO' it works.
I've tried padding escaped single quotes. I've tried the quote_* functions. I've ried using "#" "$" and "?" params stypes. This keeps popping up.
EDIT
Eliminating as much as I can, I tried the following from the sql console in IntelliJ
SELECT * from A where A.B = :p1
SELECT * from A where A.B = ?
SELECT * from A where A.B = #p1
And adding "Foo" the parameter to in the edit box. In all three cases, I get the same problem. When I add 'Foo' to the edit box, I get the results I expect.
I also used preparedStatement and ? rather than callableStatement with :p1 and also got the same results.
What am I doing wrong?
EDIT
Removing "stringtype=unspecified" from the JDBC URL seems to make the problem go away. This is why you shouldn't just copy snippets or other peoples code and just assume it will work for you.

Heredocs - Using same name twice? Why name them at all?

Toying with heredocs in PHP, I realized the name of the heredoc does not have to be unique. Thus:
$a = <<<EOD
Some string
EOD;
$b = <<<EOD
A different string
EOD;
is correct and behaves exactly as you would expect.
Is this bad practice for any reason? Why does a heredoc need a name/label (EOD above) at all, since you can't reference it by the name?
What if the string you're specifying contains EOD?
You can select the identifier to avoid conflicts with the chunk of text you're using as a string.
You don't reference it as such, but it acts as an identifier to indicate the end of the heredoc. e.g.
$a = <<<EOD
EOA
EOB
EOC
EOD;
One benefit is that editors like vim can apply syntax highlighting to heredocs named with HTML, EOHTML, EOSQL, EOJAVASCRIPT making them much prettier to work with...
$html = <<<EOHTML
<p class="foo">foo</em>
EOHTML;
$sql = <<<EOSQL
SELECT DISTINCT(name) FROM foo ORDER BY bar;
EOSQL;
$js = <<<EOJAVASCRIPT
foo = { bar: 'bar'; }
EOJAVASCRIPT;

Resources