I have 2 classes: one with 2 properties and one with an array. I want to make an array of objects of the first class.
The example compiles, but gives a wrong answer. Why?
[indent=4]
class data
prop first_name : string = " "
prop last_name : string = " "
class Arr : Object
person : data
dataset : array of data[]
init
person = new data()
dataset = new array of data[3]
def date_input()
print "\n data input \n"
person.first_name = "Egon"
person.last_name = "Meier"
dataset[0] = person
print dataset[0].first_name + " " + dataset[0].last_name
person.first_name = "John"
person.last_name = "Schneider"
dataset[1] = person
print dataset[1].first_name + " " + dataset[1].last_name
person.first_name = "Erwin"
person.last_name = "Müller"
dataset[2] = person
print dataset[2].first_name + " " + dataset[2].last_name
def date_output()
print "\n data output \n"
for i : int = 0 to 2
print dataset[i].first_name + " " + dataset[i].last_name
init
Intl.setlocale()
var a = new Arr()
a.date_input()
a.date_output()
The fundamental problem is you are referring to the same person three times, but changing their name each time. In Genie there are both value types and reference types. Value types are simpler and automatically copied on assignment. For example:
[indent=4]
init
a:int = 2
b:int = a
b = 3
print( "a is still %i", a )
A reference type has the advantage that it can be easily copied, Genie simply keeps a count of the references made. So to copy a reference type the reference count is increased by one, but this means that changes to the underlying object will affect all variables that refer to it:
[indent=4]
init
a:ReferenceTypeExample = new ReferenceTypeExample()
a.field = 2
b:ReferenceTypeExample = a
b.field = 3
print( "a.field is not 2, but %i", a.field )
class ReferenceTypeExample
field:int = 0
In the working example below I have made Person a value object by using readonly properties:
[indent=4]
init
Intl.setlocale()
var group = new Group()
print "\n data input \n"
try
group.add_person( new Person( "Egon", "Meier" ))
group.add_person( new Person( "John", "Schneider" ))
group.add_person( new Person( "Erwin", "Müller" ))
except err:GroupError
print( err.message )
print( #"$group" )
class Person
prop readonly first_name:string = ""
prop readonly last_name:string = ""
construct( first:string, last:string )
_first_name = first
_last_name = last
exception GroupError
GROUP_FULL
class Group
_people_count:int = -1
_group:new array of Person
_max_size:int = 2
construct()
_group = new array of Person[ _max_size ]
def add_person( person:Person ) raises GroupError
_people_count ++
if _people_count > _max_size
_people_count = _max_size
raise new GroupError.GROUP_FULL(
"Group is full. Maximum is %i members",
_max_size + 1
)
_group[ _people_count ] = person
print( " " + _group[ _people_count ].first_name +
" " + _group[ _people_count ].last_name
)
def to_string():string
result:string = "\n data output \n\n"
if _people_count < 0
result += " empty group"
return result
for i:int = 0 to _people_count
result += " " + _group[i].first_name + \
" " + _group[i].last_name + "\n"
return result
Some details about the code:
By changing the properties to be readonly an error will be given when you compile the program if it tries to change a detail of Person. In your example, if you change the properties of data to be readonly then the Vala compiler will warn you are trying to re-write the current object
Person has its data values set in the constructor and then any attempt after that to change them is an error
For a simple property Genie generates an automatic backing field that starts with an underscore. For example in Person the property first_name has the backing field _first_name and it is that field that is set in the constructor
Instead of including the people's names in the method itself, a method called add_person() is used that takes a Person as a parameter. This separates the concrete data from the abstract class
Checks have been added to the add_person() method to make sure the array doesn't go beyond its limits. If more people are added to the group than are allowed then an exception is raised
The add_person() calls in the init block create the Person as part of the method call. This means a reference to a Person object is not kept in the init block
Related
I created a new major baseline in a DOORS module and then ran a small DXL script which includes lines
Module mp = current
Baseline bp = getMostRecentBaseline(mp)
int majorVersion = major(bp)
int minorVersion = minor(bp)
print "major " majorVersion " minor " minorVersion "\n"
string suff = suffix(bp)
print "suffix " suff "\n"
bool bstat
bstat = isBaseline(mp)
print "bstat " bstat "\n"
ModuleVersion mv = moduleVersion(mp)
string basind = baselineIndex(mp)
print "baseline index " basind "\n"
bool otherbstat = baseline(mp)
print "otherstat " otherbstat "\n"
bool basv = isBaseline(mv)
print "version base " basv "\n"
All of these return FALSE, indicating the module is not currently baselined. I have not done any edits to any attributes since baselining. I have done things like creating new Views. If I run the IBM DXL macro to compare the latest baseline against the "Current" version, it reports there are zero differences.
So my question is - what do the various isBaseline functions look at that is causing them to return FALSE? Or, am I going about this the wrong way - all I really need is a Q&D bit of DXL code to check that my module hasn't been edited for content since the last baseline was established.
The primary issue is that when your code gets a ModuleVersion (line 11), it uses a form of the function that gets the current version of the module. Line 14 should invoke isBaseline, not baseline, making the last two lines redundant.
See p310 of the current version (9.6.1) of the DXL Reference Manual for full details of the moduleVersion function.
The minimally modified version of your code that gets the result I think you were expecting, follows:
Module mp = current
Baseline bp = getMostRecentBaseline(mp)
int majorVersion = major(bp)
int minorVersion = minor(bp)
print "major " majorVersion " minor " minorVersion "\n"
string suff = suffix(bp)
print "suffix " suff "\n"
bool bstat
bstat = isBaseline(mp)
print "bstat " bstat "\n"
ModuleVersion mv = moduleVersion(uniqueID(mp), bp)
string basind = baselineIndex(mp)
print "baseline index " basind "\n"
bool otherbstat = isBaseline(mv)
print "otherstat " otherbstat "\n"
bool basv = isBaseline(mv)
print "version base " basv "\n"
In the version below, I've renamed variables, reordered some lines, and removed some content that wasn't required, for clarity:
Module modCurrent = current
Baseline blLatest = getMostRecentBaseline(modCurrent)
int iMajorVersion = major(blLatest)
int iMinorVersion = minor(blLatest)
string sBLSuffix = suffix(blLatest)
print "last baseline: major " iMajorVersion " minor " iMinorVersion " suffix " sBLSuffix "\n"
bool bIsBaseline = isBaseline(modCurrent)
print "bIsBaseline = " bIsBaseline "\n"
ModuleVersion mv = moduleVersion(uniqueID(modCurrent), blLatest)
Module modBaselined = load(mv, false)
string basind = baselineIndex(modBaselined)
print "baseline index = " basind "\n"
bIsBaseline = isBaseline(modBaselined)
print "bIsBaseline = " bIsBaseline "\n"
close(modBaselined)
Looks like isBaseline returns TRUE only if the current module View is set to display a selected baseline, as opposed to the "current" working view. `isBaseline and its brethren do not look at module contents, and thus won't see any potential differences between a baseline version and the current working view.
I'm aware of various DXL tools which perform a 'compare' on the contents, so that can be dealt with separately. As noted at this question, there are enhanced versions of the default "compare" script, such as one posted at this DOORS forum
def createlist(json, filename, arraygroup):
filehdl = open(filename, "wb")
for key, value in rulegroup.items():
filehdl.write('#' + value + "\n")
for list in json:
if list['arraygroup'] == value:
filehdl.write(list['name'] + " " + list['surname'] + "\n")
filehdl.close()
#depart1
testname testsurname
testname1 testsurname2
testname3 testsurname3
#depart2
#depart3
Json has 5 names, and 2 names should be places in #depart2, #depart3 base on their correct department.
Hi i have here a code that will create a file and separate the names in json file base on there group, but the 2nd forloop (with json) was not resetting its index, so after 1st loop of the forloop list was stuck.
tnx for answer.^^,
I already resolve the problem by inputing json obj to array.
jsonlist = []
for obj in json:
jsonlist.append(obj)
then change the 2nd loop with jsonlist
for list in jsonlist:
if list['arraygroup'] == value:
filehdl.write(list['name'] + " " + list['surname'] + "\n")
I am trying to save a Array[String, Int] data into file. However, every time, it reports:
object not serializable
I also tried to combine the two columns into a string, and want to write it line by line, but it still report such error. The code is:
val fw = new PrintWriter(new File("/path/data_stream.txt"))
myArray.foreach(x => fw.write((x._1.toString + " " + x._2.toString + "\n").toByte
import java.nio.file._
val data = Array(("one", 1), ("two", 2), ("three", 3))
data.foreach(d => Files.write(Paths.get("/path/data_stream.txt"), (d._1 + " " + d._2 + "\n").getBytes, StandardOpenOption.CREATE, StandardOpenOption.APPEND))
Why he gives me (Type error) in that statment
" address = cur.fetchone()[2] last = cur.fetchone()[4] no = cur.fetchone()[5] , while it accept "name = cur.fetchone()[1]" in the code : "
import sqlite3
conn = sqlite3.connect('myproject.sqlite')
cur = conn.cursor()
print "Welcome Mr/Hefnawy"
cur.execute('SELECT phone FROM participants')
b = cur.fetchone()[0]
while True:
a = raw_input("Enter Phone number here : ")
if a == b :
cur.execute('SELECT name,address,last_order,no_of_orders FROM participants WHERE phone = ?',(b, ))
name = cur.fetchone()[1]
address = cur.fetchone()[2]
last = cur.fetchone()[4]
no = cur.fetchone()[5]
print "The Costumer is already exist in Paricipants "
print "To edit the costumer data press (1)", "\n" , "to delet the costumer press (2)", "\n" , "add new order to the costumer press (3) "
c = raw_input("Enter your choice here : ")
if c == "1":
print "What do you want to edit ? , to edit name press 1 , to edit address press 2 , to edit phone press 3"
d = raw_input("Enter your choice here : ")
if d == "1" :
e = raw_input("New costumer name please ")
cur.execute('UPDATE participants SET name = ? WHERE phone = ?' , (e , a))
print "Costumer name has been updated to :", e
print ""
conn.commit()
else:
print "The costumer is not exist"
print b
print a , type(a)
When you are fetching something from a cursor say for example
t = cur.fetchone()
you can access the data from t using
print t[0],t[1],t[2] but In your case you are using multiple cur.fetchone() which allows you to use name = cur.fetchone()[1] that ends the data in the cursor. The second line address = cur.fetchone()[2] and the lines that follow it do not have a sql query executed for them to fetch, hence giving you the error. If you want to access the whole row just assign it to a variable and use the variable to get the data.
I should create a search page in which i have to save in an Array all the results of the searching. I had two problems:
1) I used the following statement:
Company.joins(:references).where(sql_string)
that returns an ActiveRecord:Relation and it's not good for me cause i have to display these results in the index action , in which i use an each statement. So , to overcame this problem i used the to_a.
I checked the .class of my variable and with the to_a it passed from ActiveRecord:Relation to Array. So , it seems that this solve the problem.
Company.joins(:references).where(sql_string).to_a
2) Now, i have to pass this variable (Array) into my index action.
I executed the search in the action called search:
def search
...
#companies = Company.joins(:references).where(sql_string).to_a
end
Now, i want to pass this to index:
def index
#companies ||= Company.all
end
I used #companies ||= Company.all cause i think that the #companies is and istance variable and it should be available in all the actions of the class. Isn't it? By the way, it doesn't workl. I mean , the results are not shared through the two methods.
Also , in the search action i don't know how to call index action. I used the redirect_to but this bring me to another problem.
def search
...
#companies = Company.joins(:references).where(sql_string).to_a
redirect_to companies_index_path
end
The second time i call the search action it brings me into the index action.As i insered the searching value. At really he still had the past searching in memory, and i don't want this behavior.
So , in other words, i want to:
passing #companies searching result to index action.
avoid the loop between search-index. So in every new request resets
the old searching.
i want to know if it's correct the casting with the to_a to bring
an ActiveRecord:Relation to Array.
Thank You.
EDIT:
def search
stringa_sql = ""
ragione_sociale = ""
riferimento = ""
note = ""
min_date = ""
max_date = ""
company_type = ""
sector = ""
country = ""
certification = ""
contact = ""
state = ""
manage = ""
consultation = ""
formation = ""
software = ""
if params[:ragione_sociale]
ragione_sociale = params[:ragione_sociale]
stringa_sql = "ragione_sociale like "+"'%"+ragione_sociale+"%'"
end
if params[:riferimento]
riferimento = params[:riferimento]
stringa_sql += " AND nome like "+"'%"+riferimento+"%'"
end
if params[:note]
note = params[:note]
stringa_sql += " AND note like "+"'%"+note+"%'"
end
if params[:min_date] && params[:min_date]!= ""
if params[:max_date] && params[:max_date]!= ""
min_date = params[:min_date]
max_date = params[:max_date]
stringa_sql += " AND richiamare >="+min_date+" AND richiamare <="+max_date
end
end
if params[:company_type] #se inviamo la richesta senza scrivere params[:category] viene passato vuoto
if params[:company_type][:id] != ""
company_type = params[:company_type][:id]
stringa_sql += " AND id_forma_giuridica = "+company_type
end
end
if params[:sector]
if params[:sector][:id] != ""
sector = params[:sector][:id]
stringa_sql += " AND id_settore = "+sector
end
end
if params[:country]
if params[:country][:id] != ""
country = params[:country][:id]
stringa_sql += " AND id_provincia = "+country
end
end
if params[:certification]
if params[:certification][:id] != ""
certification = params[:certification][:id]
stringa_sql += " AND id_certificazione = "+certification
end
end
if params[:contact]
if params[:contact][:id] != ""
contact = params[:contact][:id]
stringa_sql += " AND id_contattato = "+contact
end
end
if params[:state]
if params[:state][:id] != ""
state = params[:state][:id]
stringa_sql += " AND id_stato = "+state
end
end
if params[:manage]
if params[:manage][:id] != ""
manage = params[:manage][:id]
stringa_sql += " AND id_gestito = "+manage
end
end
if params[:consultation]
if params[:consultation][:id] != ""
consultation = params[:consultation][:id]
stringa_sql += " AND id_consulenza = "+consultation
end
end
if params[:formation]
if params[:formation][:id] != ""
formation = params[:formation][:id]
#formazione DA METTERE
end
end
if params[:software]
if params[:software][:id] != ""
software = params[:software][:id]
stringa_sql += " AND id_software = "+software
end
end
#companies = Company.search(stringa_sql).to_a
if not #companies.empty?
redirect_to companies_index_path
end
end
index:
def index
#companies ||= Company.all
end
I used #companies ||= Company.all cause i think that the #companies
is and istance variable and it should be available in all the actions
of the class. Isn't it?
Not really, it depends on from where you want to access the #companies instance variable. e.g. from which view, you need #companies instance variable in the corresponding action method of the controller.
The second time i call the search action it brings me into the index
action
You are using redirect_to companies_index_path in your search method which brings you to the index action.
To implement search in your application, you can follow this somewhat standard process:
In your application_controller.rb which will have the #search_query.
# Returns string
def search_query
#search_query ||= params[:query] || params[:search]
end
Then, in your searches_controller.rb, you can have:
def search
# in the method build your search results based on
# search_query param
#search_results = Company.joins(:references).where(sql_string(search_query)).to_a
end
In your routes.rb, you can have:
get '/search(/:query)' => 'searches#search', query: /.+/, as: 'search'
Which will take you to the searches_controller's search action where you are building the search results #search_results.
Finally, you need to have a app/views/searches/search.html.erb view file where you have access to your #search_results instance variable and you can just loop through them and display them in this view.
Answers to your last 3 questions:
passing #companies searching result to index action.
avoid the loop between search-index. So in every new request resets
the old searching.
You can overcome these problems by following the request/response flow that I have mentioned above. You should not share your index view with your search and you should not have any loop between search and index. Both of them are separate actions of the controller and can be handled separately as I showed above.
i want to know if it's correct the casting with the to_a to bring an
ActiveRecord:Relation to Array.
You can do that if you want. But, you don't really need it in this use case. You can store the ActiveRecord:Relation in your search_results and when you access this instance variable from inside your search.html.erb view, you can easily loop through using a .each do block. So, you don't have to worry about ActiveRecord:Relation and Array.