I have been trying to figure out how to make it so that I can create an activity page that lists out likes by other users on your OWN individual posts. In my case, I have no friend or following system so literally anyone who signs up can like a post. I have been looking everywhere and cannot find an example of how it is done
Currently, I have defined a like method in my post controller
def like
#post = Post.find(params[:id])
#post.upvote_by current_user
redirect_to :back
end
I also have an activities controller:
class ActivitiesController < ApplicationController
def index
#activities = PublicActivity::Activity.where(trackable_type: "Post", trackable_id: current_user.post_ids, key: "post.like")
end
end
My Post model looks like this:
class Post < ActiveRecord::Base
belongs_to :user
acts_as_votable
include PublicActivity::Model
tracked only: [:create, :like], owner: Proc.new{ |controller, model| model.user }
default_scope -> { order('created_at DESC') }
end
My activities view template looks like this:
<% #activities.each do |activity| %>
<%= activity.inspect %>
<% end %>
As of right now, my notification page displays nothing. How do i go about displaying a feed showing all the likes that my posts received from other users. Thanks so much
When upvote_by is called on a post, an ActsAsVotable::Vote record is created. You therefore have to add public activity to this model if you want to log votes.
class ActsAsVotable::Vote
include PublicActivity::Model
tracked only: [:create], owner: Proc.new{ |controller, model| model.user }
end
Related
I have three models...
models/resident.rb
class Resident < ActiveRecord::Base
belongs_to :hostel
has_many :leaves,dependent: :delete_all
has_one :user,dependent: :delete
end
models/user.rb
class User < ActiveRecord::Base
belongs_to :resident
end
models/leave.rb
class Leave < ActiveRecord::Base
belongs_to :resident
end
Now when I am trying to access the value of leave's attribute in views/leave/show.html.erb
I am getting this:
app/views/leaves/show.html.erb
<%= #leaves %>
out put In Browser :
#<Leave::ActiveRecord_Associations_CollectionProxy:0x007fde611850f0>
My leave controller looks like :
leaves_controller.rb
class LeavesController < ApplicationController
def new
if logged_in?
#leave=Leave.new
else
flash[:info]="Please login to mark a leave"
redirect_to root_path
end
end
def show
#leaves= current_user.resident.leaves
end
def create
#leave=current_user.resident.leaves.create(leave_params)
if #leave.save
flash[:info] = "Leave successfully marked"
redirect_to new_leave_path
else
flash[:danger] = "Something wrong Happened try again"
redirect_to root_path
end
end
private
def leave_params
params.require(:leave).permit(:start_date,:end_date,:destination)
end
end
Am I making correct leaves for resident and related user (create method)?
Is show method correct ?
and How to assess the user's leaves attribute in show.html.erb of leaves views.
A Resident has_many Leaves so current_resident.leaves returns an array of all the current_resident's leaves. You will need to loop through leaves to show individual attributes. Try
#leaves.first.attribute_name
in your view to get an idea of how the data is represented. To show all the leaves you'll need to use a loop in the view
#leaves.each do |leave|
leave.inspect
end
You are doing everything fine, and show method is fine, and the template shows exactly what is was told to show.
#leaves is a collection. You probably want to show it’s elements? This should lead to the proper solution:
<% #leaves.each do |l| %>
<%= l.inspect %>
<% end %>
I'm trying to show only the registers (patients) from a user (medic) that creates the register
In my controller I have:
def index
# #patients = Patient.all
#medic = Medic.find(params[:id])
#patients = #medic.patients
end
I get error: Couldn't find Medic with 'id'=
In my view I have:
<% #patients.each do |patient| %>
<%= patient.name %>
<% end %>
In my models I have:
class Medic < ActiveRecord::Base
has_many :patients
end
class Patient < ActiveRecord::Base
belongs_to :medic
end
¿How can I do this?
Thanks for help!
You can not have params[:id] by default in your index method; it is a collection route not a member route. So always the value of params[:id] is nil
If you would like to index patients of a certain medic you can go to localhost:3000/patients?medic_id=x and in your controller use
if params[:medic_id]
#patients = Patient.where(medic_id: params[:medic_id]).all
else
#patients = Patient.all
end
If you use devise and you have a current_medic defined then just get patients for the current medic using
#patients = current_medic.patients
localhost:3000/patients will now display patients or logged in user.
You have to add a before_action :authenticate_medic! to your controller.
I'm using Rails 3.2.19 and Ruby 2.1.2. I've been googling around trying to figure this out, but perhaps I'm not searching for the right thing. Anyway, I'll try and be as concise as possible.
I have a few different models that all have a name attribute. In my views I want to somehow be able to access that name attribute regardless of the instance name passed into the view. Currently my various controllers create instances of their respective models. For instance:
class PagesController < ApplicationController
def show
#page = Page.find(params[:id])
respond_to do |format|
format.html
end
end
end
-
class ProductsController < ApplicationController
def show
#product = Product.find(params[:id])
respond_to do |format|
format.html
end
end
end
While I understand I could simply re-name the instances something generic, I was wondering if there was some way of accessing any/all instances while maintaining unambiguous instance names.
Basically something like this:
page.html.haml
%h1= resources[0].name #equates to #page.name
%h2= #page.some_other_attribute
or
product.html.haml
%h1= resources[0].name #equates to #product.name
%h2= #product.price
Where in each of the above resources[0] would be either #page or #product
You will have to define a route with an additional resource_type parameter to a generic controller or otherwise just include the resource_type into the url query parameter
/resources/product/17
or
/resources/17?resource_type=product
This will allow you to do the following in the controller
class ResourcesController < ApplicationController
def show
#resource = find_resource(params)
respond_to do |format|
format.html
end
end
private
def find_resource(params)
resource_klass = {
product: Product,
page: Page
}[params[:resource_type]]
resource_klass.find(params[:id])
end
end
Another Option would be to introduce another ResourceType Entity and define a polymorphic :has_one :belongs_to association to the actual resource entity (product, page). Then always search for ResourceTypes and load the polymorphic resource entity
class ResourceType < ActiveRecord::Base
belongs_to :resource, polymorphic: true
end
class Product < ActiveRecord::Base
has_one :resource_type, as: :resource
end
class Page < ActiveRecord::Base
has_one :resource_type, as: :resource
end
product_resource_type = ResourceType.create(...)
product = Product.create(resource_type: product_resource_type)
page_resource_type = ResourceType.create(...)
page = Page.create(resource_type: page_resource_type)
ResourceType.find(product_resource_type.id).resource
=> product
ResourceType.find(page_resource_type.id).resource
=> page
I figured this out after discovering instance_variables and instance_variables_get
Those methods will return all instance variables being passed into the view. From there I discovered that the :#_assigns instance variable contained the instances that I was looking for. So I iterated over them to find if any had the name attribute.
- instance_variable_get(:#_assigns).each do |var|
- if var[1].respond_to?("name")
%h1= var[1].name
There is probably a better way of accomplishing this, so if anyone has any opinions, they are welcome.
Following the RailsCast for the reputation system gem, I added the following code to my microposts_controller
def index
#microposts = Micropost.paginate(page: params[:page]).find_with_reputation(:votes, :all, order: "votes desc")
#micropost = current_user.microposts.build
end
But no sorting happens in my index action aside from the default scope I set in my model
In my micropost model I have
class Micropost < ActiveRecord::Base
belongs_to :user
has_many :retweets
has_reputation :votes, source: :user, aggregated_by: :sum
default_scope -> { order('created_at DESC') }
If I change the default scope to
default_scope -> { order('votes DESC') }
It works how I want it to for the index page only but breaks all of my other pages.
I tried removing the default scope and leaving in the find_with_reputation method but it still doesn't order by votes.
I also tried defining the scope in a method in the micropost model like this
def self.popular
find_with_reputation(:votes, :all, {:order => 'votes desc'})
end
And make the code in the microposts_controller like this
def index
#microposts = Micropost.paginate(page: params[:page]).popular
#micropost = current_user.microposts.build
end
It still does not sort by votes.
Here is a copy of the log output from visiting the micropost index page
https://gist.github.com/anonymous/9745552
Here is a link to the gem https://github.com/NARKOZ/activerecord-reputation-system/tree/rails4
My routes.rb for microposts looks like this
resources :microposts, only: [:create, :destroy, :index] do
member { post :vote }
member { post :retweet}
end
Any guidance is appreciated.
Update
My home page feed is designed differently from what I'm doing for the Micropost Index feed. Maybe comparing what works to what doesn't will help pinpoint the issue.
I have a Static Pages Controller which sets its scope for the home action like this
def home
#micropost = current_user.microposts.build
#feed_items = current_user.feed.paginate(page: params[:page])
end
In the user model I define the feed method used in the static pages controller like so
def feed
Micropost.from_users_followed_by_including_replies(self)
end
the from_users_followed_by_including_replies(self) method is a scope i set in the micropost model
scope :from_users_followed_by_including_replies, lambda { |user| followed_by_including_replies(user) }
def self.followed_by_including_replies(user)
followed_ids = %(SELECT followed_id FROM relationships
WHERE follower_id = :user_id)
where("user_id IN (#{followed_ids}) OR user_id = :user_id OR to_id = :user_id",
{ :user_id => user })
end
Maybe I need to adapt a similar approach to the Index action for the Microposts controller
EDIT
In getting my hands on the code, I've found the real problem stems from the use of default_scope.
The original order() clause specified in your default scope is still being applied, even when adding your own order().
As a side note, this issue was kind of fixed in Rails 4.0, but the behavior was reverted in 4.0.1.
The solution was to apply a reorder()
# model
def self.popular
reorder('votes desc').find_with_reputation(:votes, :all)
end
# controller
def index
#microposts = Micropost.page(params[:page]).popular
end
ORIGINAL ANSWER
It seems that using the paginate method directly may not work with activerecord-reputation-system,
However, I found some examples showing that you can use the will_paginate page and per methods:
Perhaps it will work like this:
Micropost.page(params[:page]).per(30).find_with_reputation(:votes, :all, order: "votes desc")
Or with the model scope like this:
def self.popular
find_with_reputation(:votes, :all, order: 'votes desc')
end
you could do this:
Micropost.page(params[:page]).per(30).popular
Also, as a side note, your routes file is a little strange with multiple member blocks, when only one is necessary. I would make it look like this:
resources :microposts, only: [:create, :destroy, :index] do
member do
post :vote
post :retweet
end
end
I am working on a self-learning project for learning Rails that can be found on github here. (The latest commit includes this error)
However I am posting here all codes:
Model: photo_post.rb
class PhotoPost < ActiveRecord::Base
belongs_to :user
has_attached_file :image, styles: {
post: "200x200>"
}
end
Controller: PostsController
class PostsController < ApplicationController
def show
#post = Post.find(params[:id])
end
end
Controller: PhotoPostsController
class PhotoPostsController < ApplicationController
def create
content = build_content
post = current_user.posts.build(content: content)
if post.save
redirect_to root_path
else
flash.alert = "Please enter a title"
redirect_to root_path
end
end
private
def build_content
PhotoPost.new(photo_post_parameters)
end
def photo_post_parameters
params.require(:photo_post).permit(:image)
end
end
_post.html.erb
<%= div_for post do %>
<%= link_to post.user.username, post.user %>
suggested
<%= render post.content %>
<%= link_to time_ago_in_words(post.created_at), post %>
home_controller.rb
class HomeController < ApplicationController
protect_from_forgery
def show
#title_post = TitlePost.new
#photo_post = PhotoPost.new
#posts = current_user.posts
end
end
I created three models. Posts is the main one and TitlePosts and PhotoPosts are models under Posts.
The Title Posts work fine as I can submit a title.
For Photo Posts I used paperclip. However I try to upload an image I get the following error:
'nil' is not an ActiveModel-compatible object that returns a valid partial path.
You can also check the error on imageshack here.(Screenshot with better_errors).
I was going to copy the relevant codes and files but the full project can be found on github at the link I provided. If you need any further info please ask me.
Thank you.
Any help is greatly appreciated.
In just hitting the page current_user isn't defined, so current_user.posts is trying to get posts on a Nil object.
This cleared up the error, though it isn't going to correct your issues:
HomeController ~ line 7
#posts = []
if current_user
#posts = current_user.posts
end
You may also want to add something to your controller to require authentication so that current_user is set:
before_filter :authenticate_user!
OK this seems weird (to me). The error was caused by forgetting to install ImageMagick.
After installing it everything works fine.