extract value for calculated attribute - ruby

within Rails4, the following logic determines an attribute
if #items.count == 1
value = "disc1"
elsif #items.count == 2
value = "disc2"
else
end
which would then need to be accessed
#cluster.value
however this syntax does not work as the value is not a method. How can this variable be employed to extract the object's thus-named attribute?

It would be better if you just conditionally call methods:
if #items.count == 1
#cluster.disc1
elsif #items.count == 2
#cluster.disc2
else
# ...
end
Still, if you want to go that route:
#cluster.public_send value
Or if #cluster is an ActiveRecord model and you want to fetch the stored value in the corresponding table, you could:
#cluster[value]

Related

I get this error: 'list' object has no attribute 'countPoints'

When I import this code that I typed in here in to another code I get the error: 'list' object has no attribute 'countPoints' .
import ModuleRollDice as dce
def judge(rollPlayerA,rollPlayerB):
if not all(item in dce.options for item in rollPlayerA) or
not all(item in dce.options for item in rollPlayerB):
print("error")
if rollPlayerA.countPoints(rollPlayerA[0]) == len(rollPlayerA) and
rollPlayerB.countPoints(rollPlayerB[0]) != len(rollPlayerB):
return "A"
if rollPlayerA.countPoints(rollPlayerA[0]) != len(rollPlayerA) and
rollPlayerB.countPoints(rollPlayerB[0]) == len(rollPlayerB):
return "B"
elif sum(rollPlayerA) == sum(rollPlayerB):
return "tie"
elif sum(rollPlayerA) > sum(rollPlayerB):
return "A"
else:
return "B"
return
It appears as though the arguments passed to rollPlayerA/B are not list types objects. You should sanity check this beforehand to ensure that what is recieved is in fact a list type object. The issue can be resolved by both sanity checking and looking at the caller function and seeing what is being sent as arguments.
A simple sanity check could look like:
def judge(rollPlayerA,rollPlayerB):
if type(rollPlayerA) is not type(list) or
type(rollPlayerB) is not type(list):
print("judge function did not recieve proper input types")
return
...
Another way of doing this would be using pythons assert
def judge(rollPlayerA,rollPlayerB):
assert(type(rollPlayerA) == type(list)), "rollPlayerA is not a list"
assert(type(rollPlayerB) == type(list)), "rollPlayerB is not a list"
An even nicer way of doing this would be using PEP 3107's implementation of type assertions in definition declarations:
def judge(rollPlayerA: list, rollplayerB: list) -> None:
....
This also allows you to remove the redundant 'return' statement at the end of your function, which you didn't really need anyways

How should I write an array insert to store two named columns like an sql query creates?

