views:

118

answers:

6

So I have a controller called Music with one action which is index. On the music/index.html page I list out a bunch of Songs (via a Song model) and at the bottom I have a for to create a new Song.

Song has validations which I have tested and work just fine. When the new Song saves in controller Songs action create I redirect_to => 'music_index_path' so the person can see the new song in the list. However when the Song does not save (does not pass validations) then I cannot use redirect_to since the form error_messages do not carry over. I need to use render but cannot say render :controller => 'music', :action => 'index.

My goal is to be able to show the error messages for the Song form ON the music/index.html page.

How should I go about this. I am open to other ideas (like changing up controllers) as well.

Thanks!

A: 

Why not a simple if request.post? conditional in the index action's view rather than redirecting to another page?

Azeem.Butt
+2  A: 

It sounds to me like Music should be a part of Song, or the other way around. You can always use routes to disguise it as one or the other to the user. song/index sounds to me like it should display all songs, which is all music does anyway.

Jonatan Hedborg
I will play around with the routes...this may get me to where I want to be.
thomas
A: 

You can also try using flash[:song_save_error] to pass the error conditions back to your Music controller.

http://api.rubyonrails.org/classes/ActionController/Flash.html

kubi
A: 

You could try render :file => ...

nowk
+1  A: 

My first thought is that we need to rethink this process. Assuming you're using RESTful controllers, it's unclear to me why you would need a Music controller and a Song controller... how are those resources different? The next relevant question would be, why is it not sufficient to show errors via Song#create ? I mean, they couldn't get it right when it was just a form, is the distraction of additional content likely to help? :)

With that said, here is a possible solution. (Given that you didn't paste your code, I'm making a lot of assumptions here.)

<hack> first, extract the form parts from songs/new to songs/_form, then from the music/index view, render :partial => songs/_form, and in the songs controller, render :action => '../music/index' (this is called a hackity-hack.) Because it's a hack, you will almost certainly need to go into music#index and add @song = Song.new </hack>

MustModify
The resource itself is a Song but I don't want the URLs to show the word song...I am trying to create a song recommendation page for a wedding and I want the have the URL be /music or something similar that displays a bunch of songs. Thinking through it further I could just add a route the map /music to :controller => 'songs', :action => 'index'.
thomas
+1  A: 

If you start running on edge, the ability to pass a flash through a redirect was just added...but that doesn't really get you there.

The simplest solution though, is that you need to render index, but set up all of the variables that are needed for that page. If you factor that out into a separate module or method, you can call it from both the index action and the save failure.

def index
  setup_for_index
end

def create
   @song = Song.new(params[:song])
   @song.save
   #...
   #on failure
     setup_for_index
     render :controller => "music", :action => "index"
end

def setup_for_index
  @songs = Song.all
  #etc
end

The other thing you could do is use form_remote_for and have the song form just update the div on failure. Then use an RJS template return type reload the whole song list on success.

MattMcKnight