[MacRuby-devel] Would a macruby-newbie List Be Worthwhile?

John Shea johnmacshea at gmail.com
Wed Dec 16 22:34:22 PST 2009


Great answers from all the other folks.

Directly at the end of this mail I have my copied my version of the core data utility tutorial - but without NSPredicates. Created when I was trying to test binding and core data (turned out to be a different issue), that might help when you translate the real thing. Note that at the time was using setValue rather than .value= .

regarding:
> Let me be more specific about *why* this is important to me. My app goes out to a Web Service for data, so I have to fill some of it in programmatically, then it refreshes only occasionally. I decided this would be best in the controller, so it could be triggered by the user. To emulate that, I wanted to prepopulate the managedObject collection, and that I did in awakeFromNib. Warning: Make sure to call super! So what it boiled down to what this method in the controller:
> 
>  def new_image(image = {})
>    object = NSEntityDescription.insertNewObjectForEntityForName("Image",
>      inManagedObjectContext:managedObjectContext)
>    object.setValue image[:fileid], forKey: 'fileid'
>    object.setValue image[:title], forKey: 'title'
>    puts "#{object} #{object.fileid} : #{object.title}"
>  end
> 
> I used the setters explicitly when I was confused about why the bound tableview was blank. I'm beginning to get this a bit more under control, but the IB/CoreData/Cocoa Bindings is even magical to a Ruby person :)

I guess using setvalueforkey might be useful if you are running through the hash keys - and are not really sure what key values are coming down (otherwise object.title = image[:title] is nicer).
I also guess by now you are using an in memory store - not xml, since you are not storing anything locally.

As you can see from the code below if there is a key missing in your download I guess you could also just insert it as a new attribute into the entity - you could even auto add columns to the table view or custom view decorated by a nsscrollview.

I went down a similar route once and found there was so much meta that i could not test, nor debug easily nor concentrate on the business problem at hand.

As the others suggested - simpler is better - although you might like to still use the NSInMemoryStoreType. In which case you may need to prepareContent yourself manually since there are a view model/view time based dependancies that are normally handled for you with the other persistent store types.


Scott Stevenson's Core data tutorials are worth doing too.

Hope that helps.
John

framework "Cocoa"

### binding and observing setup
class Observa
  def initialize(obj)
    p "added observer"
    obj.addObserver(self, forKeyPath:"work", options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld, context:nil)
    obj.addObserver(self, forKeyPath:"energy", options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld, context:nil)
  end
  def observeValueForKeyPath(keyPath, ofObject:object, change:change, context:context)
    val = object.valueForKey(keyPath)
    p "keypath: #{keyPath} val:#{val} class:#{val.class}"
  end
end

class Copier
  attr_accessor :energy, :work
end


##core data setup

mom = NSManagedObjectModel.alloc.init
myEntity = NSEntityDescription.alloc.init
myEntity.setName("NumberTest")
myEntity.setManagedObjectClassName("NumberTest")
mom.setEntities([myEntity])


energy = NSAttributeDescription.alloc.init
energy.setName("energy")
energy.setAttributeType(NSFloatAttributeType)
energy.setOptional(false)
energy.setDefaultValue(123.45)


work = NSAttributeDescription.alloc.init
work.setName("work")
work.setAttributeType(NSDecimalAttributeType)
work.setOptional(false)
work.setDefaultValue(123.45)


output = NSAttributeDescription.alloc.init
output.setName("output")
output.setAttributeType(NSFloatAttributeType)
output.setOptional(false)
output.setDefaultValue(123.45)

tariff = NSAttributeDescription.alloc.init
tariff.setName("tariff")
tariff.setAttributeType(NSDecimalAttributeType)
tariff.setOptional(false)
tariff.setDefaultValue(300.34)

immutable_array = NSArray.arrayWithArray([energy, work, output, tariff])
myEntity.setProperties(immutable_array)

moc = NSManagedObjectContext.alloc.init
coordinator = NSPersistentStoreCoordinator.alloc.initWithManagedObjectModel(mom)
moc.setPersistentStoreCoordinator(coordinator)
 
error = Pointer.new(:object)
url = NSURL.fileURLWithPath("~/CDFloatTest.cdft")
 
newStore = coordinator.addPersistentStoreWithType(NSXMLStoreType,configuration:nil,URL:url,options:nil, error:error)

floater = NSManagedObject.alloc.initWithEntity(myEntity, insertIntoManagedObjectContext:moc)
##end core data setup

####start accessor, kvc and binding tests
p "standard accessor"
p floater.energy
p floater.work

p "keys"
p "#{floater.energy.class} #{floater.valueForKey("energy").class}"
p "#{floater.work.class} #{floater.valueForKey("work").class}"

p "set"
floater.energy = 456.67
p floater.energy
p "#{floater.energy.class} #{floater.valueForKey("energy").class}"

floater.work = 456.67
p floater.work #changes to NSDecimalNumber
p "#{floater.work.class} #{floater.valueForKey("work").class}"

avalue = Copier.new

options = {NSAllowsEditingMultipleValuesSelectionBindingOption => true}
avalue.bind("energy", toObject:floater, withKeyPath:"energy", options:options)
avalue.bind("work", toObject:floater, withKeyPath:"work", options:options)
obie = Observa.new(floater)

