We are looking to have Sender and Receiver attributes for each micropost that is entered on our site. The sender of the post, and the receiver whom it is directed to.
In other words, on each micropost that each user sees, we want the content, and just above or below the content of the post we want the sender shown and receiver shown. We also want users to be able to click on either the sender or the receiver and be linked directly to that profile.
How can we go about doing this? We are relatively new to rails and think additions need to be made in the Micropost model for this change to work. Or should the changes be made in the MicropostsController?
Micropost Model:
class Micropost < ActiveRecord::Base
attr_accessible :content, :belongs_to_id
belongs_to :user
validates :content, :presence => true, :length => { :maximum => 240 }
validates :user_id, :presence => true
default_scope :order => 'microposts.created_at DESC'
# Return microposts from the users being followed by the given user.
scope :from_users_followed_by, lambda { |user| followed_by(user) }
private
# Return an SQL condition for users followed by the given user.
# We include the user's own id as well.
def self.followed_by(user)
following_ids = %(SELECT followed_id FROM relationships
WHERE follower_id = :user_id)
where("user_id IN (#{following_ids}) OR user_id = :user_id",
{ :user_id => user })
end
end
MicropostsController:
class MicropostsController < ApplicationController
before_filter :authenticate, :only => [:create, :destroy]
def create
#micropost = current_user.microposts.build(params[:micropost])
if #micropost.save
flash[:success] = "Posted!"
redirect_to current_user
else
#feed_items = []
render 'pages/home'
end
end
def destroy
#micropost.destroy
redirect_to root_path
end
end
To eliminate some confusion and make it a bit more railsy, I'd go with:
class Micropost < ActiveRecord::Base
belongs_to :sending_user, :class_name=>"User", :foreign_key=>"user_id"
belongs_to :receiving_user, :class_name=>"User", :foreign_key=>"belongs_to_id"
end
this will allow something like this in your view for a given Micropost object "#micropost":
<%= link_to(#micropost.sending_user.username, user_path(#micropost.sending_user)) %>
<%= link_to(#micropost.receiving_user.username, user_path(#micropost.receiving_user)) %>
*this assumes several things about the user object and routing, but should get you on the right path.
Related
I'm attempting to set limits on the amount of commenting users can do on particular post during the day. I have implemented the following (successfully) in my Post model to limit the amount of Posts they can create.
class Post < ActiveRecord::Base
validate :daily_limit, :on => :create
def daily_limit
# Small limit for users who just sign up
if author.created_at >= 14.days.ago
if author.created_posts.today.count >= 4
errors.add(:base, "Exceeds Your Daily Trial Period Limit(4)")
end
else
if author.created_posts.today.count >= author.post_limit_day
errors.add(:base, "Exceeds Your Daily Limit")
end
end
end
end
But, when I attempt to add similar restrictions to my Comment model
class PostComment < ActiveRecord::Base
validate :daily_limit, :on => :create
belongs_to :post, :counter_cache => true
belongs_to :user
def daily_limit
# Small limit for users who just sign up
if user.posted_comments.today.count >= 2
errors.add(:base, "Exceeds Your Daily Trial Period Limit(4)")
end
end
end
I am greeted with a undefined method 'posted_comments' for nil:NilClass error. I don't believe my user_id is being passed into my model correctly in order to access it with something like user.posted_comments.today.count>=2
My create action in my post_comments controller is as follows:
class PostCommentsController < ApplicationController
def create
#post = Post.find(params[:post_id])
#post_comment = #post.post_comments.create(post_comment_params)
#post_comment.user = current_user
if #post_comment.save
redirect_to #post
else
flash[:alert] = "Comment Not Added"
redirect_to #post
end
end
end
and the my hacked down User model is as follows:
class User < ActiveRecord::Base
has_many :created_posts, class_name: 'Post', :foreign_key => "author_id",
dependent: :destroy
has_many :posted_comments, class_name: 'PostComment', :foreign_key =>"user_id", dependent: :destroy
end
Thanks.
You are assigning the user after "create" in your controller
#post_comment = #post.post_comments.create(post_comment_params)
#post_comment.user = current_user
Try this:
#post_comment = #post.post_comments.build(post_comment_params)
#post_comment.user = current_user
I'm creating a simple newsfeed in rails. The aim is for it to return all the posts from the groups the user is following. I am using socialization for my follow functionality.
The exact error is:
NoMethodError (undefined method `followees' for false:FalseClass)
Here are my basic models not including like and follow as they're empty:
User:
class User < ActiveRecord::Base
authenticates_with_sorcery!
attr_accessible :username, :password, :email
has_many :groups
has_many :posts
acts_as_follower
acts_as_liker
before_create :generate_auth_token
def auth_token_expired?
auth_token_expires_at < Time.now
end
def generate_auth_token(expires = nil)
self.auth_token = SecureRandom.hex(20)
self.auth_token_expires_at = expires || 1.day.from_now
end
def regenerate_auth_token!(expires = nil)
Rails.logger.info "Regenerating user auth_token"
Rails.logger.info " Expiration: #{expires}" if expires
generate_auth_token(expires)
save!
end
end
Group:
class Group < ActiveRecord::Base
attr_accessible :description, :name, :user_id
has_many :posts
belongs_to :user
acts_as_followable
end
Post:
class Post < ActiveRecord::Base
attr_accessible :body, :user_id, :group_id
belongs_to :user
belongs_to :group
acts_as_likeable
end
I have setup a function named newsfeed in my post controller. The function grabs all the groups that a user is following and then grabs all the posts that have group_ids matching group_ids in the returned groups array. But I keep getting unidentified method followees(socialization provides this). Yet it appears to work when using single users and posts in irb.
def newsfeed
#groups = current_user.followees(Group)
#posts = Post.where(:group_id => #groups)
respond_to do |format|
format.html # show.html.erb
format.json { render json: #posts }
end
end
Thanks for any help.
Apparently, your current_user method returns false, instead of a user. Check what's returned from that method, as find out why you get the error...
Your current_user return false instead of instance of User. You may see it from error text.
I am trying to prevent a user from accessing a profile that is not his/hers. My UserProfile model is linked to my profile model and has a column pertaining to the user_id. My thought was use cancan and "if a user.id does not match up with the associated user_id from the user_profile" then reject. I have tried to do this in so many different combinations and permutations and have only gotten cancan to reject if use the id field correlating to the UserProfile.
With the code below I can access
http://localhost:3000/users/8/profile and http://localhost:3000/users/6/profile
so the user has permission to see "use the show method of the UserProfile" of any user. So results are fetching properly but cancan is not limiting permissions based on the current User.id
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
if user.has_role? :registered
can :show, UserProfile, :user_id => user.id
end
end
end
class UserProfile < ActiveRecord::Base
attr_accessible :DOB, :user_id, :address_city, :address_country, :address_state, :address_street, :address_zip, :avatar, :first_name, :gender, :last_name, :position, :time_zone, :years_played
belongs_to :user
end
class User < ActiveRecord::Base
has_one :user_profile, :dependent => :destroy
end
Route File
get '/users/:user_id/profile/' => "user_profiles#show", :as => :user_profile
UserProfile Controller
class UserProfilesController < ApplicationController
load_and_authorize_resource
def show
##user = User.accessible_by(current_ability)
##user = User.find(params[:user_id])
##profile = #user.user_profile
#profile = UserProfile.where(:user_id => params[:user_id]).first
respond_to do |format|
format.html # show.html.erb
format.json { render :json => #profile }
end
end
end
On our site we have a user profile page where we want to display all microposts that are relevant to that User's profile.
In our microposts table we have a belongs_to_id column and a user_id (defines who the micropost is to from)
We are trying to match the belongs_to_id with the user_id. This is so that when a profile is viewed, only microposts where the belongs_to_id matches the user_id of the profile being viewed are displayed. How could we go about doing this?
class Micropost < ActiveRecord::Base
attr_accessible :content, :belongs_to_id
belongs_to :user
validates :content, :presence => true, :length => { :maximum => 240 }
validates :user_id, :presence => true
default_scope :order => 'microposts.created_at DESC'
# Return microposts from the users being followed by the given user.
scope :from_users_followed_by, lambda { |user| followed_by(user) }
private
# Return an SQL condition for users followed by the given user.
# We include the user's own id as well.
def self.followed_by(user)
following_ids = %(SELECT followed_id FROM relationships
WHERE follower_id = :user_id)
where("user_id IN (#{following_ids}) OR user_id = :user_id",
{ :user_id => user })
end
end
UsersController:
class UsersController < ApplicationController
before_filter :authenticate, :only => [:index, :edit, :update, :destroy]
before_filter :correct_user, :only => [:edit, :update]
before_filter :admin_user, :only => :destroy
def index
#title = "All users"
#users = User.paginate(:page => params[:page])
end
def show
#user = User.find(params[:id])
#microposts = #user.microposts.paginate(:page => params[:page])
#title = #user.name
#micropost = current_user.microposts.build(params[:micropost])
end
Here's an approach with a named scope in the MicroPost class only if you want the posts where the user_id AND belongs_to are the same:
micropost.rb
class MicroPost < ActiveRecord::Base
scope :relevant_to_user, lambda{|i|
where("user_id = ? AND belongs_to_id = ?", i, i)}
end
then in the controller:
def show
#user = User.find(params[:id])
#microposts = MicroPost.relevant_to_user(#user.id)
end
EDIT: If you only need to find microposts where the belongs_to_id matches a value (in this case current_user.id) use:
def show
#microposts = MicroPost.where(:belongs_to_id=>current_user.id)
end
I'm not sure why Microposts have both belongs_to_id and user_id. But if you want to find all the Microposts whose belongs_to_id matches a given User's ID, all you need is:
#microposts = Micropost.find_all_by_belongs_to_id(#user.id)
My intention here is just to create a corresponding contact when a user
signs up, but the said contact is never created, despite using build_*
with a has_one:
Contact model:
has_one :user
User model:
belongs_to :contact
Users Controller:
def signup
#user = User.new
end
def signup_success
#user = User.find params[:id]
contact = #user.build_contact
contact.contactable = School.first
contact.save
end
protected
routes:
map.resources :users,
:collection => {
:signup => :get
},
:member => {
:signup_success => :any
}
Any idea of what I'm doing wrong? Thanks for any suggestions.
Does it work if you pass the attributes to build?
contact = #user.build_contact(:contactable => School.first)
contact.save