Slick update tuple with more than 22 elements - database

I'm running a Scala Play project where Slick is used for the database.
I've now added a new field to the Books table in the database and when I try to update an item like I used to do before I get the following error: tuples may not have more than 22 elements, but 23 given.
How do I run a update query with more than 22 fields?
val q =
for { book <- Books.filter(_.uuid === book.uuid) } yield (
book.field1,
book.field2,
book.field3,
book.field4,
book.field5,
book.field6,
book.field7,
book.field8,
book.field9,
book.field10,
book.field11,
book.field12,
book.field13,
book.field14,
book.field15,
book.field16,
book.field17,
book.field18,
book.field19,
book.field20,
book.field21,
book.field22,
book.field23
)
db.run(
q.update(
(
details.field1,
details.field2,
details.field3,
details.field4,
details.field5,
details.field6,
details.field7,
details.field8,
details.field9,
details.field10,
details.field11,
details.field12,
details.field13,
details.field14,
details.field15,
details.field16,
details.field17,
details.field18,
details.field19,
details.field20,
details.field21,
details.field22,
Timestamp.from(Instant.now)
)
)

Nothing prevents you from writing your own implementation of a tuple. But as said: It's bad practice. You probably have a lot of fields that should be in other tables.
An example can be found here: (it's old but more or less still the same)
https://github.com/scala/legacy-svn-scala/blob/master/src/library/scala/Tuple22.scala
But I honestly don't know if it will properly work, because I don't know what other code is being called.
I do like the question about updating more fields, because I'm working on an application that has a lot of datapoints for some elements; but I'll still try to split them.

Related

Rails update remove number from an array attribute?

Is there a way to remove a number from an attibute array in an update? For example, if I want to update all of an alchy's booze stashes if he runs out of a particular type of booze:
Alchy has_many :stashes
Stash.available_booze_types = [] (filled with booze.ids)
Booze is also a class
#booze.id = 7
if #booze.is_all_gone
#alchy.stashes.update(available_booze_types: "remove #booze.id")
end
update: #booze.id may or may not be present in the available_booze_types array
... so if #booze.id was in any of the Alchy.stash instances (in the available_booze_types attribute array), it would be removed.
I think you can do what you want in the following way:
if #booze.is_all_gone
#alchy.stashes.each do |stash|
stash.available_booze_types.delete(#booze.id)
end
end
However, it looks to me like there are better ways to do what you are trying to do. Rails gives you something like that array by using relations. Also, the data in the array will be lost if you reset the app (if as I understand available_booze_types is an attribute which is not stored in a database). If your application is correctly set up (an stash has many boozes), an scope like the following in Stash class seems to me like the correct approach:
scope :available_boozes, -> { joins(:boozes).where("number > ?", 0) }
You can use it in the following way:
#alchy.stashes.available_boozes
which would only return the ones that are available.

Scala Slick update column value

I'm using Slick with Play but am having some problems when trying to update a column value as it is not being updated, although I don't get any error back.
I have a column that tells me if the given row is selected or not. What I want to do is to get the current selected value (which is stored in a DB column) and then update that same column to have the opposite value. Currently (after many unsuccessful attempts) I have the following code which compiles and runs but nothing happens behind the scenes:
val action = listItems.filter(_.uid === uid).map(_.isSelected).result.map { selected =>
val isSelected = selected.head
println(s"selected before -> $isSelected")
val q = for {li <- listItems if li.uid === uid} yield li.isSelected
q.update(!isSelected)
}
db.run(action)
What am I doing wrong (I am new to slick so this may not make any sense at all!)
this needs to be seperate actions: one read followed by an update. Slick allows composition of actions in a neat way:
val targetRows = listItems.filter(_.uid === uid).map(_.isSelected)
val actions = for {
booleanOption <- targetRows.result.headOption
updateActionOption = booleanOption.map(b => targetRows.update(!b))
affected <- updateActionOption.getOrElse(DBIO.successful(0))
} yield affected
db.run(actions)
Update:
Just as a side note, RDBMSs usually facilitate constructs for performing updates in one database roundtrip such as updating a boolean column to it's opposite value without needing to read it first and manually negate it. This would look like this in mysql forexample:
UPDATE `table` SET `my_bool` = NOT my_bool
but to my knowledge the high level slick api doesn't support this construct. hence the need for two seperate database actions in your case. I myself would appreciate it if somebody proved me wrong.

SWIFT OS X - multiple statements inside a closure statement, a debugging tool?

I am using the following code to filter a large array:
var arrayOfSelectedRowDetails = self.projectRowDetails.filter(
{ $0.projectNumber == self.projectNumberArray[selectedRow] }
)
Normally the code runs fine and I have no issues. But in one scenario (after I have deleted some management objects from the persistent store) and then rerun the code I am getting a EXC_BAD_ACCESS (code = 1, address=0x0) error at runtime.
I have set a break and stepped through the runtime of this statement. It is a large array built from a core data entity (using a fetch statement) - and therefore takes a long time. When I step through the code over the first dozen or so indexes the code runs ok - when i remove the break and let it run it then presents the error.
Is it possible to println() from within the closure statement to assist with debugging? I have tried a number of different syntaxes and cannot get it to work.
Alternatively, is it possible to set an error capture statement within the closure so that the code ceases through a break or an abort() statement?
Fundamentally i am trying to identify the index of the array at the point that the error occurs so that I can get sufficient information to debug the delete function (which is where I think the error is). I do not seem to be able to ascertain the index from the info available to me when the error occurs.
This is the first time I have tried programming in Swift and making use of closures so I am learning as I go. Apologies if I am asking fundamental questions. I have not been able to find a similar question elsewhere here with an answer that works.
You can set an exception breakpoint in Xcode (for an example see here).
Also, I suggest that you move the access to self.projectNumberArray out of the closure:
let pn = self.projectNumberArray[selectedRow]
var arrayOfSelectedRowDetails = self.projectRowDetails.filter(
{ $0.projectNumber == pn }
)
The change might not solve the issue, but it will at least help the debugging.
Lastly, if you want to print the index, the following approach will probably work:
let pn = self.projectNumberArray[selectedRow]
var index = 0
var arrayOfSelectedRowDetails = self.projectRowDetails.filter(
{ println(index++); return $0.projectNumber == pn }
)

Select random item from an array with certain probabilities and add it to the stage

Its quite a big task but ill try to explain.
I have an array with a list of 200 strings and I want to be able to randomly select one and add it to the stage using code. I have movieclips exported for actionscript with the same class name as the strings in the array. Also, if it is possible, would I be able to select the strings with predictability such as the first has a 0.7 chance the second a 0.1 etc. Here is what i have currently
var nameList:Array=["Jimmy","Bob","Fred"]
var instance:DisplayObject = createRandom(nameList);
addChild(instance);
function createRandom(typeArray:Array):*
{
// Select random String from typeArray.
var selection:String = typeArray[ int(Math.random() * typeArray.length) ];
// Create instance of relevant class.
var Type:Class = getDefinitionByName(selection) as Class;
// Return created instance.
return new Type();
}
All this throws me this error
ReferenceError: Error #1065: Variable [class Jimmy] is not defined.
Ive searched for other threads similar but none combine the three specific tasks of randomisation, predictability and addChild().
I think that you've got two problems: a language problem and a logic problem. In the .fla connected to your code above, in the Library find each symbol representing a name and write into the 'AS linkage' column for that symbol the associated name -- e.g., 'Bob,' 'Fred' -- just the name, no punctuation.
Now getDefinitionByName() will find your 'Class'
If you put a different graphic into each MovieClip -- say, a piece of fruit or a picture of Bob,Jim, Fred -- and run your program you'll get a random something on stage each time.
That should solve your language problem. But the logic problem is a little harder, no?
That's why I pointed you to Mr. Kelly's solution (the first one, which for me is easier to grasp).

Restrict ObjectSet to a related Entity and sort by a dynamic column name

Given a Parent and a valid columnName, I want to find all the related Children, ordered by a dynamic column name. Here's how I thought my code would look:
Parent. // EntityObject
Children. // EntityCollection
Where(c => c.Gender == 'm'). // IEnumerable
OrderBy(columnName, ListSortDirection.Ascending). // -- not available --
Skip(pages * pageSize).Take(pageSize);
IEnumerable.OrderBy(string columnName) doesn't exist. Looking around to accomplish the "sort by dynamic column name", I started with this excellent-looking solution: How do I create an expression tree for run time sorting? , but this operates on an IQueryable
If it did, I assume it would bring the records over the wire to sort and diminish the performance of my pager anyway. So I reordered:
Repository. // Repository
Children. // ObjectSet
Where(c => c.Parent == Parent && c.Gender == 'm'). // ObjectQuery, runtime error
OrderBy(columnName, ListSortDirection.Ascending). // IOrderedQueryable
Skip(pages * pageSize).Take(pageSize);
ObjectSet and ObjectQuery implement OrderBy(string columnName), and this code compiles, but yields the error:
Unable to create a constant value of type 'DataModel.Parent'. Only
primitive types ('such as Int32, String, and Guid') are supported in
this context.
Of course, I can get the parent ID, but the Child.ParentReference is also a non-primitive type.
I can think of a few ways that would result in loading the entire recordset across the wire, but I feel like I must be missing something, because it must not be so hard to get a set of basic directive through to the database using all MS-centric technologies.
edit: pretend I'm http://en.wikipedia.org/wiki/Quiverfull , and need to paginate my children. :)
edit2: clarified my need to query a dynamic column name.
var parents = db.Parents; // Do whatever you need to get your unsorted collection from EF here.
if (sortBy == "Gender")
{
parents = parents.OrderBy(p => p.Gender);
}
else if (sortBy == "FirstName")
{
parents = parents.OrderBy(p => p.FirstName);
}
Now, this obviously isn't sorting on multiple columns, just a single column. And you can add in more logic for sort direction as well.
Edit: took out the crap about PredicateBuilder, I was going the wrong way when I started typing this answer, and forgot to take out the old stuff.
Try replacing your OrderBy
OrderBy("age", ListSortDirection.Ascending).
with
OrderBy(x => x.Age).
also the Where
Where(c => c.Parent == Parent && c.Gender = 'm').
should read
Where(c => c.Parent == Parent && c.Gender == 'm').
So there were a couple issues I was having, both mentioned in the question title.
Sorting by a run-time-selected, or dynamic, column name required some expression building. I used #Slace's popular extension method here.
That required an IQueryable. IQueryable works for me, because every time I was accidentally transforming my query into an enumerable, I was of course bringing all the results back over the wire before paging, which I was trying to avoid. But I still needed a way to get an IQueryable for results with a relationship to an entity I already held.
It was something simple I overlooked, just joining on the Entity.Id worked, and didn't result in redundant joins at the datasource. Not quite as object-oriented as I expected from EF, but it will do.
Repository. // Repository
Children. // ObjectSet
Where(c => c.Parent.Id == Parent.Id). // ObjectQuery, works fine
OrderBy(columnName, ListSortDirection.Ascending). // IOrderedQueryable
Skip(pages * pageSize).Take(pageSize); // Only transfers 1 page

Resources