Undefined local variable or method friendship - ruby-on-rails

I'm trying to add some social functionality to my app, and following RailsCast #163 about self-referential association, but I have a problem with deleting friendship.
On user#show page I have 2 columns: with #users and #friends. The show method from UsersController is:
def show
#user = User.find(params[:id])
#users = User.all
#friends = #user.friends
end
Also I'm using <%= render #users %> and <%= render #friends %> partials, both of them renders _user.html.erb from users folder, which is the following:
<tr>
<td>
<%= gravatar_for user, size: 30 %>
</td>
<td>
<%= user.name %>
</td>
<td>
<% if current_user.friends.exists?(user) %>
<%= link_to 'Remove friend', friendship, :method => :delete %>
<% else %>
<%= link_to 'Add friend', friendships_path(:friend_id => user), method: :post %>
<% end %>
</td>
</tr>
Everything is ok with models and controllers, as I've checked everything a hundred times. But when I try to open a page I receive an error undefined local variable or method friendship from this line <%= link_to 'Remove friend', friendship, :method => :delete %>.

Like the error says, friendship is not defined. You need to pass instead of friendship, the user you want to delete. For example:
<%= link_to 'Remove friend', user, :method => :delete %>
or
<%= link_to 'Remove friend', friendship_path(user), :method => :delete %>
Hope this helps!

It looks awful, but seems that current_user.friendships.find_all_by_friend_id(user.id).first instead of friendship solved my problem. But I'm sure that there is more simple solution.

