Rails: How to toggle a boolean field from a view?
I have a boolean field called "saved" in my database. I want to toggle this field by clicking on a text link that changes from "Save" to "Unsave" depending on the situation, and updates my "Customer" table with 0 or 1. I imagine Javascript may be a way to go for this but I am not experienced enough (yet!) in Javascript to know how to code it.
I've rolled back the question to keep it shorter. Here is my exact code.
#employers controller
def save_toggle
@matching = Matching.find(params[:id])
if @matching.employer_stars == false
@matching.employer_rejects = false # If saving a match, remove any existing rejection.
end
@matching.employer_stars = !@matching.employer_stars
@matching.save
render :partial => "save_unsave_buttons", :layout => false
end
#view home.html.erb
<%= render :partial => "save_unsave_buttons", :locals => {:matching => matching} %>
#partial _save_unsave_buttons.html.erb
<div id="save_buttons" class="buttonText"> #latter is just for CSS layout
<% if @matching.employer_stars %>
<%= link_to_remote "开发者_Python百科Unsave",
:url => {:action => "save_toggle", :id => matching.id},
:update => {:success => "save_buttons", :failure => "Error"} %>
<% else %>
<%= link_to_remote "Save",
:url => {:action => "save_toggle", :id => matching.id},
:update => {:success => "save_buttons", :failure => "Error"} %>
<% end %>
</div>
The database is working but the toggle text isn't switching. To @nathanvda: I'm really sorry for being such a pain - I want to confirm your answer but I know if I do I'll just leave this for a while then come back to it and get frustrated again! Thanks man.
You have to define a controller-method, which sets your saved
attribute. In your view you can then link to this method using link_to_remote
.
That should get you started.
--Update: after updated question:
You should create a partial that renders your save/unsave button like this, call it "_save_unsave_buttons.html.erb" :
<div id="save_buttons">
<% if matching.employer_stars %>
<%= link_to_remote "Unsave",
:url => {:action => "save_toggle", :id => matching.id},
:update => {:success => "save_buttons", :failure => "Error"} %>
<% else %>
<%= link_to_remote "Save",
:url => {:action => "save_toggle", :id => matching.id},
:update => {:success => "save_buttons", :failure => "Error"} %>
<% end %>
</div>
This partial will render you correct save-buttons, and upon update the containing div is updated/replaced by the result of your controller action.
From inside your main view, write
<%= render :partial => "save_unsave_buttons", :locals => {:matching => match } %>
where you want the buttons to be visible.
And inside your controller:
def save_toggle
@matching = Matching.find(params[:id])
@matching.employer_stars = !@matching.employer_stars
@matching.save
render :partial => "save_unsave_buttons", :locals => {:matching => @matching}, :layout => false
end
Good luck!
--Update again: so i presume you render a set of @matchings, i would change the naming between the collection and the item a bit, to prevent more confusion and accidental mistypings.
But actually this is pretty easy:
@matchings.each do |match|
.. build your view here ..
<%= render :partial => "save_unsave_buttons", :locals => {:matching => match}
end
and in your partial you can then use the correct matching
everywhere.
Just a notice:
Your save_toggle
method is not RESTful. The HTTP PUT verb should be implemented idempotent (See o.a. http://en.wikipedia.org/wiki/Idempotence#Examples), which means it should always do the same thing no matter how often you execute it. In your example, executing the save_toggle
method once does not give the same result as executing it twice.
A better practice would be to make two methods, e.g.:
def set_employer_stars
end
def unset_employer_stars
end
or whatever you want to call them. Then you can also use these two different methods in the link_to_remote
methods (because you now use save_toggle
in both "Unsave" and "Save").
精彩评论