Ok I solved this by using a combination of suggestions above and to
cover my specific requirements.

Save as Draft and Publish are input buttons.
Preview is a link_to_function with the following javascript function.

function preview_post(element){
        element.up('#post_form').writeAttribute('target', '_blank');
        element.up('#post_form').down('#preview_value').value += 1;
        element.up('#post_form').submit();
        element.up('#post_form').writeAttribute('target', false);
}

The above function is called only if Preview is clicked and adds a
target = "_blank" attribute to the form in the page. This ensures that
the form submit opens a new window with the response(which is in this
case a preview). I then set the same attribute to 'false' so that
subsequent form submissions dont open in a new window except if its
preview again.

During the course of solving this, I decided i HAD to save before
previewing for requirement reasons. Im updating a hidden 'preview'
attribute (with a default value of 0) in the form to 1 so that back in
the controller, i check for this value and if its 1, I save and render
'show' (which opens in a new window). Controller is quite complicated
so im just gonna paste the code below and let you understand for
yourself.

def create
    @post = current_account.posts.build(params[:post])
    if ((params[:preview].to_i == 1) && !((params[:save] == "Save") ||
params["save.x"]) && !((params[:publish] == "Publish") || params
["publish.x"]))
      @post.status = "Draft"
      @post.save(false)
      render :action => 'show', :layout => 'application'
    elsif ((params[:preview].to_i > 1) && !((params[:save] == "Save")
|| params["save.x"]) && !((params[:publish] == "Publish") || params
["publish.x"]))
      render :action => 'show', :layout => 'application'
    elsif ((params[:save] == "Save") || params["save.x"])
      unless (params[:preview].to_i > 0)
        if @post.save(false)
          @post.update_attribute(:status, "Draft")
          redirect_to posts_path
        else
          flash[:error] = "There was a problem creating your blog
post. Please try again later."
          render :action => 'new'
        end
      else
        flash[:success] = "Post successfully created"
        redirect_to posts_path
      end
    elsif ((params[:publish] == "Publish") || params["publish.x"])
      unless (params[:preview].to_i > 0)
        @post.status = "Active"
        @post.published = 1
        if @post.save
          flash[:success] = "Post successfully published"
          redirect_to post_path(@post)
        else
          render :action => 'new'
        end
      else
        if @post.valid?
          flash[:success] = "Post successfully published"
          redirect_to post_path(@post)
        else
          render :action => 'new'
        end
      end
    end
  end

Thats quite a lot and quite ugly. Am refactoring it. But this is
perfectly functional. Hope it helps someone.

Thank you all for your suggestions.


On Sep 11, 10:40 am, "s.ross" <cwdi...@gmail.com> wrote:
> On Sep 9, 2009, at 11:15 PM, Ram wrote:
>
>
>
> > Hi ross,
>
> > Thats what im doing right now. Im saving it as a Draft and rendering
> > the show action for the instance @post as a preview. But that breaks 2
> > requirements, namely
>
> > 1. The preview does not open in a new window.. its the same window.
> > 2. There are no call to action buttons on the Preview page (there
> > should not be any) and so when the user hits the back button, he's
> > taken back to the new post form where hitting Save as Draft saves a
> > whole new post with the same data.
>
> > Even if I manage to show the preview in a new window, i will still
> > have the duplicating posts problem if i save it before previewing it.
>
> It seems like you are trying to make your show action work too hard.  
> If you are dead set against saving the data, you'll probably have to  
> come up with a Javascript preview. On the other hand, creating a one-
> off action like 'preview' makes a ton of sense here because its job  
> would be simply to preview some disposable data.
>
> Again, I don't know your requirements, but my philosophy is to write  
> really stupid controllers. If something like the show action tries to  
> get too clever, it's a code smell to me.
>
>
>
> > On Sep 10, 10:58 am, "s.ross" <cwdi...@gmail.com> wrote:
> >> Use a state machine. posts are initially in 'draft' state, and thus
> >> can be previewed, but are not published. When publish is pressed,
> >> change the state to 'published'. You probably don't even need to
> >> manage state transition formally. Just make sure when you display
> >> posts to get only published ones (use named_scope to make this more
> >> automatic).
>
> >> On Sep 9, 2009, at 10:49 PM, Ram wrote:
>
> >>> Hi,
>
> >>> Ive got a form for a blog post and there are 3 buttons - Publish,
> >>> Preview and Save as Draft.
>
> >>> Clicking on Preview should open a new window with the preview of the
> >>> post without saving it while the current window stays on the "New
> >>> Post" form. I dont want the post to be saved because, once the user
> >>> views the preview and closes it, when he clicks on, say, Save as  
> >>> Draft
> >>> on the form, a second post with the same details gets created. How  
> >>> can
> >>> I achieve this functionality?
>
> >>> On a side note, I also want to perform model validations only if the
> >>> post is Published. Thought it might be relevant.
>
> >>> Im quite stumped so any and all ideas are welcome :)
>
> >>> Thanks.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Talk" group.
To post to this group, send email to rubyonrails-talk@googlegroups.com
To unsubscribe from this group, send email to 
rubyonrails-talk+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to