Destroying UpVotes on acts_as_votable - ruby-on-rails

I have a rails app that is working fine using acts_as_votable. The like button upvotes the post count, and then switches to an un-like button and this down votes the post count.
My issue is, that since I started using the Public Activity gem, I can't find a way to remove likes from the feed. I have used the following loop in the activities index view:
<% #activities.each do |activity| %>
<p>
<% if activity.trackable %>
<%= link_to activity.owner.name, activity.owner %>
<%= render_activity activity %>
<% end %>
</p>
<% end %>
When I delete a comment, the entire line in the activity feed of 'FOO added a comment on BAR' disappears. However, because the acts as votable gem actually creates a downvote rather than destroying the upvote, the line 'FOO liked BAR' still appears and would be subsequently followed by 'FOO unliked BAR'.
Does anybody know how I can locate the upvote by the current_user on a particular post and then destroy it?
Below is my controller code for like and unlike as it stands:
def like
#ink.create_activity :like, owner: current_user
#ink.upvote_by current_user
redirect_to :back
end
def unlike
#ink.downvote_by current_user
redirect_to :back
end
Thanks

I know this have been answered but the ideal and easiest answer would be using the official gem method which is unvote_by it works for both upvotes and downvotes.

It looks like what you want to do is remove the model's like notification when it is "unliked" - is that correct? All you have to do is find the relevant activity and destroy it. Because Activities are models just like any other, you can do this with destroy and/or destroy_all.
I'm not quite sure what your public_activity model looks like, so instead of giving a specific example I'll link you to this post on the mailing list for the gem, which shows examples of deleting public activity records.
You may also find it useful to delete the record by its trackable_id - for example:
#activity = PublicActivity::Activity.find_by(trackable_id: (params[:id]), trackable_type: controller_path.classify)
#activity.destroy
There's more information about how that works in this SO answer.

For anyone that stumbles across this in future, thanks to Element119 I was eventually able to pinpoint the current users likes on a particular post with a few variables and arel searches. I then destroyed the pinpointed likes.
def like
#post.create_activity :like,
owner: current_user,
recipient: #post.user
#post.upvote_by current_user
redirect_to :back
end
def unlike
#post.downvote_by current_user
#currentUserLikes = PublicActivity::Activity.where(trackable_id: #post.id, owner_id: current_user.id, key: "post.like")
#currentUserLikes.destroy_all
redirect_to :back
end

Related

Rails App - Object_ID Returning for User Name