I have a setup table of about 30 items, all of which are used in various locations. I make one call for some of the data in the application controller, and thought that I might save some cpu cycles and build some of the collection_select sql calls as arrays built from the first pass into the setup table.
I have one collection that requires that I pass two values from the db.
I can create an array that only passes a single column to a collection_select. I hit a wall when I try to pass two columns of data. Here is the array built by an sql call, with the resulting data.
#myscosts = Setmeup.find_by_sql("select (t_is || '--' || description) as shipr, description::float as cost from setmeups where active is true and g_is = 'Ship' order by t_is, srby;")
shipr | cost
----------------------+------
FedEx_Large--17.00 | 17
FedEx_Medium--7.00 | 7
FedEx_Small--5.00 | 5
Self_Delivery--1.00 | 1
USPS_2d_Large--9.00 | 9
USPS_2d_Medium--5.00 | 5
USPS_2d_Small--3.00 | 3
(7 rows)
In the application controller I have this code:
#setups = Setmeup.find_by_sql("select g_is, t_is, srby, description from setmeups where active = 'true' order by g_is, srby;")
# puts #setups.class
#setups.each do |f|
#title = "#{f.description}" if "#{f.g_is}" == "App" && "#{f.t_is}" == "Title"
(more code here, the next stanza works for a collection)
if f.t_is == 'Process' then
#steps << "#{f.srby} - #{f.description}"
end
(I can not find the right way to make this one work.)
if "#{f.g_is}" == 'Ship' then
#shpr = "#{f.t_is} -- #{f.description}"
#cst = "#{f.description}".to_f
#myscosts << "[#{#cst}, #{#shpr} ]"
end
(results of above in log..)
myscosts == ["[5.0, FedEx_Small -- 5.00]", "[3.0, USPS_2d_Small -- 3.00]", "[1.0, Self_Delivery -- 1.00]", "[5.0, USPS_2d_Medium -- 5.00]", "[7.0, FedEx_Medium -- 7.00]", "[9.0, USPS_2d_Large -- 9.00]", "[17.0, FedEx_Large -- 17.00]"]
Rails validation step throws error because the value passed:
"shipping_quoted"=>"[\"5.0\", \"FedEx_Small -- 5.00\"]" is not a number.
This is passed when the sql query creates the array:
"shipping_quoted"=>"5.0"
The data in the above example does not constitute all of the setup variables and options. Below is the method within the program to use the collection with the array '#myscosts' created by a direct sql query:
<%= form.label :shipping_quoted %>
<%= form.collection_select :shipping_quoted, #myscosts, :cost, :shipr %>
This is the collection_select I am having trouble dynamically creating an array that mimics the sql query result. Here is an example of a collection_select (with only one value passing) that I am able to get to work (but I do not understand how :to_s acts as an alias):
<%= form.label :step %>
<%= form.collection_select :step, #steps, :to_s, :to_s %>
My hope is to somehow have someone help me understand how to do something like this:
(in a model or controller)
#a1 = sql("select * from xytable";) # where #a1[0..n].y = 'Y'
#a1.each do |k|
if k.y != 'Y'
#a2 << "#{k}" # or "#{k.inspect}"
end
end
Such that array #a2 has the same class type, structure and key value pairs as array #a1. I could then use #a2 in a collection like the sql array generated as #myscosts.
Thanks for your response, I hope I have answered your questions with this additional data.

rails string substitution or similar solution in controller

I'm building a site with users in all 50 states. We need to display information for each user that is specific to their situation, e.g., the number of events they completed in that state. Each state's view (a partial) displays state-specific information and, therefore, relies upon state-specific calculations in a state-specific model. We'd like to do something similar to this:
##{user.state} = #{user.state.capitalize}.new(current_user)
in the users_controller instead of
#illinois = Illinois.new(current_user) if (#user.state == 'illinois')
.... [and the remaining 49 states]
#wisconsin = Wisconsin.new(current_user) if (#user.state == 'wisconsin')
to trigger the Illinois.rb model and, in turn, drive the view defined in the users_controller by
def user_state_view
#user = current_user
#events = Event.all
#illinois = Illinois.new(current_user) if (#user.state == 'illinois')
end
I'm struggling to find a better way to do this / refactor it. Thanks!
I would avoid dynamically defining instance variables if you can help it. It can be done with instance_variable_set but it's unnecessary. There's no reason you need to define the variable as #illinois instead of just #user_state or something like that. Here is one way to do it.
First make a static list of states:
def states
%{wisconsin arkansas new_york etc}
end
then make a dictionary which maps those states to their classes:
def state_classes
states.reduce({}) do |memo, state|
memo[state] = state.camelize.constantize
memo
end
end
# = { 'illinois' => Illinois, 'wisconsin' => Wisconsin, 'new_york' => NewYork, etc }
It's important that you hard-code a list of state identifiers somewhere, because it's not a good practice to pass arbitrary values to contantize.
Then instantiating the correct class is a breeze:
#user_state = state_classes[#user.state].new(current_user)
there are definitely other ways to do this (for example, it could be added on the model layer instead)

QTP handling Null values with public functions

