modernistik / parse-stack

Parse Server Ruby Client SDK
https://www.modernistik.com/gems/parse-stack/
MIT License
61 stars 20 forks source link

belongs_to returns pointer when defining subclasses #26

Closed oclef closed 7 years ago

oclef commented 7 years ago

If I do Parse.auto_generate_models!, I can go through the belongs to association fine

Song.first.author.name

However if I define my classes

class Song < Parse::Object property :name belongs_to :artist end

class Artist < Parse::Object property :name end

and do not do Parse.auto_generate_models!

Song.first.author.name will throw an error

Song.first.author.class will be

Parse::Pointer

apersaud commented 7 years ago

Can you provide the error for the Song.first.author.name and an example app I can use for testing?

Also, can you confirm the Song and Artist were previously defined in your Parse Server (otherwise you might have needed to run Parse.auto_ugprade!).

oclef commented 7 years ago

Here is what happen when I don't auto generate models.

Using rails 5.0.1

Here are my model definitions

class Collection < Parse::Object property :opus, :string property :title, :string property :coverImageURLs, :array

belongs_to :composer belongs_to :publisher, as: :collection_publisher

end

class Composer < Parse::Object property :lastName, :string property :firstName, :string property :imageURL, :string

has_many :collections

end

irb(main):004:0> collection = Collection.first => #<Collection:0x007fef0e3a3bd0 @id="00UQtxtRNv", @composer=#<Parse::Pointer:0x007fef0e3a3360 @parse_class="Composer", @id="wQTUnzSpww">, @title="Albumleaves", @created_at=Thu, 17 Dec 2015 06:25:28 +0000, @updated_at=Thu, 17 Dec 2015 06:25:28 +0000, @changed_attributes={}, @acl=ACL({"*"=>{"read"=>true, "write"=>true}}), @previously_changed={}> irb(main):005:0> composer = collection.composer => #<Parse::Pointer:0x007fef0e3a3360 @parse_class="Composer", @id="wQTUnzSpww"> irb(main):006:0> composer.name NoMethodError: undefined method `name' for #

apersaud commented 7 years ago

Thanks. Will look into it. I assume you are using the latest version?

oclef commented 7 years ago

Thank you

apersaud commented 7 years ago

Hi @oclef,

There is also an issue where name is not defined as a property to your model Composer, it should probably be firstName?

I ran the sample models you had against a new Parse Server:

Parse.setup # configure Parse here with your keys

puts "[ParseServerURL] #{Parse.client.server_url}"
puts "[ParseAppID]     #{Parse.client.app_id}"

class Collection < Parse::Object
  property :opus, :string
  property :title, :string
  property :coverImageURLs, :array
  belongs_to :composer
end

class Composer < Parse::Object
  property :lastName, :string
  property :firstName, :string
  property :imageURL, :string

  has_many :collections
end

require "pry"
Pry.start

And running this on the command line, everything worked properly:

pry(main)> collection = Collection.first
=> #<Collection:0x007fd18d0a6750
 @acl=ACL({"*"=>{"read"=>true, "write"=>true}}),
 @changed_attributes={},
 @composer=
  #<Composer:0x007fd18d0a6020
   @acl=ACL({"*"=>{"read"=>true, "write"=>true}}),
   @changed_attributes={},
   @fetch_lock=false,
   @id="kauLQ7SkGQ",
   @previously_changed={}>,
 @created_at=Sat, 28 Jan 2017 22:27:00 +0000,
 @id="nRnPjDLeIn",
 @previously_changed={},
 @title="my collection",
 @updated_at=Sat, 28 Jan 2017 22:27:07 +0000>
[3] pry(main)> collection.composer
=> #<Composer:0x007fd18d0a6020
 @acl=ACL({"*"=>{"read"=>true, "write"=>true}}),
 @changed_attributes={},
 @fetch_lock=false,
 @id="kauLQ7SkGQ",
 @previously_changed={}>
[5] pry(main)> collection.composer.firstName
=> "myComposer"

Also checking the class registration, seems to be mapping it to the correct class: (can you try this too in your setup?)

# Verify the "Composer" collection name maps to the `Collection` class
Parse::Model.find_class "_User" # => Parse::User
Parse::Model.find_class "Composer" # Composer
# Check to make sure the belongs_to reference for `composer` maps to the "Composer" class
Collection.references # => {:composer=>"Composer"}

Are those model files defined in the same file, or are they being loaded at different times? Parse-Stack requires all model files to be eagerly loaded so it can build all the relationships.

oclef commented 7 years ago

The model files are defined in different files.

My classes don't seem to be registering correctly.

irb(main):001:0> Parse::Model.find_class "_User" => Parse::User irb(main):002:0> Parse::Model.find_class "Composer" => nil irb(main):003:0> Collection.references => {:composer=>"Composer", :publisher=>"CollectionPublisher"}

apersaud commented 7 years ago

It seems that the 'Composer' class is not being loaded. I would check on how you are booting the rails app and debug it from there.

oclef commented 7 years ago

OK, thanks.

I ran the rails app in production mode and it works fine.

oclef commented 7 years ago

Changing this config in development.rb does it

config.eager_load = true

apersaud commented 7 years ago

One think you can do is require the dependent class files in your Collection model as well. I will close the issue.