If you wanted to keep your current flow, you'll have to pick through any records in the database which might be nil (difficult):
#Controller
@listings = current_user.listings.unfinished
#app/models/listing.rb
class Listing < ActiveRecord::Base
def self.unfinished
execute(";WITH XMLNAMESPACES('http://www.w3.org/2001/XMLSchema- instance' as ns) SELECT * FROM Listings WHERE (SELECT Listings.*
FOR xml path('row'), elements xsinil, type
).value('count(//*[local-name() != "colToIgnore"]/@ns:nil)', 'int') > 0")
end
end
I have absolutely no idea if the above will work. It uses execute
in ActiveRecord to use a pure SQL query.
wont let the users publish the listings
This sounds like you want to make draft
functionality.
I would strongly recommend putting validations into your model so that you don't have to pick through a database that might have null values dotted around.
I know you said you have this already; I would make the validations conditional on whether the status
of the listing
is to be "published" or not (with an enum)...
#app/models/listing.rb
class Listing < ActiveRecord::Base
enum status: [:draft, :published] #-> defaults to draft
belongs_to :user
has_many :photos
scope :draft, -> { where status: :draft }
scope :published, -> { where status: :published }
####
validates :name, :user, :photos, :etc, :etc, presence: true, unless: "status.draft?"
####
def publish!
self.update status: :published
end
end
This would work similarly to the Wordpress "draft" functionality (IE publishing and saving are two completely different things):
#config/routes.rb
resources :listings do
post :publish, on: :member #-> url.com/listings/:id/publish
end
#app/controllers/listings_controller.rb
class ListingsController < ApplicationController
def new
@listing = current_user.listings.new
end
def create
@listing = current_user.listings.new listing_params
@listing.save #-> will be "draft" by default so no validations
end
def publish
@listing = current_user.listings.find params[:id]
redirect_to @listing if @listing.publish!
end
end
In your front-end, you'll be able to then list the @listings
by whether they're published or draft:
#app/views/listings/index.html.erb
<% @listings.published do |published| %>
...
<% end %>
<% @listings.draft do |draft| %>
...
<% end %>
Update
According to the OP, the answer was to use the following in his model:
#app/models/listing.rb
class Listing < ActiveRecord::Base
enum status: [:draft, :published] #-> defaults to draft
belongs_to :user
has_many :photos
####
validates :name, :user, :photos, :etc, :etc, presence: true, unless: "draft?"
####
def publish!
self.update status: :published
end
end