I have a Rails application that doesn't seem to run the expected .js.erb file, so I would like to override the default behavior, but I'm not sure how to do this.
Details:
This is a Rails 3 application that displays a button_to with an AJAX call to switch the state of something to the backend, and then changes the button text to reflect the opposite action if you click it again. Basically, โSave to Scheduleโ becomes โRemove from Schedule,โ and you can click it again to do the opposite.
This really works fine, but only if I put the jQuery that I want to execute in show.js.erb (named after the view associated with the method that shows the page the button is on), and not toggle.js.erb ( depending on the name of the actual method being called).
In this example, I am using jquery-rails.
In the view that displays the button ( show.html.erb
(more precisely, a partial call from there):
<% if current_user.shows.include?(@show) %> <p><%= button_to "Remove from schedule", toggle_show_path(@show), :remote => true, :class => 'schedule_button' %> <% else %> <p><%= button_to "Save to schedule", toggle_show_path(@show), :remote=> true, :class => 'schedule_button' %> <% end %>
From routes.rb
:
match '/shows/toggle/:id' => 'shows#toggle', :as => :toggle_show
From my `show_controller.rb:
def toggle if current_user show = Show.find(params[:id]) if show if current_user.shows.include?(show) current_user.shows.delete(show) flash[:notice] = "This show has been removed from your schedule." else current_user.shows << show flash[:notice] = "This show has been added to your schedule." end else flash[:error] = "Unknown show." end else flash[:error] = "You're not logged in." end end
I assume that there are some default conventions that determine which .js.erb file to use, but why doesn't it use the one that is based on the method provided by the form?
I experimented with an explicit message of what to do, but I'm not quite sure how to specify the name of my alternate .js.erb file to call. It doesn't seem to be that way:
respond_to do |format| format.html { redirect_to show_path(params[:id]) } format.js { render toggle_show_path(params[:id]) } end
From my journal:
ActionView::MissingTemplate (Missing template /shows/toggle/22 with {:handlers=>[:erb, :rjs, :builder, :rhtml, :rxml], :formats=>[:js, :html], :locale=>[:en, :en]} in view paths "/Data/Sites/tvgridthing.local/app/views", "/Users/jschuur/.rvm/gems/ruby-1.9.2-p0/gems/devise-1.1.3/app/views", "/Data/Sites/tvgridthing.local", "/"): app/controllers/shows_controller.rb:78:in `block (2 levels) in toggle' app/controllers/shows_controller.rb:76:in `toggle'
I assume that since I want to override the default behavior, I can no longer use Rails 3 shorter 'response_with format?
Unrelated question: Any way to condensate my show add / remove logic into my user model? I do a search, turn on and add / remove and wonder if there is a simpler solution.
Update: I just figured this out with the help of someone I sent this link to. The solution was simple: render :toggle
.
It is still interesting if there are suggestions for optimizing the switching logic.