2.times do
  floater.setValue(rand(10) * 1.234, forKey:"work")
  sleep 1
  p "avalue work #{avalue.work}. #{avalue.work.class}"
end
p "--"
2.times do
  floater.setValue(rand(10) * 1.234, forKey:"energy")
  sleep 1
  p "avalue energy #{avalue.energy}. #{avalue.energy.class}"
end


On Dec 17, 2009, at 12:40 AM, Laurent Sansonetti wrote:

> 
> On Dec 16, 2009, at 2:25 PM, Brian Chapados wrote:
> 
>> On Wed, Dec 16, 2009 at 9:11 AM, steve ross <cwdinfo at gmail.com> wrote:
>>> On Dec 16, 2009, at 1:07 AM, John Shea wrote:
>>>> 
>>>> The second part, filling with data (presumably you will only need to do this once, because then the data can be saved with the app).
>>>> There are many ways to add data.
>>>> 
>>>> The easiest I reckon, is to add a method to the AppDelegate - called applicationDidFinishLaunching(notification) (delegated from the application singleton) and in that method you can do something like:
>>>> new_student = NSEntityDescription.insertNewObjectForEntityForName("Student", inManagedObjectContext:self.managedObjectContext).
>>>> Then set the attributes for that obj, eg student.name = "Bill".
>>> 
>>> Let me be more specific about *why* this is important to me. My app goes out to a Web Service for data, so I have to fill some of it in programmatically, then it refreshes only occasionally. I decided this would be best in the controller, so it could be triggered by the user. To emulate that, I wanted to prepopulate the managedObject collection, and that I did in awakeFromNib. Warning: Make sure to call super! So what it boiled down to what this method in the controller:
>>> 
>>> def new_image(image = {})
>>>   object = NSEntityDescription.insertNewObjectForEntityForName("Image",
>>>     inManagedObjectContext:managedObjectContext)
>>>   object.setValue image[:fileid], forKey: 'fileid'
>>>   object.setValue image[:title], forKey: 'title'
>>>   puts "#{object} #{object.fileid} : #{object.title}"
>>> end
>>> 
>>> I used the setters explicitly when I was confused about why the bound tableview was blank. I'm beginning to get this a bit more under control, but the IB/CoreData/Cocoa Bindings is even magical to a Ruby person :)
>>> 
>>> See? I told you it was a dumb question.
>>> 
>>> Thanks,
>>> 
>>> Steve
>>> _______________________________________________
>>> MacRuby-devel mailing list
>>> MacRuby-devel at lists.macosforge.org
>>> http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
>>> 
>> 
>> If MacRuby is your first exposure to mac programming and all of the
>> associated tools and techniques, starting out by jumping into an
>> IB-based project that uses CoreData & Bindings is going to be really
>> confusing.
>> 
>> I'd break up the tasks into pieces small enough that you can actually
>> understand what's going on. You shouldn't feel like things are
>> happening "magically". If that is the case, then try to take a step
>> back and figure out how the magic trick works.
>> 
>> For example, if you want to tackle CoreData first, then start with
>> just CoreData.  Build a command-line program that creates a CoreData
>> stack by reading in your compiled .xcdatamodel (or create the model in
>> code!), add some data, and save it.  Once you've got that working,
>> then make it download data from your web service and save it.
>> 
>> Here is the approach I would take:
>> 
>> 1. If you haven't already, read through the Core Data Programming guide:
>> http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/CoreData/cdProgrammingGuide.html
>> 
>> At the very least, browse through this to get a feel for what's going
>> on.  You won't understand everything, but at least you'll have some
>> sense of where to look when you get stuck.
>> 
>> 2. Read the Core Data Utility tutorial:
>> http://developer.apple.com/mac/library/documentation/cocoa/conceptual/CoreDataUtilityTutorial/Articles/00_introduction.html
>> 
>> This gives you a basic Obj-C version of a program the uses CoreData
>> entirely through the API.  Everything is done in code, even creating
>> the model, so it should get you started on something basic.
>> 
>> 3. As it turns out, Matt Gallagher (cocoawithlove.com) recently posted
>> an excellent article on parsing CSV files and importing the data into
>> CoreData: http://cocoawithlove.com/2009/11/writing-parser-using-nsscanner-csv.html
>> 
>> I highly recommend you also download and read through his code to see
>> how it works.
>> 
>> 4. Use the code from #2 & #3 to write a minimal implementation in
>> MacRuby that imports data into your model.
>> 
>> 5. After getting #4 to work, go back and read the section on
>> efficiently importing data in the CoreData programming guide and
>> refactor your import code appropriately.
>> 
>> At least this way, if you get stuck on #4 & #5, you'll have a fairly
>> short, self-contained example program that you can put in a gist, post
>> a link, and ask for help on specific parts.
>> _________________________________
> 
> And 6. Once you believe you understand how everything works, submit a sample code to us! :-)
> 
> Laurent
> _______________________________________________
> MacRuby-devel mailing list
> MacRuby-devel at lists.macosforge.org
> http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel



More information about the MacRuby-devel mailing list