Reputation: 587
I've been stuck on this for a few days and I'm afraid I lack the vocabulary to properly ask this question, but any feedback is greatly appreciated!
I am working on a basic blog site. Users can create posts with a title, description, and declare whether others can see the post (public or private). From the index page, I want the user to be able to see a list of their posts, toggle public|private, and delete the post. Listing is easy (I'm rendering a partial based on the user's posts), and the AJAX delete link is working nicely:
<%= link_to 'Delete Post', post, :confirm => 'Are you sure?', :method => :delete, :remote => true %>
Toggling public|private corresponds to an edit/update action, and I cannot figure out how to do that using a link or button--it seems I have to use a form. I've tried a lot of variations of the working delete button that look something like this (and none work):
<%= link_to 'Make Public', { :controller => "posts", :action => "update", :id => post, :public => true, :post => post }, :method => :put, :remote => true %>
The only way that seems to work is with a form, but this requires that the user click the Update Post
button:
<%= form_for(post, :remote => true) do |f| %>
<div class="field">
<%= f.label :public %><br />
<%= f.check_box :public %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
So, in Rail3 what is the proper way to update a single attribute? (Is there more fitting verbiage?) Can it be done using a link or button? Do I have to use a form? Is there a Rails3 way (like destroy.js.erb) to add an onclick/onchange event or do I need to develop my own JavaScript?
Zabba's answer is great; however, I ultimately used a hidden form submitted via JavaScript (specifically jQuery).
In the view:
<div>
<%= form_for(post, :remote => true) do |f| %>
<%= f.hidden_field :public, { :value => !post.public } %>
<% end %>
<% if post.public == true %>
<div class="pp">Public</div>
<% else %>
<div class="pp">Private</div>
<% end %>
</div>
The JavaScript:
$('.pp').live('click', function(){
$(this).siblings('form').submit();
});
Comments on the two approaches? Is one more idiomatic?
Upvotes: 2
Views: 1094
Reputation: 65497
I would do it this way (not tested, so might be some minor mistakes):
Create action named make_public
in PostsController
a. The link" would be: <%= button_to 'Make Public', :confirm => 'Are you sure?', :method => :put, :remote => true %>
b. The action will receive the posts's id (params[:id]
)
Define a method called make_public
on the Post model
a. Call update_attributes :make_public => true
The link that does the update should be a PUT not a GET (Always put all state-changing actions behind a POST or a PUT)
Upvotes: 4