Devise - how to show user's post - ruby-on-rails

I use Devise gem for authentication.
In database I have users table and posts table in my database schema (and Post controller).
In post controller I want to find all posts assigned to specific user. I have user_id in posts table.
How to get all user's posts or how to check if specific post is assigned for SIGNED IN user.
I thought about something like this (of course is only pseudocode:
current_user.id == Post.where(params:[post_id]).user_id
So how to get current user id in Devise and how to check the current user id is the same like eg. user_id assigned to viewing post (I want to add 'edit' function when current user is post owner) and how to find all post which current user is owner.

Associations
Firstly, your user_id column in your posts table is what's known as a foreign_key
Foreign keys are used in relational database systems to give you the ability to call associative data from a single record. Simply, it means that you'll be able to use the ActiveRecord associations to call the data you require, rather than having to call it individually:
#app/models/user.rb
class User < ActiveRecord::Base
has_many :posts
end
#app/models/post.rb
class Post < ActiveRecord::Base
belongs_to :user
end
This will give you the ability to use the following call:
#app/controllers/posts_controller.rb
class PostsController < ApplicationController
def index
#posts = current_user.posts
end
end
You'll be best served looking up the has_many association:
Fix
In regards to showing your posts for your users, you need to be sure that you have the correct "flow" set up. What I mean is you need some condition to know whether your user is signed in & that #posts is set:
#app/views/posts/index.html.erb
<% if #posts.present? %>
<% #posts.each do |post| %>
<%= post.title %>
<% end %>
<% end %>

Maybe this is the first time you use Devise. You can access current_user inside controllers or views. I imagine you could do something like this
In controller (posts_controller.rb):
#posts = current_user.posts
In view (posts/show.html.erb, I guess):
if current_user.id = #post.current_user
#render something here
end

Get all post which current user is owner.
#posts = Post.where(:user_id => current_user.id)
and on your view
<%-# commented : checking if #posts is empty -%>
<% if #posts.empty? %>
<span>Sorry, post is empty </span>
<% else %>
<%= #posts.each do |p| %>
<% if p.user_id == current_user.id %>
<% link_to "edit", edit_path(p) %>
<% end %>
<% end %>
<% end %>

There are many ways you could get current_user posts. I'll go the long way.
we need
an action
an action view and a partial
a route
a link_to
* action *
def my_posts
#posts = current_user.posts.all.order(created_at: 'DESC')
end
* view *
my_posts.html.erb
<% if #posts.present? %>
<%= render 'posts' posts: #posts %>
<% else %>
<h1>You don't have any posts yet! create one</h1>
<% end %>
_posts.html.erb
<%posts.each do |post| %>
<%= post.title %>
<% end %>
index.html.erb
<%= render 'posts' posts: #posts %>
route
get 'post' => 'posts#my_posts', as: :my_posts
link_to
<%= link_to 'My posts', my_posts_path %>
I may be late but someone can find it useful :)

Related

Rails Controller Index Only Display Objects with Association

I have a Rails model called User. There are two different types of users. Some users have company_profiles in a separate table.
In my controller for my page view, I'd only like to display those users who have company_profiles. I'd also like to display their user info and their company_profile info too.
I'm not sure how to handle this in my controller and view.
What should be in my index method?
def index
#users = User.scoped # ?????
end
And how do I loop through each user with a company profile on the index page?
<% #users.each do |user| %>
<p>
<%= user.email %>
<%= user.company_profile.poc_first_name %>
</p>
<% end %>
Now you mentioned you want to show users only for which company_profile exists. So in your controller method following should be in the index method
def index
#users = User.left_outer_joins(:company_profile).where("company_profiles.id is NOT NULL")
end
Then in your views you can get company_profile's poc first name as follows
<% #users.each do |user| %>
<p><%= user.email %>
<%= user.company_profile.poc_first_name %>
</p>
<% end %>
Making an INNER JOIN when loading the records from the database should work:
def index
#users = User.joins(:company_profile)
end

