Rails Create an object Array of my class? - ruby-on-rails

Example java code is below if I have a class Movie
In java I will create its array by writing below code
Movie[] a = new Movie[4];
but how I can do it in rails So that when I check it on the console
#> a.type
#> "Movie"
Reather than
#> ActiveRecord::Relation

You just create a class by inherited from Array like below,
class MyArray < Array
#Add you custom methods
end
my_array = MyArray.new([1,2,3,4,5]) or
my_array = MyArray.new
my_array[0] = 1
my_array[1] = 2
That enough for basic customization of array data structure.

Literal translation would be
a = (1..4).map { Movie.new }
or (in Rails)
a = (1..4).map { Movie.create! }
but you normally shouldn't need to do it, since unlike in Java, you don't have limited-size arrays in Ruby.
Also, the type of that would then be Array (or rather its class; basic Ruby objects don't have type); the type of an element of that, a[0] for example, would be a Movie.
In the end, not quite sure what you're asking here...

Related

Groovy Equivalent: javascript object methods

In JavaScript you can do the following:
var obj = {
property: 1,
method1: function() {
//...
},
method2: function() {
//...
}
};
obj.method1()
I am wondering if there is a groovy equivalent for this (a map containing a method). I know this is just like a class, but I dont want a class ha..
Yes, you can put closures inside a map. But this is not the way to get
objects in Groovy. There is no concept of "this", that knows about the
map.
def obj = [
inc: { it + 1 }
]
println obj.inc(10)
Ok so Javascript is not OOP. They have OBJECTS but that is it. What you are showing is an OBJECT.
In Groovy, you can do this with a class that can instantiate the object and then you can do that on the object. For example you can create a CommandObject (which is what you are probably wanting) and then fill in the properties like you want or fill them in on instantiation. For example (using above example):
def paramsDesc = new ParamsDescriptor()
paramsDesc.paramType = 'paramtype'
paramsDesc.keyType = 'keyType'
paramsDesc.name = 'name'
paramsDesc.idReferences = 'id'
paramsDesc.description = 'desc'
paramsDesc.mockData = 'mock'
paramsDesc.values = []
OR (if you create a constructor) you can instantiate all at once:
def paramsDesc = new ParamsDescriptor('paramtype','keyType','name','id','desc','mock',[])
CommandObjects can have methods and functions (like above). But you just have to instantiate them first (def paramsDesc = new ParamsDescriptor())
This is the difference between a class and an object; think of a class as the blueprint and the object as what is created from the blueprint.

Building a map for parallel step from directory names [duplicate]

For example, the groovy File class has a nice iterator that will filter out just directories and not files:
void eachDir(Closure closure)
When I use eachDir, I have to use the verbose method of creating the collection first and appending to it:
def collection = []
dir1.eachDir { dir ->
collection << dir
}
Any way to get it back to the nice compact collect syntax?
I don't know of any "idiomatic" way of doing this, nice riddle! =D
You can try passing the eachDir, or any similar function, to a function that will collect its iterations:
def collectIterations(fn) {
def col = []
fn {
col << it
}
col
}
And now you can use it as:
def dir = new File('/path/to/some/dir')
def subDirs = collectIterations(dir.&eachDir)
def file = new File('/path/to/some/file')
def lines = collectIterations(file.&eachLine)
(that last example is equivalent to file.readLines())
And only for bonus points, you may define this function as a method in the Closure class:
Closure.metaClass.collectIterations = {->
def col = []
delegate.call {
col << it
}
col
}
def dir = new File('/path/to/some/dir')
def subDirs = dir.&eachDir.collectIterations()
def file = new File('/path/to/some/file')
def lines = file.&eachLine.collectIterations()
Update: On the other hand, you might also do:
def col = []
someDir.eachDir col.&add
Which I think is quite less convoluted, but it's not leveraging the collect method as you requested :)
Not for the specific example that you're talking about. File.eachDir is sort of a weird implementation IMO. It would have been nice if they implemented iterator() on File so that you could use the normal iterator methods on them rather than the custom built ones that just execute a closure.
The easiest way to get a clean one liner that does what you're looking for is to use listFiles instead combined with findAll:
dir1.listFiles().findAll { it.directory }
If you look at the implementation of eachDir, you'll see that it's doing this (and a whole lot more that you don't care about for this instance) under the covers.
For many similar situations, inject is the method that you'd be looking for to have a starting value that you change as you iterate through a collection:
def sum = [1, 2, 3, 4, 5].inject(0) { total, elem -> total + elem }
assert 15 == sum

Groovy - with closure with multiple references

I'm trying to parse a JSON data and assign it to a POJO in Grails.
I started with
obj.param=jsonRequest.jsonWrap.attrib.something.jsonParam
After some experimenting and refactoring, it looks like this now.
jsonRequest.jsonWrap.attrib.something.with {
obj.param1=jsonParam1
obj.param2=jsonParam2
//...
}
}
Now, can I avoid the repeated use of obj reference?
I'm imagining that your actual starting point is something like the following. On the JSON side:
import groovy.json.JsonSlurper
String jsonText = '''{
"jsonWrap":{
"attrib":{
"something":{
"jsonParam1": "value1",
"jsonParam2": "value2",
"jsonParam3": "value3",
"jsonParam4": "value4",
"jsonParam5": "value5"
}
}
}
}'''
def jsonRequest = new JsonSlurper().parseText(jsonText)
On the Groovy side:
class ObjectType {
def param1, param2, param3, param4, param5
}
def obj = new ObjectType()
Now, if I had any control over how either the JSON side or the Groovy side are defined then I would do my darnedest to ensure that the property names of the JSON "something" object are exactly the same as the property names in the Groovy "ObjectType" class. For example, like this:
class ObjectType {
def jsonParam1, jsonParam2, jsonParam3, jsonParam4, jsonParam5
}
Then, unmarshalling the "something" object into Groovy is as simple as this:
def obj = new ObjectType(jsonRequest.jsonWrap.attrib.something)
Only one reference to the JSON object. Only one reference to the Groovy object. And the former is used to instantiate the latter. And furthermore, notice that there is no need to reference the properties at all. That is, JSON objects from the slurper are instances of Map, so if the property names match up, you can use the default "Map constructor" syntax.
If, however, you do not control property naming in either set of objects, I would still recommend a different Map-based short-cut. First define a constant Map from one set of property names to the other, like so:
def map = [param1:"jsonParam1", param2:"jsonParam2", param3:"jsonParam3",
param4:"jsonParam4", param5:"jsonParam5"]
Then I would use something like this for the object unmarshalling:
def obj = new ObjectType().with { o ->
jsonRequest.jsonWrap.attrib.something.with { j ->
map.each { oParam, jParam -> o[oParam] = j[jParam] }
}
o
}
i don't think there is a trivial way to trick groovy into "use objectA, if getting is needed and objectB for setting". If obj above is a map or you can apply a map to this object, then you could produce a map in your with block and use this. If you have to have nested structures then more work is needed.
def jsonParam = new Expando([ p1: 'p1', p2: 'p2', p3: 'p3', ])
def obj = new Expando(
jsonParam.with{
[
param1: p1,
param3: p3,
] // `with` will return this map
})
assert obj.param1==jsonParam.p1
assert obj.param3==jsonParam.p3
I use expandos for simple code.

How to save a collection all at once in Grails

For example I need to retrieve several registers in a table, and edit a field, but it takes too long to save all with a loop, does exist a better way to save?
This how I do it....
class Table
static mapping = {
table "TABLEEX"
id generator:'sequence', params:[sequence:'TABLEEX_SEQ']
}
// identificacion
String data1
String data2
}
And searching the data:
def stuff = Table.createCriteria().list{
eq("data1","1")
}
And editing and saving
stuff.each {
it.data2 = "aaa"
it.save()
}
It isn't clear why you are retrieving the objects to begin with. Is something like this what you are looking for?
Table.executeUpdate("update Table t set t.data2=:newData where t.data1=:oldData", [newData: 'BAR', oldData: 'FOO'])
EDIT
You could also do something like this...
def query = Table.where {
data1 == 'FOO'
}
int total = query.updateAll(data2:'BAR')
Hibernate (the underlying mechanism of gorm, the grails orm) does not support that.
You'll have to iterate over every element and save or implement it yourself (and that will not make it faster).

How does one keep an array representative of its class?

If I take a number Object like so :
#objects = Object.all[1..5]
I no longer can perform a where method on #object.
Is there anyway, I can still perform..
#objects.where(:attribute => identity)
So long as I know all the objects are of the same class?
Once you triggered all an Array instance is returned, so answer to your question is no. There are some gotchas, though:
Keep a scope variable. I.e. if you need to use a scoped object in multiple places, do the following:
objects = Object.scoped
all_objects = objects.all
special_objects = objects.where(attribute: something_special).all
Continue playing with scoping:
objects = Object.skip(1).take(5)
all_objects = objects.all
special_objects = objects.where(attribute: something_special).all
Hacky and inefficient way:
all_objects = Object.all[1..5]
special_objects = object.select { |object| object.attribute == something_special }

Resources