I want to use https://github.com/cleverage/play2-elasticsearch in my play project where I am using slick2.0 for database interactions. But unfortunately I can't find any proper documentation or example which could help me get started.
I don't know well Slick, but I suppose that your data is represented as case class instances.
In this case, you can look at the Scala sample of the module, especially, the IndexTest class : https://github.com/cleverage/play2-elasticsearch/blob/master/samples/elasticsearch-scala/app/indexing/IndexTest.scala . First, you will see that your case class needs to extend the Indexable trait. Then that you have to define an IndexableManager for your class that is used to specify the ES type to use and the Json reads and writes for converting your data (you can just use the Json.reads / Json.writes macro for a basic usage).
Then you can look at the sample controller that show the usage of the IndexableManager to index, delete and search indexed data : https://github.com/cleverage/play2-elasticsearch/blob/master/samples/elasticsearch-scala/app/controllers/Application.scala
Related
I'm attempting to parse json from the GitHub API with play-json, and encountering a problem with the merge_commit_sha field on Pull Requests (incidentally, I know this field is deprecated, but don't want to discuss that in this parsing problem!). Unfortunately merge_commit_sha field comes back as the empty string in some cases:
"merge_commit_sha": ""
This is how the field is declared in my case class:
merge_commit_sha: Option[ObjectId],
I have an implicit Format[ObjectId], which does not tolerate the empty string, because that's not a valid value for a Git hash id. I'm also using a play-json macro-generated Read[PullRequest], which I'd like to keep on using, in preference to individually declaring reads for every single field on pull requests.
As I've declared the field to be an Option, I'd like "merge_commit_sha": "" to be read as the value None, but this is not what currently happens - a string is present, so the Format[ObjectId] is invoked, and returns a JsFailure.
One thing I tried was declaring an implicit Format[Option[ObjectId]] with the required behaviour, but it didn't seem to get used by the macro-generated Read[PullRequest].
You can define a custom Reads and Writes yourself.
Using Json.format[MyType] uses a Scala macro. You may be able to hook into that. Although, 'extending' a macro for this one case class just seems wrong.
Custom Reads and Writes might be a little 'boilerplate-like' and boring, but they have their upsides.
For example if your json has a bunch of new fields on it, you wont get a JsError when validating or transforming it to a case class. You only take what you need from the JSON and create objects. It also allows for a separation between your internal model and what you're consuming, which in some cases is preferred.
I hope this helps,
Rhys
EDIT
After using some other JSON libs I may have found what you are looking for.
I know the question was asking specifically after Play JSON.
If you're able to move away from Play JSON, Look at spray-json-shapeless specifically JsNullBehaviour and JsNullNotNone REF.
I have a use case where I need to create a class based on user input.
For example, the user input could be : "(Int,fieldname1) : (String,fieldname2) : .. etc"
Then a class has to be created as follows at runtime
Class Some
{
Int fieldname1
String fieldname2
..so..on..
}
Is this something that Scala supports? Any help is really appreciated.
Your scenario doesn't seem to make sense. It's not so much an issue of runtime instantiation (the JVM can certainly do this with reflection). Really, what you're asking is to dynamically generate a class, which is only useful if your code makes use of it later on. But how can your code make use of it later on if you don't know what it looks like? For example, how would your later code know which fields it could reference?
No, not really.
The idea of a class is to define a type that can be checked at compile time. You see, creating it at runtime would somewhat contradict that.
You might want to store the user input in a different way, e.g. a map.
What are you trying to achieve by creating a class at runtime?
I think this makes sense, as long as you are using your "data model" in a generic manner.
Will this approach work here? Depends.
If your data coming from a file that is read at runtime but available at compile time, then you're in luck and type-safety will be maintained. In fact, you will have two options.
Split your project into two:
In the first run, read the file and write the new source
programmatically (as Strings, or better, with Treehugger).
In the second run, compile your generated class with the rest of your project and use it normally.
If #1 is too "manual", then use Macro Annotations. The idea here is that the main sub-project's compile time follows the macro sub-project's runtime. Therefore, if we provide the main sub-project with an "empty" class, members can be added to it dynamically at compile time using data that the macro sees at runtime. - To get started, Modify the macro to read from a file in this example
Else, if you're data are truly only knowable at runtime, then #Rob Starling's suggestion may work for you as it did me. I'll share my attempt if you want to be a guinea pig. For debugging, I've got an App.scala in there that shows how to pass strings to a runtime class generator and access it at runtime with Java reflection, even define a Scala type alias with it. So the question is, will your new dynamic class serve as a type-parameter in Slick, or fail to, as it sometimes does with other libraries?
As a simplest example, say I'm starting my application in a certain mode (e.g. test), then I want to be able to check in other parts of the application what mode I'm running in. This should be extremely simple, but I'm looking for the right Scala replacement for global variables. Please give me a bit more than : "Scala objects are like global variables"
The ideal solution is that at start-up, the application will create an object, and at creation time, that object's 'mode' is set. After that, other parts of the application will just be able to read the state of 'mode'. How can I do this without passing a reference to an object all over the application?
My real scenario actually includes things such as selecting the database name, or singleton database object at start-up, and not allowing anything else to change that object afterwards. The one problem is that I'm trying to achieve this without passing around that reference to the database.
UPDATE:
Here is a simple example of what I would like to do, and my current solution:
object DB{
class PDB extends ProductionDB
class TDB extends TestComplianceDB
lazy val pdb = new PDB
lazy val tdb = new TDB
def db = tdb //(or pdb) How can I set this once at initialisation?
}
So, I've created different database configurations as traits. Depending on whether I'm running in Test or Production mode, I would like to use the correct configuration where configurations look something like:
trait TestDB extends DBConfig {
val m = new Model("H2", new DAL(H2Driver),
Database.forURL("jdbc:h2:mem:testdb", driver = "org.h2.Driver"))
// This is an in-memory database, so it will not yet exist.
dblogger.info("Using TestDB")
m.createDB
}
So now, whenever I use the database, I could use it like this:
val m = DB.db.m
m.getEmployees(departmentId)
My question really is, is this style bad, good or ok (using a singleton to hold a handle to the database). I'm using Slick, and I think this relates to having just one instance of Slick running. Could this lead to scalability issues.
Is there a better way to solve the problem?
You can use the typesafe config library, this is also used in projects like Play and Akka. Both the Play and Akka documentation explain basic parts of it's usage. From the Play documentation (Additional configuration)
Specifying alternative configuration file
The default is to load the application.conf file from the classpath. You can specify an alternative configuration file if needed:
Using -Dconfig.resource
-Dconfig.resource=prod.conf
Using -Dconfig.file
-Dconfig.file=/opt/conf/prod.conf
Using -Dconfig.url
-Dconfig.url=http://conf.mycompany.com/conf/prod.conf
Note that you can always reference the original configuration file in a new prod.conf file using the include directive, such as:
include "application.conf"
key.to.override=blah
Not sure if i'm using the right vocabulary. In the browsable api that comes for free with django-rest-framework, I was wondering if there was a way to autogenerate a form similar to how we define ModelForms. This would allow us to more easily test input to the API in some cases.
I'm currently using ModelSerializers and the generic view APIView in case that makes a difference.
I have read the documentation (several times at this point) but didn't see it mentioned anywhere.
If you're using the generic class-based-views you'll get that for free. Try the live tutorial at http://restframework.herokuapp.com logging in as one of the users, so that you can create some snippets. eg user: 'max', password: 'max'.
Any views subclassing GenericAPIView and setting a serializer_class will get that behavior, as REST framework can determine what the form should look like.
For example:
(Note the form input at the bottom of the screen shot)
If you're just working from APIView you'll get the generic content input (such as json), like the once you've included a screenshot of, which is also useful, but not quite as convenient as the forms.
Create a serialiser class that fits the form input fields you want and set it on your APIView like so;
class MyView(APIView):
serializer_class = MySerializer # Used for the form in the browsable api
That works just perfectly.
Example of a serializer class based on a model:
from rest_framework import serializers
class MySerializer(serializers.ModelSerializer):
class Meta:
model = MyModel
class MyApiView(APIView):
"""My Demo API View"""
serializer_class = serializers.MySerializers
Make sure you're using the name "serializer_class" and not any other name like serializers_class.
using the exact "serializer_class" will autogenerate form in the browseable API
i have a kohana-based website, and i want to use zend-lucene search.
as i have seen in the documentation here https://github.com/evopix/kohana-search/blob/master/README.markdown but i do not understand: must i re-create the models i already have in order to be able to use it? the model should extend the ORM_Searchable (it is a must)? and where can i find the ORM_Searchable class in kohana?
thanks a lot!
You don't have to recreate the models. You extend from a new class, implement its methods which specify what data you want to be indexed by Zend Lucene. The documentation is really straight forward.
the model should extend the ORM_Searchable (it is a must)? and where can i find the ORM_Searchable class in kohana?
This is in the code repository you linked to. classes/kohana/orm/searchable.php