Ruby case multiple conditions with and - ruby-on-rails

I've got below case condition which works well.
case params[:event_type]
when 'publish'
StoreActivityWorker.perform_async(params)
when 'delete'
DeleteActivityWorker.perform_async(params)
end
But I want to add another conditions to each when - name == %w[Text Video Audio] so the code should be like:
case params[:event_type]
when 'publish' && name == %w[Text Video Audio]
StoreActivityWorker.perform_async(params)
when 'delete' && name == %w[Text Video Audio]
DeleteActivityWorker.perform_async(params)
end
but it won't work, it shows false every time.
name is just:
params.dig('entity', 'relationships', 'item_type', 'data', 'name')

Currently you're checking if
('publish' && name == %w[Text Video Audio]) === params[:event_type]
or if
('delete' && name == %w[Text Video Audio]) === params[:event_type]
The left side of === can be either true or false and I don't think params[:event_type] is going to be either of those two values, so neither of your two cases are going to be executed.
What you probably want is something like:
if name == %w[Text Video Audio]
case params[:event_type]
when 'publish'
StoreActivityWorker.perform_async(params)
when 'delete'
DeleteActivityWorker.perform_async(params)
end
end
Even that seems a bit off since you're checking if name is equal to %w[Text Video Audio] which I don't think is going to be the case. Perhaps you want:
%w[Text Video Audio].include?(name)
A nested case inside of an if statement is also not the best option. I might suggest a guard clause but without knowing the entire method it's hard to tell.

The expression 'publish' && name == %w[Text Video Audio] does not make sense. Remember that && is a shortcut operator: (E1) && (E2) evaluates E1, and if the result is falsy, returns this value (i.e. nil or false), without even looking at E2. If E1 is trueish, it evaluates and returns E2. In your case, 'publish' is trueish, and hence E2 is returned.
Your E2 is
name == %w[Text Video Audio]
and this expression evaluates to either be true or false, and neither can match your params[:event_type], because the event type is likely not truenor false, but a string, and therefore the condition does not fire.

Related

Ruby - Next if vs Next unless

What is the difference between next if vs next unless.
My understanding of next if was that next only if variable == value but in the following code, the second next statement isn't working. next if datastore.id == 5 it is bypassing this and proceeding even if the datastore.id == 2 or datastore.id == 3 etc.,
$evm.vmdb(:ManageIQ_Providers_Vmware_InfraManager_Storage).all.each do |datastore|
next if datastore.ems_id == provider.id.to_s
next if datastore.id == 5
dialog_hash[datastore[:id]] = "#{datastore.name} on #{datastore.ext_management_system.name}"
end
But if I change the next if to next unless then it works fine.
$evm.vmdb(:ManageIQ_Providers_Vmware_InfraManager_Storage).all.each do |datastore|
next if datastore.ems_id == provider.id.to_s # Next if works here
next unless datastore.id == 5 # Next unless works here instead of next if
dialog_hash[datastore[:id]] = "#{datastore.name} on #{datastore.ext_management_system.name}"
end
I'll quickly explain next and the difference between if and unless in ruby, and proceed to suggest some things you could try to get your code to work.
if
Code would execute if the condition is true.
unless
Code would execute if the condition is false. It would work the same as:
if !(expression) { ... }
next
The program would skip the rest of the code inside the loop block, and skip to the next iteration.
In your case, if there is a next called in the first line, then the rest of the code wouldn't run.
$evm.vmdb(:ManageIQ_Providers_Vmware_InfraManager_Storage).all.each do |datastore|
next if datastore.ems_id == provider.id.to_s # if this condition is true, don't run rest of the code in this loop, and go to the next datastore
next if datastore.id == 5
dialog_hash[datastore[:id]] = "#{datastore.name} on #{datastore.ext_management_system.name}"
end
Suggestion
It's unclear from your question what you mean by if doesn't work but unless does.
From the first code snippet in the question, the last line of the code. i.e,
dialog_hash[datastore[:id]] = "#{datastore.name} on #{datastore.ext_management_system.name}"
would only run if both of the conditions above are false.
You can check where the data is unexpected, or if your initial conditions are wrong, by debugging the datastore with either a debugger or some puts statements inside the loop.
All the best.
The difference is that
next if condition calls next when the condition is true, but
next unless condition calls next when the condition is false.
When calling next with a condition like datastore.id == 5 doesn't work as expected, then the problem is not the usage of if or unless because they work the opposite way.
Instead, you need to debug why you expect datastore.id == 5 to be true and why it is not. Obviously, the condition datastore.id == 5 can only be true when datastore.id returns the integer 5. If it returns false then datastore.id might return a string with the digit "5".
I suggest adding debug output to your code to dig deeper, like this:
p datastore.id
p datastore.id.class
Additionally to answers, most popular Ruby style guide recommends to use positive instead of negative conditions
# bad
do_something if !some_condition
# good
do_something unless some_condition
Depending on this, you can choose if or unless