if you have an instance variable defined in your controller (#friendship or #user) use that opposed to user or friendship for the route.
<%= link_to 'Remove friend', #user, :method => :delete %>

Related

Rails form submit operate like a link_to

So ultimately what I'm trying to do is get the form to be split across two different columns with the status to be in one column and the save button in another column next to the link_to OR have the form's submit operate like a link_to. The form automatically applies some CSS that's causing the issue of splitting the form.
<tbody>
<% #training_resource.spud_users.each do |training| %>
<tr>
<td><%= training.full_name %></td>
<% utr = training.user_training_resources.where(training_resource: #training_resource).first %>
<td class="utr-form">
<%= tb_form_for [:admin, utr], url: admin_update_utr_path(utr), :remote => true, :html => {:id=>'form_id'}, :data => {:errors => :inline, :success => admin_training_resources_path} do |f| %>
<%= f.select :status, UserTrainingResource.statuses.map {|k,v| [k.humanize, k]}, selected: utr.status %>
</td>
<td class="table-actions">
<%= f.tb_save_buttons('', admin_update_utr_path(utr)) %>
<% end %>
<%= link_to 'submit', admin_update_utr_path(utr), :onclick => "$('#form_id').submit()" %>
<%= link_to 'Delete', admin_destroy_utr_path(utr), :method => :delete, :data => {:confirm => 'Are you sure you want to delete this?'}, :class => 'btn btn-danger btn-sm' %>
</td>
</tr>
<% end %>
</tbody>
So what I'm trying to figure out is if there is a way to change the form save button to be a link_to. Right now I have it here under link_to 'submit'. It however does not operate like the tb_save_button as it doesn't redirect to the correct location or save.
You could handle this in the controller.
(example)
def create
if utr.save
redirect_to admin_update_utr_path(utr)
else
# render new form or display the previous view
end
end

How to link to users show page in the view

I added a link to the Photos page so that below each picture it would link to the users page.
The issue is I am getting redirected to /photos/1 when I should be directed to /users/1
Photos controller:
def show
#photos = Photo.find(username: params[:id])
end
View:
<% #photos.each do |photo| %>
<%= link_to photo.user, photo %>
<%=image_tag photo.image_url(:thumb) %>
<%= button_to "remove", photo, :confirm => 'Are you sure?', :method => :delete %>
<% end %>
As noted, using <%= link_to photo.user.username, photo.user %> should give you what you're looking for.

Rails checkbox to get json value of selected records

Hi I have a form in rails and this is the code
<%= form_tag getjson_products_path do %>
<% #products.each do |product| %>
<%= check_box_tag "product_ids[]",product.id , false%>
<%= product.name %>
<%= product.category %>
<%= product.price %>
<%= link_to 'Show', product %>
<%= link_to 'Edit', edit_product_path(product) %>
<%= link_to 'Destroy', product, method: :delete, data: { confirm: 'Are you sure?' } %>
<br>
<% end %>
<%= submit_tag "submit" %>
<br>
<% end %>
and I have written one method in products controller
def getjson
#stuff to do
redirect_to root_path
end
and this is my routes file
resources :products do
collection do
get 'getjson'
end
end
I want is to get json value of selected products , but whenever I click submit it says routes error what I have to do and how to get json value for selected records?
In controller change like this
def getjson
if params[:product_ids]
#products = Product.find(params[:product_ids])
render json: #products
end
end
thats all it will works

creating a form to delete a resource

I have a subscriber resource (mailinglist) and want to make a unsubscribe form. I created a remove view with a form
<%= form_for(Subscriber.new, :action => :delete) do %>
email: <%= text_field_tag :mail %>
<%= submit_tag "Sign out" %>
<% end %>
I try to call the delete method of the controller but instead the edit action gets called.
The problem is that the RESTful routes to the destroy action needs an :id of the resource to be deleted and since you use Subscriber.new as a source for creating the form, it cannot create an appropriate url to post to.
You can go around this by using routes like this:
<% form_for(:subscriber, :url => subscriber_path("email"), :html => {:method => :delete}) do %>
email: <%= text_field_tag :mail %>
<%= submit_tag "Sign out" %>
<% end %>
Note that you have to edit subscriber_path to your own routing but by using "email" as an identifier you make sure that no faulthy :id is being passed to the controller and you can use the email to find the correct model to destroy as I think was what you wanted to do.
<%= form_for #subscriber, :method => :delete do %>
email: <%= text_field_tag :mail %>
<%= submit_tag "Sign out" %>
<% end %>
This should do the trick.

Ruby on Rails - Trouble looping through partial using collection

I am having issues using the :collection command for a partial within a form I am creating in rails. I would ideally like to use the :collection command, so I can easily manipulate this section in my .rjs templates (the form will submit and reload the form when the check box is changed, it's a to-do list).
This code works:
<% form_for "list[]", :url => {:action => "checkbox_update"} do |f| %>
<ul id="lists_not_completed">
<% for #list in #lists %>
<%= render :partial => #list, :locals => {:f =>f, :complete => FALSE } %>
<% end %>
</ul>
<% end %>
with the partial:
<% if #list.completed == complete %>
<li><%= f.check_box :completed %>
<%=h #list.name %>
<%= link_to 'Show', list %>
<%= link_to 'Edit', edit_list_path(list) %>
<%= link_to 'Destroy', list, :confirm => 'Are you sure?', :method => :delete %></li>
<% end %>
This code does not work, but I would like it to use this form:
<% form_for "list[]", :url => {:action => "checkbox_update"} do |f| %>
<ul id="lists_not_completed">
<%= render :partial => 'list', :collection => #lists, :locals => {:f =>f, :complete => FALSE } %>
</ul>
<% end %>
with the non-working partial:
<% if list.completed == complete %>
<li><%= f.check_box :completed %>
<%=h list.name %>
<%= link_to 'Show', list %>
<%= link_to 'Edit', edit_list_path(list) %>
<%= link_to 'Destroy', list, :confirm => 'Are you sure?', :method => :delete %></li>
<% end %>
I get the error:
object[] naming but object param and #object var don't exist or don't respond to to_param: nil. It is referring to this line: <li><%= f.check_box :completed %>. I'm not sure if why this doesn't work and have tried many, many different variations, but I can't get it working. Is the form preventing me from doing this? The form_for code is straight from the Rails Way book for listing multiple objects from one model in a form.
Any help on this would be greatly appreciated.
I think that the problem is you've not got #list defined anywhere when you're using the render :partial with a :collection.
The system is looking for #list to match the list[] when you call f.check_box
you could set #list = list in your partial to get around that. I suppose.
Tim's answer is correct, but I'd probably avoid extracting the partial within the form_for loop altogether. I suppose it's a matter of style, but I think the confusion here isn't really worth the cleanup that the partial represents in this case. I'd probably write a partial that included the whole form.

Resources