Accessing further objects from the results of a loop in Rails

I don't even know what to search for on this, so I'll just explain what I'm trying to do. On my user index page I'm printing out a list of the latest users with the immediate info (stuff from the users table). How do I go about pulling the latest post by that user, then? I don't know what to do in the controller that will enable me to have access to each result separately.
Here is a simplified view:
<% #users.each do |user| %>
<%= link_to user.username, user_path(user) %><br />
<%= user.email %>
# this is where I would show the user's latest post
<% end %>
controller:
def index
#users = User.order('created_at DESC').paginate(:page => params[:page], :per_page => 24)
#user_latest_post = ???
end
You should set up User so that it has an association with Post. This allows you to access all Posts belonging to that User (like user.posts). This isn't totally necessary for your question, but is probably something you want (or have already done).
Then you need to create a second, scoped association that gets the latest Post. This way you can use includes in your controller and avoid an N+1 issue (otherwise it will do a new query for the latest post every time you iterate through a user with that each block).
Lastly, you need to choose what you want to display about the Post. Convention would have you make a shared "partial" view for Post that you can reuse. This means you can just tell Rails to render user.latest_post and it will know what to do (assuming you've defined this partial).
I give code examples below to explain what I mean:
# models/user.rb
class User < ApplicationRecord
has_many :posts
has_one :latest_post, class_name: "Post", -> { order(created_at: :desc).limit(1) }
end
# controllers/users_controller.rb
def index
#users = User.includes(:latest_post).order(created_at: :desc).paginate(:page => params[:page], :per_page => 24)
end
# views/users/index.erb
<% #users.each do |user| %>
<%= link_to user.username, user_path(user) %><br />
<%= user.email %>
<%= render user.latest_post %>
<% end %>
# views/posts/_post.erb
<%= post.text %>
# or whatever you want here

Why does link_to when used in a partial return a link to the parent object rather than the actual object?

So I have two models, Users that belong_to Organization (which has_many users). I'm using a partial to display all the users that belong to any one particular organization, and this is working fine if I output just the name (it correctly names all the users). However when I change the partial code to provide link_to user.name, the returned links are all links to the parent Organization rather than the individual child objects. What am I doing wrong?
Relevant code:
Organizations Controller
def show
#organization = Organization.find(params[:id])
#users_index = User.joins(:organization).where(organizations: {id: #organization.id})
end
Organization.show.html.erb
<% provide(:title, #organization.organization_name) %>
<h1><%= #organization.organization_name %></h1>
<h2>Your Organization's Users:</h2>
<%= render partial: "users_index", collection: #users_index %>
_users_index.html.erb code:
<p class="users"><%= link_to users_index.name %></p>
If you set up your relationship properly then you can use:
#users_index = #organization.users
And then you need to loop through #users_index and pass that to your partial.
#users_index.each do |user|
<%= render "users_index", :user => user %>
end
And in your partial, change to:
<p class="users"><%= link_to user.name, user %></p>
link_to
I think the core of the issue, as alluded to in the other answer, is your link_to:
<%= link_to users_index.name %>
The link_to helper method basically works like this:
<%= link_to "Your Link Text", link_path %>
I don't see how your application will be able to load the correct link path without your definition, irrespective of whether you added it to the helper or not.
I presume that your rendered link will point to "#", not the "parent object" as you alluded.
--
Fix
I'd do this:
#app/views/organization/show.html.erb
<%= render partial: "users_index", collection: #users_index, as: :user %>
#app/views/organization/_users_index.html.erb
<p class="users"><%= link_to user.name, user %></p>
This should set the correct link_to helper method for you
--
Models
Further, I would also address the associations in your models
You're currently calling users in the most inefficient way. ActiveRecord associations work to remedy this:
#app/models/user.rb
Class User < ActiveRecord::Base
belongs_to :organization
end
#app/models/organization.rb
Class Organization < ActiveRecord::Base
has_many :users
end
This will allow you to call the following:
#app/controllers/organizations_controller.rb
Class OrganizationsController < ApplicationController
def show
#organization = Organization.find params[:id]
#users_index = #organization.users
end
end

Feed of all posts from all users

I am trying to Implement a feed of all post from a multi user blog. I want to know where to define this method and how to define it to be as "RESTFUL" as possible.
I am thinking of putting it in the posts index view but the problem is i dont have access to the users name attribute that created that post. The index action currently looks like this
def index
#posts = Post.all
end
and doing this:
def index
#user=User.find(params[:user_id])
#posts = #user.posts.all
end
raises an error " Couldn't find User without an ID "
App info:
I have a users resource and a post resource (nested in the users). That is pretty much it.
Thanks
Clarification:
Thanks guys for the assistance so far. My controllers index action is defined as follows
def index
#users = User.all
#posts = #users.collect { |user| user.posts }.flatten
end
The issue i am having is displaying the posts users name in the view. for example this works but only displays the posts attibutes:
<% #posts.each do |post| %>
<ul>
<li> <%= post.title %>
<%= post.content %>
<%= user.name %> or <%= #user,name %> #This does not work
</li>
</ul>
I am not sure if i wrote the block correctly. Hope this clarifies things
You can do something like this:
def index
#posts = Post.includes(:user)
end
# view
<ul>
<% #posts.each do |post| %>
<li>
<%= post.title %>
<%= post.content %>
<%= post.user.name %>
</li>
<% end %>
</ul>
You should be visiting the wrong URL.
First, check your parameters in your server console, you should not see user_id param.
To set this param, use the correct route
user_posts_path(an_user_instance)
I suppose you have in routes:
resources :users do
resources :posts
end
First you need to query the users that you want...
def index
# For example...
#users = User.all # or...
#users = User.find_by_group_id(params[:group_id]) # etc...
# Then, from your users, you need to collect the posts...
#posts = #users.collect { |user| user.posts }.flatten
end
This would get an array of each users posts, then flatten it to a single array. At that point you can then sort the array to whatever you want.
I don't know what exactly you're looking for, but these are just some ideas. Depending on how you're app is structured (and the groups of users are organized), you'll likely want to use some sorted of nested resource like juanpastas posted.

Cannot manage associations in Ruby on Rails

I have a Post model which is used to store content posted by guest users, and that content is managed by an Admin user. The admin has the rights to block or unblock a particular post.
What I want to do is this:
Display all unblocked Posts to the Guest Users.
Display all Posts to the admin user.
For the first requirement, I have a model BlockedPost which has a polymorphic association with Post model. The post that will be blocked by the admin will be maintained in the BlockedPost model.
For the second requirement I have to give admin the right to block or unblock any particular content. So in my posts/index.html.erb I have done this
<% #posts.each do |post| %>
<% post.content %>
<% if post.post_blocked? %>
<td><%= link_to 'Unblock', blocked_post_path(content.id),:method => :delete%></td>
<% else %>
<td><%= link_to 'Block', create_blocked_post_path(content.id) %></td>
<% end %>
<% end %>
The post_blocked? method above is defined in the Post model:
class Post < ActiveRecord::Base
def post_blocked?
!self.blocked_posts.nil?
end
end
This works but the problem is every time the post_blocked? method is called it makes a database call.
Is there any way to stop this behavior and get the status of all posts in one database call itself?
hmm... i think you should change your models a little, because they are unconfortable a bit and there isnt any fast way to get your posts from DB,
delete BlockedPost model
and add a column to Post model (in migration)
t.boolean :blocked, :default => true
I'd do it like this:
#blocked_posts = Post.where( :blocked => false)
#unblocked_posts = Post.where( :blocked => true )
or prepare scopes in your Post model
and then in your view just display 2 lists
<% #unblocked_posts.each do |upost| %>
<%= upost.content %>
<%= link_to 'Block that post', ... %>
<% end %>
<% #blocked_posts.each do |bpost| %>
<%= bpost.content %>
<%= link_to 'Unblock', ... %>
<% end %>

Resources