I am trying to write a QTP Script which works as follows
* takes a column from table checks if it is null
if yes
it adds that column name in a variable .
Later that column name will be used to display to user that all such fields are left blank .
Something like this:
Set rsRecordset1 = dbConnection.Execute("select formcd,sndrpstlcd,recppstlcd,sndrcntrycd, from test_data where trk in ('"&tin&"')")
If rsRecordset1.EOF = false Then
Blank_field="blank_fields->"
formcd = rsRecordset1("formcd").value
typcd="formcd"
Call validatenull (typcd,Blank_field)
packaging = rsRecordset1("packaging").value
typcd="packaging"
Call validatenull (typcd,Blank_field)
......
Public function validatenull (typcd,Blank_field)
If (isnull(typcd) )Then
Blank_field = Blank_field & " " & typcd &", "
End If
End Function
Value of blank_Field is expected to catch values as "blank_fields->Form_id,packaging (Considering Form_id, Packaging passes Null values) {It shouldnt add values which are not Null to blank_fields}
In simpler words
ss = Null
call nnn(ss)
Public function nnn(ss)
If isnull(ss) Then
msgbox("yes")
End If
End Function
Has Error that msgbox does not populates But,
ss= Null
nnn(ss)
If isnull(ss) Then
msgbox("yes")
End If
Populates Msgbox as Yes
But I want Case 1 to be working and I do not want to add any more variables to the function name.
IF By making an Array we can do it, please suggest .
It appears your function works fine, but you are passing the wrong values. From your code snippet:
formcd = rsRecordset1("formcd").value
typcd="formcd"
Call validatenull (typcd,Blank_field)
When you call 'validatenull', you are passing the variable 'typecd'. On the previous line, you populate this variable with a string, so it will never be null. It appears what you intended to pass was the variable 'formcd'. Your second call to 'validatenull' does the same thing. Here is your first call modified to use the other variable.
formcd = rsRecordset1("formcd").value
typcd="formcd"
Call validatenull (formcd,Blank_field)

Single Ruby Value in One Line From a Collection

I have a collection of objects. There are 3 properties in each object
'id', 'name', 'is_primary'
The collection of objects will usually have anywhere from 1 to 5 objects.
What I want to do is check the collection to see if is_primary is true. If so output the name, or at least return it.
I want to do this in 1 line of code if possible. I am trying to slim up this one line for erb output in rails. Later in the page i'll output them all. I thought I had it, but if I return nil it adds extra space which shifts all the html oddly.
Thanks.
Hmm, this doesn't quite work if no element is_primary...I'm still thinking...
c.detect(&:is_primary).name
Ok, how about:
((a = c.detect(&:is_primary)) && a.name).to_s
As it happens, it is OK in an erb template for the <%= expression to return nil, that just results in an empty string, so for that case you can use:
(a = c.detect(&:is_primary)) && a.name
Update: Responding to the first comment, I do have a test case that I didn't post...
class A; attr_accessor :is_primary, :name, :id; end
t = [A.new, A.new, A.new, (a = A.new; a.name = 'xyz'; a.is_primary = true; a)]
puts (a = t.detect(&:is_primary)) && a.name
puts ((a = [].detect(&:is_primary)) && a.name).to_s
Complementing #DigitalRoss, you can also write:
collection.detect(&:is_primary).try(:name) || "default_if_no_element_or_name"
(well, to be honest I prefer Ick's maybe over Rails' try: c.detect(&:is_primary).maybe.name)
Side note: IMHO a flag that can only be active for a row it's not such a good idea. You may have inconsistent states with more than one being active and you'll have worry about it when updating (transactions, and so on). Try to store the PK reference somewhere else (a parent model? a state model?).
I want to do this in 1 line of code if possible. I am trying to slim up this one line for erb output in rails. Later in the page i'll output them all.
No need for one-liners (funny since I just wrote one): move the code to yous models or helpers as appropriate and keep your views pristine.

Resources