(Disclaimer: New to Rails here)
Say I have a Rails ActiveRecord Model that responds to "id":
User.first.id # => 22
My life has changed, and now I need to get this same object via JSON call, and I want minimal code changes.
I do this:
uri = URI.parse("http://localhost:3001/user/")
uri.query = "query=id#{user_id}"
#user = JSON.parse(open(uri).read)
I can now do:
#user["id"]
However, this is not good enough because it would mean too many changes.
Is there any way to turn this into a real User object? or something that will act like one in a simple one (I probably can create a dummy object with constructor, but I'm looking for something that will do it for me, and I suspect there is a simple Rails-way for it).
I have found a possible solution to this problem:
https://github.com/sprysoft/json_object
However, I realized I actually need the original ActiveRecord Model and not a dummy object..
That said, to my specific question, above gem is a possible solution.
Related
I am trying to find a clean way to access the regmap that is used with *RegisterNode for creating documentation and testing files. The TLRegisterNode has methods for generating the json through some Annotations. These are done in the regmap method by adding them to the ElaborationArtefacts object. Other protocols don't seem to have these annotations.
Is there anyway to iterate over the "regmap" Register Fields post elaboration or during?
I cannot just access the regmap as it's not really a val/var since it's a method. I can't quite figure out where this information is being stored. I don't really believe it's actually "storing" any information as much as it is simply creating the hardware to attach the specified logic to the RegisterNode based logic.
The JSON output is actually fine for me as I could just write a post processing script to convert JSON to my required formats, but I'm wondering if I can access this information OR if I could add a custom function call at the end. I cannot extend the case class *RegisterNode, but I'm not sure if it's possible to add custom functions to run at the end of the regmap method.
Here is something I threw together quickly:
//in *RegisterRouter.scala
def customregmap(customFunc: (RegField.Map*) => Unit, mapping: RegField.Map*) = {
regmap(mapping:_*)
customFunc(mapping:_*)
}
def regmap(mapping: RegField.Map*) = {
//normal stuff
}
A user could then create a custom function to run and pass it to the regmap or to the RegisterRouter
def myFunc(mapping: RegField.Map*): Unit = {
println("I'm doing my custom function for regmap!")
}
// ...
node.customregmap(myFunc,
0x0 -> coreControlRegFields,
0x4 -> fdControlRegFields,
0x8 -> fdControl2RegFields,
)
This is just a quick example I have. I believe what would be better, if something like this was possible, would be to have a Seq of functions that could be added to the RegisterNode that are ran at the end of the regmap method, similar to how TLRegisterNode currently works. So a user could add an arbitrary number and you still use the regmap call.
Background (not directly part of question):
I have a unified register script that I have built over the years in which I describe the registers for a particular IP. It works very similar to the RegField/node.regmap, except it obviously doesn't know about diplomacy and the like. It will generate the Verilog, but also a variety of files for DV (basic `defines for simple verilog simulations and more complex uvm_reg_block defines also with the ability to describe multiple of the IPs for a subsystem all the way up to an SoC level). It will also print out C Header files for SW and Sphinx reStructuredText for documentation.
Diplomacy actually solves one of the main issues I've been dealing with so I'm obviously trying to push most of my newer designs to Chisel/Diplo.
I ended up solving this by creating my own RegisterNode which is the same as the rocketchip RegisterNodes except that I use a different Elaboration Artifact to grab the info and store it for later.
I've been playing around with this for a while now, and I think, I've - almost - cracked it, but I am still not fully satisfied with my solution.
So, what I want to do, is having a piece of content, a list of items, which would have two views: The standard HTML one, so people can view and edit it; and then a JSON endpoint for other services to consume.
First I thought it's a simple matter of creating two JSP scripts to render the content:
/apps/my-stuff/components/list-page/html.jsp
/apps/my-stuff/components/list-page/json.jsp
However the Apache Sling DefaultServlet seems to be rather ignorant of the json.jsp script.
As a second attempt, I created another script, in /apps/foundation/components/primary/cq/Page/json.jsp which will be actually called, and renders the page, as I expected. However there are a couple of worries/questions regarding this:
First of all, why is this being honoured by the system, and not the one in the more specific place?
The documentation states, that to find the appropriate renderer, first sling:resourceType will be inspected, then sling:resourceSuperType and then, only as a fallback will jcr:PrimaryType checked. However I think this is rather: jcr:PrimaryType, then the DefaultServlet, and then all the other things.
Most worryingly however, I have to admit, this is rather generic, so it'll break all the contnet with jcr:PrmaryType = Page, so that could have some side-effects.
A solution could be creating a new type: ListPage extends Page; and then create a renderer for that in /apps/foundation.... However I have this bad feeling, that might introduce other problems.
So my question is two fold: What is the proper way of doing this, and/or what am I missing from the way the URL -> script resolution is working in AEM/Sling. (Because it seems to be slightly different that described here and here.)
(Obviously I am trying to keep the default JSON renderer for other pages, as that might be needed for other things in the page. I am not even sure, changing this one page won't break the UI for this particular page...)
However the Apache Sling DefaultServlet seems to be rather ignorant of the json.jsp script.
Have you tried renaming your JSP like so: "list-page.json.jsp"?
If you're using AEM 6.3, you should look at Sling model Exporters. They allow you to automatically register a servlet against your Sling Model (that you can create to model your list content). That servlet can generate a JSON representation of the model for you using Jackson.
If you're not using AEM 6.3, I would suggest you create a servlet registered against your resource type and use an additional selector.
#SlingServlet(
selectors = "json",
resourceType = "my-stuff/components/list-page",
methods = "GET")
More information on Sling Servlets can be found here.
A rails service I am currently working on requires that points are returned as a GeoJSON object within our json response. We are using rgeo and the mysql2spatial adapter to represent these points in our application and I would like to use the rgeo-geojson gem to handle the encoding if possible (we already use it to decode geojson on post).
I am currently overwriting as_json with the following code to achieve this:
def as_json(params)
l = {:lat_lng => ::RGeo::GeoJSON.encode(lat_lng)}
self.attributes.merge(l).as_json
end
However this is not optimal as the root (eg object: {}) is missing. Is there a function to easily include it? (a lot of our models have a lat_lng associated, so I'd rather not hard code it).
Any tips for a ruby/rails beginner would be greatly appreciated
For posterity, I fixed this in the "rgeo-activerecord" gem, version 0.3.4, after getting several reports on it. By default it renders spatial columns in WKT. To switch it to GeoJSON, set this:
RGeo::ActiveRecord::GeometryMixin.set_json_generator(:geojson)
The answer by NielsV will work sometimes but not every time. Specifically, it will work for geographic factories (i.e. geometry columns in PostGIS) but not for GEOS-backed factories.
You can specify it by including root with this line of code:
ActiveRecord::Base.include_root_in_json = true
I Hope this helps.
I solved this by extending the RGEO library with an as_json method for a Point, doing this it's no longer required to overwrite as_json in my own models. Thanks for your response though.
module RGeo
module Feature
module Point
def as_json(params)
::RGeo::GeoJSON.encode(self)
end
end
end
end
I have some Rails 2.3.x code that I would like to run on Rails 3.0.3, but it seems to fail in my JSON to ActiveRecord code. Here is what I do:
mymodel = MyModel.new.from_json(json_string)
I get no errors here, but my object is empty as if there was no data in my json_string, but there is. If I look at the API (http://apidock.com/rails/ActiveRecord/Serialization/from_json) then it looks to me as it is not supported in 3.x, or?
I have tried with ActiveSupport::JSON.decode, but that decodes into a hashtable of key/values it seems?
Same problem here. The culprit is https://github.com/rails/rails/commit/c1d73270717f30498f8f4d55d6695509107c2834, here is an explanation: http://www.simonecarletti.com/blog/2010/04/inside-ruby-on-rails-serializing-ruby-objects-with-json/
The solution seems indeed to use
#obj.attributes = ActiveSupport::JSON.decode(json)
instead of "#obj.from_json(json)". At least for ActiveRecord objects, this works for me.
I started out looking at the JAX-RS plugin for grails and thought that was the way to go mainly because it was based on JSR-311 and I figure following standards is usually the smart thing to do. However, using Grail's UrlMappings it seems I basically achieve the same thing. I figure I'm missing something, however, we aren't doing anything overly complex. We basically just need to expose CRUD via an API. Example of doing the same thing with both versions:
JAX-RS:
#PUT
#Consumes(['application/json'])
#Produces(['application/json'])
Response putUser(User user) {
user.save(flush:true)
ok user
}
Grails:
def update = {
def user = new User(params['user'])
user.save(flush:true)
render user as JSON
}
Obviously, this is an overly-simplified example and like I said, maybe I'm missing something important. Also, the nice thing about the Grails built in mechanism is I can utilize Content Negotiation along with it.
Anyone have any opinions on this?
I had to make the same decision, and I found it just easier to use URL Mappings because the API was not that complex and there were a limited number of API calls that needed to supported.
If came down to what would be easier to maintain based on the LOE and the resources able to support the implementation.
The jax-rs plugin is very useful if you are creating web services straight to your domain models. It gives you a "generate-resource" command that automatically creates CRUD apis for your model.
grails generate-resource mydomain.Model
This part seems to work fine, however, I encountered quite a few bugs/problems with the plugin that I finally had to implement the REST services using URL-mappings.
Although the URL-mapping method seems to be more coding, it works perfectly.
import grails.converters.JSON
class ModelServiceController {
def id = params.id
def myModel = MyModel.findById(id)
render myModel as JSON
}
Here's the link for grails REST
http://grails.org/doc/1.0.x/guide/13.%20Web%20Services.html