vlc.playlist.loop automation

Basically I have this .lua code in my vlc extension, now I am having problems in setting the VLC repeat automatically to loop all in a playlist.
I have tried setting it into "all", 0, 1, 2, true, "TRUE" but it does just not set the playlist's loop value into "all".
I also cannot get the playlist loop value. I tried object.playlist().loop, vlc.playlist.loop.
I read the VLC's Lua Script and Extensions page but I still cannot get what is supposed to be that
<status>
value or any of its acceptable strings.
function trigger()
vlc.playlist.stop()
vlc.playlist.sort("random")
vlc.playlist.goto(0)
--vlc.playlist.repeat_(<status>)
--vlc.playlist.loop(<status>)
vlc.playlist.play()
end
Solved it, thanks to Vyacheslav and Piglet
this would now set the vlc playlist loop to loop all, but I cannot print or vlc.msg.info the value of playlist.loop though. But it works in the end.
function trigger()
vlc.playlist.stop()
vlc.playlist.sort("random")
vlc.playlist.goto(0)
playlist = vlc.object.playlist();
if vlc.var.get(playlist,"loop") == false then vlc.playlist.loop() end
vlc.playlist.play()
end
I have not tried it but following the documentations logic status should be either nil, true or false. If nil (or no argument) it will toggle the current state. true will enable, false disable loop or repeat.
Not sure why you expect loop to be "all".
Did you remove the -- in front of the respective line?
I assume setting both doesn't make sense. And they will toggle each other internally?
In common case, if you do not know how it properly works, it is possible to search such code in github.com.
In your case, you can use this:
https://github.com/search?utf8=%E2%9C%93&q=vlc.playlist.loop+language%3ALua&type=Code&ref=searchresults
As you can see,
you can use such code:
elseif command == "pl_loop" then
vlc.playlist.loop()
elseif command == "pl_repeat" then
vlc.playlist.repeat_()
or
elseif c == 'loop' then
if vlc.playlist.loop(v) then
vlc.playlist.repeat_('off')
end
elseif c == 'repeat' then
if vlc.playlist.repeat_(v) then
vlc.playlist.loop('off')
end

add variable value in table in lua for ptokax script

