Skip to content

Commit

Permalink
Closes #4 - Included model scopes break on includes and joins
Browse files Browse the repository at this point in the history
  • Loading branch information
Chris Peters committed Jun 3, 2014
1 parent 75547f9 commit 0ab221b
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 23 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,9 @@
# CHANGELOG

## v0.2 - June 3, 2014

- Fixed [#4](https://github.com/live-editor/draftsman/issues/4) - Added `referenced_table_name` argument to scopes.

## v0.1.1 - March 7, 2014

- Fixed [#3](https://github.com/minimalorange/draftsman/issues/3) - draft_publication_dependencies not honoring drafts
Expand Down
2 changes: 1 addition & 1 deletion Gemfile.lock
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
draftsman (0.1.1)
draftsman (0.2)
activerecord (>= 3.0, < 5.0)

GEM
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright (c) 2013 Minimal Orange, LLC
Copyright (c) 2013-2014 Minimal Orange, LLC

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
Expand Down
10 changes: 10 additions & 0 deletions README.md
Expand Up @@ -223,6 +223,14 @@ Widget.trashed # Limits to items that have been drafted for deletion (but not
Widget.live # Limits to items that have not been drafted for deletion. Best used in an "admin" area in your application.
```

These scopes optionally take a `referenced_table_name` argument for constructing more advanced queries using `includes`
eager loading or `joins`. This reduces ambiguity both for SQL queries and for your Ruby code.

```ruby
# Query live widgets and gears without ambiguity.
Widget.live.includes(:gears, :sprockets).live(:gears)
```

### Draft Class Methods

The `Draftsman::Draft` class has the following methods:
Expand Down Expand Up @@ -498,6 +506,8 @@ work on features or find bugs!

## License

Copyright 2013-2014 Minimal Orange, LLC.

Draftsman is released under the [MIT License][9].


Expand Down
43 changes: 39 additions & 4 deletions lib/draftsman/model.rb
Expand Up @@ -74,17 +74,52 @@ def has_drafts(options = {})
belongs_to self.draft_association_name, :class_name => self.draft_class_name, :dependent => :destroy

# Scopes
scope :drafted, lambda { where("#{self.draft_association_name}_id IS NOT NULL") }
scope :published, lambda { where("#{self.published_at_attribute_name} IS NOT NULL") }
scope :trashed, lambda { where("#{self.trashed_at_attribute_name} IS NOT NULL") }
scope :live, lambda { where("#{self.trashed_at_attribute_name} IS NULL") }
scope :drafted, (lambda do |referenced_table_name = nil|
referenced_table_name = referenced_table_name.present? ? referenced_table_name : table_name

if where_not?
where.not(referenced_table_name => { "#{self.draft_association_name}_id" => nil })
else
where("#{referenced_table_name}.#{self.draft_association_name}_id IS NOT NULL")
end
end)

scope :published, (lambda do |referenced_table_name = nil|
referenced_table_name = referenced_table_name.present? ? referenced_table_name : table_name

if where_not?
where.not(referenced_table_name => { self.published_at_attribute_name => nil })
else
where("#{self.published_at_attribute_name} IS NOT NULL")
end
end)

scope :trashed, (lambda do |referenced_table_name = nil|
referenced_table_name = referenced_table_name.present? ? referenced_table_name : table_name

if where_not?
where.not(referenced_table_name => { self.trashed_at_attribute_name => nil })
else
where("#{self.trashed_at_attribute_name} IS NOT NULL")
end
end)

scope :live, (lambda do |referenced_table_name = nil|
referenced_table_name = referenced_table_name.present? ? referenced_table_name : table_name
where(referenced_table_name => { self.trashed_at_attribute_name => nil })
end)
end

# Returns whether or not `has_drafts` has been called on this model.
def draftable?
method_defined?(:draftsman_options)
end

# Returns whether or not the included ActiveRecord can do `where.not(...)` style queries.
def where_not?
ActiveRecord::VERSION::STRING.to_f >= 4.0
end

# Serializes attribute changes for `Draft#object_changes` attribute.
def serialize_draft_attribute_changes(changes)
serialized_attributes.each do |key, coder|
Expand Down
2 changes: 1 addition & 1 deletion lib/draftsman/version.rb
@@ -1,3 +1,3 @@
module Draftsman
VERSION = '0.1.1'
VERSION = '0.2'
end
20 changes: 4 additions & 16 deletions spec/models/vanilla_spec.rb
Expand Up @@ -159,14 +159,8 @@
describe :drafted do
subject { Vanilla.drafted }
its(:count) { should eql 1 }

it 'includes the unpublished item' do
subject.should include drafted_vanilla
end

it 'does not include the published item' do
subject.should_not include published_vanilla
end
it { should include drafted_vanilla }
it { should_not include published_vanilla }
end

describe :live do
Expand All @@ -180,14 +174,8 @@
describe :published do
subject { Vanilla.published }
its(:count) { should eql 1 }

it 'does not include the unpublished item' do
subject.should_not include drafted_vanilla
end

it 'includes the published item' do
subject.should include published_vanilla
end
it { should_not include drafted_vanilla }
it { subject.should include published_vanilla }
end

describe :trashed do
Expand Down

0 comments on commit 0ab221b

Please sign in to comment.