Haskell persistent library allows me to create entities with relations. I would like to be able to get entities (and also create them) using REST JSON calls. But I don't seem to understand how to approach the problem of combining a resulting entity when it is split amongst tables or how to split it when I need to save it (so that the needed parts are saved into needed tables).
An example:
share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
Problem
name T.Text
description T.Text
Solution
problemId ProblemId
author T.Text
solution T.Text
|]
So, let's say we have a single problem and multiple solutions to it. How can I get a combined information (which is a problem with all related solutions). Do I need to create a data type which could look something like this:
data Solution =
Solution { author :: T.Text
, solution :: T.Text
}
data Problem =
Problem { name :: T.Text
, description :: T.Text
, solutions :: [Solution]
}
... and then define toJSON, so that I can send it to the caller? Or is there some other approach?
And what about creating entries in DB when I want to add a problem with several solutions (from a single REST call). How would that look like?
I hope I explained my problem correctly and you understand what I am struggling with.
Thank you
Related
using rails 4.1.8, ruby 2.2, mysql, elasticsearch-rails 5.0.4, elasticsearch 5.2. the selectors field on the Selector model is stored as json in a varchar column and for some reason when I load a location and its associated selector using as_json, the selectors field comes back nil when I know there is data in the column?
the Selector table:
create table Selectors do
t.text selectors
t.text selectors_other
t.references location
t.timestamps
end
I recently added Elastic Search so the model has:
settings index: {
analysis: {
analyzer: {
selector_analyzer: {
type: :standard,
stopwords: ["some","words","here"]
}
}
}
}
mapping do
indexes :selectors, {analyzer: :selector_analyzer}
indexes :selectors_other, {analyzer: :selector_analyzer}
end
def as_indexed_json(options={})
{
'id' => id,
'selectors' => selectors,
'selectors_other' => selectors_other
}
end
and the call I make to get the data for the view is
Location.find(<id>).as_json(:include => [:selector, :response])
every field I expect is in the json and all the data is there except the selectors field which is nil. I know there is data because if I do:
loc = Location.find(<id>)
loc.selector
the selectors field is not nil. I tried adding an as_json method to the Selector model but it didn't have any effect. The only changes I've made recently were to add the Selector model to the Elasticsearch index. I used an IndexManager in order to create one index with multiple types and created a rake task for deployments and re-indexing. The only distinction is that this field is stored as json, but it was working fine before.
Any ideas, suggestions, etc would be appreciated since I can't think of anything that would cause it to be nil.
figured out what was causing the field to be nil, tho not why it is causing a problem
I had added a method to manipulate the json when updating the selectors field, in that method I had a line like
sel_hash = JSON.parse(self.selectors)
the IDE was unable to resolve self.selectors so I added
attr_accessor :selectors
and that line for some reason caused the selectors field to be nil, go figure
So I am having a couple problems with Play's scalaJSON. First being that I am somehow not able to make my keys anything other than strings. I have defined a a JSONWrites converter as follows:
implicit val musics = new Writes[Question] {
def writes(question:Question) = Json.obj(
"questionID" -> question.questionID,
"questionText" -> question.questionText,
"responseURI" -> question.responseURI,
"constraints: min,max,Optional" -> Json.arr(question.minResponse, question.maxResponse, question.optionalQ),
"responseDataType" -> question.responseDataType
)
}
my model case class for question:
case class Question (questionID:Int,
questionText:String,
responseURI:String,
minResponse:Option[Int],
maxResponse:Option[Int],
optionalQ:Boolean,
responseDataType:String)
When desigining my REST API in play, I wanted to access the specific question of this survey app with a url such as /questionBlock/questionID
I tried to simply make the question.questionID the parent key and nest the rest of the JSON as the value to this key, but it would not allow me to do this, saying expected String actual Int
the actual JSON rendered out looks like this:
[{"questionID":0,"questionText":"What is your favorite musical artist?",
"responseURI":"/notDoneYet","constraints: min,max,Optional":[1,1,false],
"responseDataType":"String"},{"questionID":1,"questionText":"What is your favorite music genre?",
"responseURI":"/notDoneYet","constraints: min,max,Optional":[1,1,false],"responseDataType":"String"}]
But using this I cannot seem to figure out how to return the entire field where questionID equals 1 or 2 etc. I have used the 0th, 1st, etc element of the array but that is not the ideal approach for me, since question Ids may not always start at 0 for a particular sequence of questions.
Basically, I want to be able to show an entire record for one question when I provide the value of questionID. In Javascript I would have made the outermost key this questionID value, but I am unable to figure out how to do this using scalaJson. If there is an alternative way to accomplish this, I am open to suggestions.
I have a User model.
Each user can speak 2 languages.
So I have 2 integer columns speak_1 and speak_2 in my DB.
Each integer correspond to one language :
1 -> french
2 -> english
etc.
I'd like to filter by facets all the users who speak one particular language (= all the user whith speak_1 or speak_2 attribute set to 1)
So I defined this indice :
has [speak_1, speak_2], as: :speak, type: :integer, facet: true
I was hoping it will work because this kind of attributes does :
has mobilities(:city_id), :as => :mobile_cities_ids
But it only consider the speak_1 values in my facets search then
Any idea ?
If you add :multi => true to the attribute definition and then run ts:rebuild, does that get things working? Although I would hope TS is smart enough to realise multiple columns means multiple values.
I have a table that stores queries that return a list of users.
I then have a method "get_public" to a "Banana" model that execute multiple queries using logic AND between them.
So, when I do
Banana.find(x).get_public I receive an Array of users (the ones suitable to that banana object).
The get_public method is like this:
def get_public
pb = []
banana_queries.each do |q|
pb << User.find_by_sql(q.query)
end
pb.inject(:'&')
end
But, would be great if I could get ActiveRecord::Relation instead. I want to do something like this after: Banana.find(x).get_public.where(...)
Any way to modify get_public and achieve this?
I am not sure I correcly undestood the problem, but I will try to help anyway.
As especified here
where returns an ActiveRecord::Relation
find (and its related dynamic methods) returns a single model object
So I suggest divide your queries into: 'joins' and 'where' fields. Your new code should look like something like this:
pb << User.joins(q.query_joins).where(q.query_where)
Also find methods will are deprecated in rails 4, so using where is recommended.
Hope I haven't missed the point too much :-)
Using sqlalchemy 0.7.2
Is there a way to find the table class from the query object? For example:
q = session.query(Customers)
how can I find Customers in q? Possible? Not Possible?
Yes. You need column_descriptions.
It's a long road to the table, though. sqlalchemy.orm.Query.column_descriptions returns a list of dicts, describing each query entity as it was given to query. in your example, there's only one entity, so you need the first item from that list. And since you're interested in the type of the query entity, rather than its' structure, you want the "type" key from that list:
q_entity = q.column_descriptions[0]['type']
assert q_entity == Customer
Accessing the table for the mapped class requires snooping around in the mapper subsystem. for that, you should use manager_of_class. The table is accessible from the manager through the mapper.mapped_table attribute:
from sqlalchemy.orm.attribute import manager_of_class
q_table = manager_of_class(q_entity).mapper.mapped_table
Resist the urge to skip strait to the mapper through Customer.__mapper__, or even Customer.__table__; That's specific to sqlalchemy.ext.declarative, and won't work with classes that are mapped by other means.