ActiveRecord::Relation mystery - ruby-on-rails-3

Please explain why:
User.first.comments.class => Array
User.first.comments.missing_method => undefined method `missing_method' for []:ActiveRecord::Relation
Why in the first line class is Array and the other is Relation?

User.first.comments actually returns an AssociationProxy object. You're getting an Array when you call User.first.comments.class because the class method is undefined and being delegated elsewhere.
Check out How do rails association methods work?

Because method User.first.comments exist and it has return value array and missing_method doesn't exist for Relation comments. comments is ActiveRecord::Relation method with return value array.

Related

Using KVC to get a list of objects' properties

In this SO post, the chosen answer uses the syntax below to get a list of frequentFlyerNumbers from a list of passengers this way.
NSArray *frequentFlyerNumbers =
someFlight.passengers.frequentFlyerNumbers;
How is this possible given that passengers is an array and compiler can't infer the type that goes into the array?
I got the following error when implementing passengers.
Property 'frequentFlyerNumbers' not found on object of type
'NSMutableArray *'
The answer you cite is poorly written. The code as presented there won't work.
Dot-syntax, in plain code, is just shorthand for an accessor: someFlight.passengers means [someFlight passengers], which from the context appears to return a NSMutableArray. NSMutableArray of course doesn't have a frequentFlyerNumbers property itself.
To get the effect you want, do something like this:
NSArray *frequentFlyerNumbers = [someFlight valueForKeyPath:#"passengers.frequentFlyerNumbers"];
This will work, and return an array of frequentFlyerNumbers. When there's an array or set along a key path, it "projects" the subsequent path across all members of that array or set, producing an array or set of the results.

Sorting objective-C array: where does 'element' come from?

I'm reading a book on Objective-C. A part dealing with sorting arrays in an Addressbook. The sort method is like this:
- (void) sort
{
[book sortUsingSelector: #selector(compareNames:);
}
The 'compareNames' method is like this:
//Compare the two names from the specified address cards
-(NSComparisonResult) compareNames: (id) element
{
return [name compare: [element name]];
}
I kinda can see how it works. By comparing each element of the array to the next until all the 'names' are swapped in alphabetical order.
What I don't get (as it hasn't been mentioned earlier) is where the '(id) element' argument comes from? The 'name' I get cause that's been initialized earlier. But where does 'element' come from? Is that a fixed object that comes with NSArray? Earlier is described how to print an element by e.g. NSLogging nummer[1]. In case of this address book one element or card in that book could be printed by NSLogging book[32]. But how does 'element' fit in that?
The 'name' I get cause that's been initialized earlier.
I'm not sure you understand how this works. The method corresponding to the sorting selector must compare two objects that are members of the array. No "static" objects, no ahead-of-time-initialized stuff, nothing.
This method will be called on an object in the array, and its argument will be another object in the array, to which it should compare the first object (its self argument). The implementation of sortUsingSelector: uses the return value of this method to decide if two objects are in the right order. Internally, it is called like this:
id oneObject = array[firstIndex];
id otherObject = array[secondIndex];
NSComparisonResult cmpRes =
[oneObject performSelector:#selector(comparisonSelector)
withObject:otherObject];
if (cmpRes == NSOrderedDescending) {
// swap the objects if they're in the wrong order
}
Maybe the asymmetry is confusing; in principle, NSArray could as well use a freestanding function that takes two objects and returns the comparison result. Actually, there indeed is a method (sortUsingComparator:) that takes a block which isn't called "on an object" (since it's not a method), but it's simply called with two arguments: the two objects to compare.
It's pretty simple. The sorting algorithm is based on object-comparison. Let's say we have 3 objects in the array: [A, B, C].
Then the method compareNames: is called on the following objects:
[A compareNames:B]
[B compareNames:C]
[A compareNames:C]
The element is just some other object in the array.

How NSSet compares values in array to remove duplicates when using SetWithArray

I have NSArray and I want to remove duplicates from it. I know that using this method
[NSSet setWithArray:[arrAllValues valueForKey:#"value"]]
I also know that it invokes method specified in valueForKey parameter. But I don't know what method NSSet invokes to compare objects in array.
My problem is that I want to compare property named "value", but I want to return array of the object that contains the property and not the property. Can I do that?
Thanks !!!
It compares them using the NSObject protocol reference method:
- (BOOL)isEqual:(id)anObject
therefore, you can override this method in your class to implement the desired behavior, as a note just like you would do it in Java, you should also override hash.

Accessor that returns value vs accessor that returns reference?

From my understanding both of the following getter methods reference the actual object.
So what is the difference between the two?
When and why would you want to use the second getter method?
- (MyObject *)myObject
{
return _myObject;
}
- (void)getMyObject:(MyObject **)myObject
{
if (!myObject)
{
*myObject = _myObject;
}
}
You would not use the second one.
Unless you like confusing people/yourself at a later date by not following the standard conventions.
It would make more sense if there was another piece of data that could also be returned for example look at NSManagedObjectContext
- (BOOL)save:(NSError **)error
The important result of the method is YES/NO did it save, but then we can also get an NSError object to inspect if there was an error.
In Objective C, an "object" is a C pointer, so an object value is actually already the same as a structure reference (an opaque structure with hidden fields if you want the code to be portable between Objective C runtimes).
So there is no "versus".
YouR first example is both.
There are special situations when an algorithm needs a reference to a reference, or a pointer to a pointer, but not very commonly. That would be your second example.

Instance pointers in an array

I'm trying to save pointers of class instances into a mutable array. I'm able to do this but getting them back into use seems to be a problem. The next is how I inserted the pointers into the array:
Class *class = [Class new];
/* Do something with the instance */
[instanceArray addObject:class];
I am able to retrieve the wanted index from the array but when I try to access the instance variables etc. I only get compiler shouting at me or sometimes I get every variable as zero.
How am I supposed to get the instance back to use from the array? I know they are pointers but playing with them didn't seem to work.
Using addObject: the element is inserted at the end of the array. To retrieve it you can use -[NSArray objectAtIndex:]
Pointer arithmetic works in C since then your array is just a pointer to the first index, and array[i] is the same as *(array + i). In Objective-C this may still be done, however you're using an NSArray object. Now you don't have a pointer to the first object anymore, but to the instance of the class. To retrieve the objects stored in the array, you'll have to call the corresponding methods.
EDIT
So you are able to retrieve it from the array and then your pointer is not nil, so you do have access to the object. You know in Objective-C, all instance variables are private so you can't access them from outside. You'd have to declare them as properties first (please refer to the documentation). Also, when you declare a variable to be of type id, accessing a property with dot-syntax doesn't work, it will cause a compiler error.