Recently i updated my ptokax to 0.5.3 and since then my votekick script has stopped working as in my script takes input from other online users as 1 or 2 as accept or deny the user to be kicked or not but now whenever the user enters 1 or 2 the script has stopped taking input and inserting it in the table i suspects its maybe due to some syntax change . please have a look at my script and suggest .
data = " <Nick> 2" -- this is the way script takes input frm dc chat
s,e,vote= string.find(data,"%b<>%s(.+)")
if vote == "1" then
table.insert(votesPlus,user.sNick)
Core.SendToAll("*--"..user.sNick.." accepts--")
if #votesPlus == votes or # votesMinus == votes then
stop(nTimerId)
end
return true
elseif vote == "2" then
table.insert(votesMinus,user.sNick)
Core.SendToAll("*--"..user.sNick.." denies--")
if #votesPlus == votes or # votesMinus == votes then
stop(nTimerId)
end
return true
else
-- the user is not voting even when poll active
end
Please mention whether you're using the PtokaX released to be used with Lua 5.3.0 or 5.1.5.
The NMDC hub protocols define that the chat messages are sent in the following format:
<Nick> the message|
where | acts as the delimiter.
Apart from that, I don't see any issues with your script. You can, although, optimise performance:
local vote = data:match "%b<>%s(%d)"
-- since you only want a single digit to be matched
-- also, use local variable whenever possible
if vote == "1" then
table.insert(votesPlus, user.sNick)
Core.SendToAll( "*--"..user.sNick.." accepts--" )
if #votesPlus == votes or #votesMinus == votes then
stop( nTimerId )
end
return true
elseif vote == "2" then
table.insert(votesMinus, user.sNick)
Core.SendToAll( "*--"..user.sNick.." denies--" )
if #votesPlus == votes or #votesMinus == votes then
stop( nTimerId )
end
return true
else
-- the user is not voting even when poll active
-- return false so that further scripts might be able to process it
return false
end
PS: I think you should also check if the same user is voting twice! Also, you can put the following code:
if #votesPlus == votes or #votesMinus == votes then
stop( nTimerId )
end
in the call to OnTimer function.

Error using Ruby OR in if

I have this simple condition in my ruby code:
if user.text != ("Empty" || "Damaged")
do something...
the thing is that when it is "Damaged" it still enters the loop, so I have to use this:
if user.text != "Empty"
if user.text != "Damaged"
...
..
What is the correct syntax to make the first one work?
Thanks!
Use this:
unless ["Empty", "Damaged"].include?(user.text)
...
end
The problem with your first approach is that a || b means that: if a != nil then it is a, else it is b. As you can see it is good for variables, not constants as they are rarely nil. Your expression ("Empty" || "Damaged") simply equals "Empty".
You want to use the this as a binary operator, the correct form would be:
if (user.text != "Empty") && (user.text != "Damaged")
The upper solution is just shorter. It consists of an array of elements you want to avoid, and you just simply check is the user.text is not present in it.
#Matzi has the right answer, for sure. But here's why what you're doing is failing:
Your statement ("Empty" || "Damaged") evaluates to "Empty"
You're saying return either one of these, whichever non-false thing you find first. In Ruby, any string, number or Object returns true, so you return "Empty" every time.
A better way to lay it out if you really want to use an if statement:
if user.text != "Empty" && user.text != "Damaged"
...
end
I assume, by the way, that you're trying to say "If the user text is neither Damaged nor Empty".
Hope that helps.
if ((text != "Empty") && (text != "Damaged"))

ruby: how avoid if-then-else when doing case-insensitive comparison that handles nil too

I frequently find myself having to do an extra nil check (to avoid throwing an 'undefined for nil' error) that I'm pretty sure is unnecessary.
In one common example, when looking at optional url params, e.g. which might or might not exist, I like them to be case insensitive (if they exist).
for example one of my controller methods allows (doesn't require) &showdate=true and I like to make it user friendly by not caring about true vs TRUE vs True.
I could just say
#showdate = params[:showdate] == "true"
but that assumes lower case.
If I do this:
#showdate = params[:showdate].lower == "true"
it of course throws an unwanted error if showdate is missing from the url becasue nil.lower throws an error.
So I end up doing something like this LOTS of time in my code:
if params[:showdate]
#showdate = params[:showdate].lower == "true"
else
#showdate = false (or maybe nil)
I know there's a Better Way, just don't know what it is. Any help would be appreciated.
#showdate = params[:showdate].to_s.downcase == "true"
Rails?
#showdate = params[:showdate].try(:downcase) == "true"
or
#showdate = !!params[:showdate] && params[:showdate].downcase == "true"
You could do it this way:
#showdata = (params[:showdate] || '').downcase == 'true'

Resources