Skip to content

Instantly share code, notes, and snippets.

@rlivsey
Created September 13, 2009 22:03
Show Gist options
  • Select an option

  • Save rlivsey/186348 to your computer and use it in GitHub Desktop.

Select an option

Save rlivsey/186348 to your computer and use it in GitHub Desktop.
# returns duplicates, essentially the same as the datamapper query
SELECT books.*
FROM books
INNER JOIN readers ON readers.book_id = books.id
WHERE readers.user_id = xxx OR books.private = FALSE
# gets rid of the duplicates because of the DISTINCT
SELECT DISTINCT books.*
FROM books
INNER JOIN readers ON readers.book_id = books.id
WHERE readers.user_id = xxx OR books.private = FALSE
#!/usr/bin/env ruby -KU
require 'rubygems'
require 'do_sqlite3'
require 'dm-core'
require 'pp'
DataMapper.logger = DataMapper::Logger.new($stderr, :debug)
DataMapper.setup(:default, 'sqlite3://memory')
class User
include DataMapper::Resource
property :id, Serial
property :name, String
has n, :readers
has n, :books, :through => :readers
end
class Reader
include DataMapper::Resource
belongs_to :user
belongs_to :book
property :id, Serial
property :book_id, Integer
property :user_id, Integer
end
class Book
include DataMapper::Resource
property :id, Serial
property :name, String
property :private, Boolean, :default => true
has n, :readers
def self.accessible_by(user)
all(
:links => [Book.relationships[:readers]],
:conditions => ["(readers.user_id = ? OR books.private = ?)", user.id, false]
)
end
end
DataMapper.auto_migrate!
tom = User.create(:name => "tom")
dick = User.create(:name => "dick")
harry = User.create(:name => "harry")
public_book = Book.create(:name => "public", :private => false)
private_book = Book.create(:name => "private")
Reader.create(:user => tom, :book => private_book)
Reader.create(:user => dick, :book => public_book)
Reader.create(:user => harry, :book => public_book)
pp Book.accessible_by(tom) 
# This outputs the following:
# => [#<Book id=1 name="public" private=false>, #<Book id=1 name="public" private=false>, #<Book id=2 name="private" private=true>]
# Obviously I want just:
# => [#<Book id=1 name="public" private=false>, #<Book id=2 name="private" private=true>]
class Book
include DataMapper::Resource
property :id, Serial
property :name, String
property :private, Boolean, :default => true
has n, :readers
def self.accessible_by(user)
all(
:links => [Book.relationships[:readers]],
:conditions => ["(readers.user_id = ? OR books.private = ?)", user.id, false],
# add this!
:unique => true
)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment