NoBrainerORM / nobrainer

Ruby ORM for RethinkDB
http://nobrainer.io/
Other
387 stars 49 forks source link

Associations in where #166

Closed kvaggelakos closed 8 years ago

kvaggelakos commented 8 years ago

I want to find all objects that don't have an associated model. The problem however is that nobrainer does not see the associative model as an attribute when building where queries, which I guess makes sense. I am unsure how to solve this problem though. Any ideas/help would be great.

To give you an idea for what I am trying to do by example: Profile:

has_one :github, dependent: :destroy

Github:

belongs_to :profile, required: true

Now I am trying to execute something like this:

pry(main)> Profile.where(:github.undefined => true)
NoBrainer::Error::UnknownAttribute: `github' is not a valid attribute of Profile
from ~/.rvm/gems/ruby-2.1.3/gems/nobrainer-0.29.0/lib/no_brainer/document/attributes.rb:158:in `ensure_valid_key!'
kvaggelakos commented 8 years ago

bump

nviennot commented 8 years ago

Oops sorry i thought I had replied to this already.

So has_one is like a has_many. It has no data. So you cannot query it at a class level. You'll have to do something more evolved to do this

nviennot commented 8 years ago

For example, you might want to maintain a integer num_github on the profile model and query it.

kvaggelakos commented 8 years ago

Thanks for the reply @nviennot.

Is this due to limitations in how rethinkdb works or nobrainer? Having a separate field num_github for a has_one relation doesn't make much sense, also it's kind of duplicating data. If possible I rather skip this method.

Would it be possible to do a subquery like an sql where not in style to get all profiles that don't have githubs with nobrainer? Is there a way to run rethinkdb commands straight?

Thanks for this awesome lib and all help.

nviennot commented 8 years ago

Here's what you can do:

class Profile
  include NoBrainer::Document

  has_one :github

  virtual_field :has_github do |doc|
    Github.without_ordering.where(:profile_id => doc['id']).to_rql.is_empty.not
  end
end

Now you can do Profile.where(:has_github => true)... and the has_github value will be returned as a virtual attribute. Essentially, you are computing the "num_github" variable on the fly.

If you know a better way in SQL, or with ActiveRecord, let me know, I'd like to see if I can do like them.

nviennot commented 8 years ago

If you wanted all profiles that had a github, it's easy:

Profile.join(:github).each { ... }

But if you want the ones that don't have a github, you'll have to do the virtual attribute method I'm afraid.