I am developing a simple blog app and am having trouble displaying the user name associated with a comment.
Comments belongs_to :posts and :users. Posts belongs_to :user and has_many :comments. Users has_many :posts and :comments.
The create action in my comments model works and stores the comments as expected with the post_id and user_id:
class CommentsController < ApplicationController
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.create(comment_params)
#comment.user = current_user
if #comment.save
redirect_to #post
else
flash.now[:danger] = "error"
end
end
private
def comment_params
params.require(:comment).permit(:content)
end
end
I am able to access the user name via the console as expected with Comment.first.user.name which returns the users name. When trying to do this in the view, I get the following error:
undefined method `name' for nil:NilClass
Here is the view:
<% #post.comments.each do |comment| %>
<p>User:<%= comment.user.name %></p>
<p>Comment:<%= comment.content %></p>
<% end %>
When I remove the .name from the user in the view, the app displays what looks to be the object_id.
User:#<User:0x00000001f62830>
Comment:Test comment
I've tried resetting the database mentioned here: Show username when posting comments in Rails
I've also tried to address the proxy_id mentioned here: Returning issue in Comment::ActiveRecord_Associations_Collection
I'm not sure what else to try. Also, when I reset the comments table so there is no data in it, the app still displays:
User:
Comment:
when it loops through even though there is no data in it. I think it has to do with the dynamic finder confused by the id, but I tried moving it all to the controller as mentioned here, retrieving username with find_by_id(comment.user_id).name not working, and I still am getting undefined method errors. Any ideas? Appreciate the insight. I am not using a comments gem, am developing in cloud9, and am using PostgreSQL.
I found the issue in this post: Using <%= render comments %> always outputs an empty partial, even if there is nothing in the database
"The issue is that the form is above the <%= render #post.comments %> so there is an empty comment when you reach the partial for all the comments, even if there's none in database, put the <%= render "comments/form" %> below to fix this."

*Show* view always shows the first pin (item) in the database

I'm working on a pinterest-like app, and I've encountered a problem recently.
When as a logged in user I try to access a pin through "show" it gives me the correct id number in the url for e.g. http://localhost:3000/pins/7 but the description comes from the first item in the database.
Here's my Show view code:
<%= image_tag #pin.image.url %>
<p>
<strong> Description: </strong>
<%= #pin.description %>
</p>
<% if #pin.user == current_user %>
<%= link_to 'Edit', edit_pin_path(#pin) %>
<% end %>
<%= link_to 'Back', pins_path %>
On the other hand when I try to access it via heroku through show or edit it ends with a following message:
"We're sorry, but something went wrong. If you are the application owner check the logs for more information."
Here is my github repo https://github.com/LeJaques/myfirstapp_new
I would be grateful for help!
Your issue seems to be in your set_pin method in your PinController.
private
# Use callbacks to share common setup or constraints between actions.
def set_pin
#pin = Pin.find_by(params[:id])
end
When passing simply params[:id] to find_by, you're going to run into issues. You should either use
#pin = Pin.find(params[:id])
or
#pin = Pin.find_by(id: params[:id])
the latter of which you oddly used in your later correct_user method.
Unrelated to your question, but in the future, rather than linking to your github project and having us dig through the code, please post the relevant code to your question. Doing so will help you get quicker answers in the future; this question would have been answered within five minutes (rather than in over half an hour) if your set_pin method had been in your question from the start.
Looks like you are using find_by to set the #pin incorrectly.
def set_pin
#pin = Pin.find_by(params[:id])
end
Try to change it to just Pin.find(params[:id]) or add a field to search by Pin.find_by(id: params[:id])

Rails Wicked Gem - Understanding routing

Okay, so I'm not really understanding nested routing in the wicked gem.
So far I have this. I'm not sure if everything is in the right folder or if I'm doing that right.
routes.rb
resources :events
resources :events do
resources :build, controller: 'events/build'
end
controllers/events_controller.rb
def create
#event = Event.new(event_params)
if #event.save
flash[:success] = "Event Created!"
redirect_to event_build_path(event_id: "event", id: #event.id)
# previously had redirect_to event_build_path without parameters)
else
render 'new'
end
end
controllers/events/build_controller.rb
class Events::BuildController < ApplicationController
include Wicked::Wizard
steps :details, :visibility
def show
#event = Event.find(params[:event_id])
render_wizard
end
end
views/build/details.html.erb
<%= form_for #event do |f| %>
#blab blah
<% end %>
I had the event_build_path without parameters at first and I had this error
No route matches {:action=>"show", :controller=>"events/build"} missing required keys: [:event_id, :id]
Had influence from this Rails wicked gem redirect with params but don't entirely understand the routing
I don't have an event_id set and I don't really understand how wicked keeps track of the step of via the id (or if its event_id).
As my object (event) is not created yet, what is "event_id" and the id at the end represent?
Not really an answer, but some clarifications. The thing you're trying to do is pretty hard, and requires a bunch of customizations to suit your own case. If you're not comfortable with wicked, or if that tutorial is nearly incomprehensible, it might be better to skip doing a wizard for now and come back and try it again in a month or so once you've had time to meditate on it.
Form
This is your wicked form
<%= form_for #event do |f| %>
#blab blah
<% end %>
Wicked works by doing two things, storing state in your url domain.com/build_pah/<step> and providing you with helper methods to easily manipulate the current state. Once you render the form you need to tell the browser where to submit info to when enter is pressed. Right now it is going to #event path, which isn't what we want. Instead we need to do something like:
<%= form_for #event, :url => wizard_path, :method => :put do |f| %>
<% end %>
This tells the form to go to the wizard_path url, this is a helper we provide. It also tells the form to submit using the PUT HTTP method, which should trigger your def update action inside of your Events::BuildController if it is set up correctly. On another note it doesn't look like Events::BuildController has an update action.
Event Controller
Your event controller looks fine, however you're redirecting
redirect_to event_build_path(event_id: "event", id: #event.id)
Wicked needs the id parameter to be the step you want to go to. So it should be:
redirect_to event_build_path(event_id: #event.id, id: :details)
or
redirect_to event_build_path(event_id: #event.id, id: Wicked::FIRST_STEP)
You can also get fancy and redirect to the index action which will do another redirect to the first step, but i always prefer being explicit.
Other Questions
Here is someone with a similar question: https://github.com/schneems/wicked/issues/141 take a look at their code, and their question. Try to understand what was wrong and how it was fixed. Then compare between what they're trying to do and what you're trying to do.
This question
It's hard to be more helpful without an explicit question. Breaking it down into I did this => I expected this => I got this instead , I tried to debug using this . Anywhoo, hope some of this was helpful. Maybe spin up another Rails example app and try to walk through my wicked tutorial in the readme, it will give you some more experience with what wicked does (and doesn't) do for you.

Rails single table inheritance. Shared controller, howto Update (CRUD)

I've got three classes Admin, Client, Agent which all inherit from User < ActiveRecord::Base. The system is designed using STI, hence all classes share the same users table.
I am interested in keeping the CRUD functionality pretty much the same, hence for now I am using a single UsersController.
When implementing the Update functionality I'm faced with a doubt.
Here's my edit form:
#Edit Form
<%= form_for(#user,{url:user_path(#user),method: :put}) do |f| %>
<%= render 'edit_fields',f:f %>
<%= f.submit "Save", class: "btn btn-large btn-primary"%>
<% end %>
#UsersController
def edit
#user=User.find(params[:id])
end
def update
binding.pry
#if #user.update_attributes(params[:user]) #<---BEFORE
#WORKAROUND BELOW
if #user.update_attributes(params[#user.type.downcase.to_sym])
flash[:success]="User was updated successfully."
redirect_to user_path(#user)
else
flash[:danger]="User could not be updated."
render 'new'
end
end
My "problem" is that params is dependent on the #user.type of the #user instance. Therefore sometimes there's a params[:client], other times a params[:admin] or params[:agent].
Hence the line
if #user.update_attributes(params[:user]) does not always work.
The workaround I implemented works fine, but I was wondering whether there's a more DRY or elegant way to approach these issues, i.e. sharing CRUD between different STI-ed classes.
There is indeed a much more elegant solution. Just change your form_for declaration and add the as option, like this:
<%= form_for(#user, as: :user, url: user_path(#user), method: :put) do |f| %>
That way in your controller your parameters will be scoped under the user key instead of the model's class.
In your controller, check for the User type in a before_filter as below. I've used this for similar STI Controllers and works great for me.
before_filter :get_user_type
private
def get_user_type
#klass = params[:type].blank? ? User : params[:type].constantize
end
And then for example you could call a show method as :
def show
#user = #klass.find params[:id]
#render
end
Using #klass across your CRUD actions should simplify your Controller.

rails3 show not getting :user_id in one case

I have a strange problem. I've been coding in Rails for, off and on, a year. I created a new project recently and used scaffolding. Things were going fine, yesturday I started implementing some favoriting features. Now I have a strange problem. I rolled back the stuff I did last night but still have the problem. First
Entry belongs to user
User has many entries
My Entry show method in my controller is very standard and simple
def show
#user = User.find(params[:user_id])
#entry = #user.entries.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render :json => #entry }
end
end
When I view the entry from a normal link in the entries index
<%= link_to 'Show', user_entry_path(#user, entry) %>
I takes me to where it should go:
/users/4/entries/11
When I create new things still look good
/users/4/entries/new
Until I click "create entry" or the submit button
<div class="actions">
<%= f.submit %>
</div>
Then it goes to
/entries/20 ...with the error:
ActiveRecord::RecordNotFound in EntriesController#show
Couldn't find User without an ID
If I go back to the entries index however, the file new entry is there and the show link takes me to the right place. Thoughts? Your help is appreciated!
The error message tells you that User.find(params[:user_id]) couldn't find a user with that ID. Try checking the structure of the GET parameters in the server logs.
If your GET path is /entries/20, then the path only has an entry ID and is missing a user ID. You might be able to fix this in your Controller#create by having it redirect to user_entry_path instead of entry_path.
How does your form look like?
I think you have nested routes? Your form should look like following:
<%= form_for [#user, #entry] do |f| %>
<% # your fields %>
<% end %>
Your form seems to point to resources entry, instead of the nested ressource..

Resources