I have post and user model and I have Many(posts) to One(User) association.
I want to display only the posts which are created by that user(current user).
So somehow I have to inject the currently logged in user's id into the "user_id" foreign key
of the post model during creation. I'm using Devise as my authentication system.
Any solutions of how to achieve this ?
I'm using Rails version 3.0.
Thanks in advance.
With devise simply use the "current_user" helper ;)
<% if user_signed_in? %>
<% current_user.posts.each do |post| %>
<%= post.title %>
<% end %>
<% end %>
In your PostsController#create method, you can set the Post's user to the current_user (since you are using Devise).
def create
#post = Post.create(params[:post]) do |p|
p.user = current_user
end
#respond_with(#post) or Rails 2 equivalent
end
Related
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 :)
I am a rookie in Rails. I am using Rails 4 and I could not find how they do this or what it is called.
I got this idea from devise where you can use devise and implement such thing in your application.html.erb file:
<% if user_signed_in? %>
Logged in as <strong><%= current_user.email %></strong>.
Where user is the devise model.
However when I try to search for user_signed_in or current_user variable, I cannot find it at all!
So essentially what I want to do is link this user model (which is used for devise) with another model that I created called profile. These models are linked by their ids, and if user has not created a profile, then simply ask user to create his/her profile.
To do that, I've written this to application.html.erb:
<% if user_signed_in? && (current_profile.id != current_user.id)? %>
<%= link_to 'You have not created your profile! Please create your profile first.', update_profile_index_path, :class => 'navbar-link' %>
<% else %>
<%= yield %>
<% end %>
Which does not work as expected because I have not defined current_profile. The error that I am getting is:
undefined local variable or method `current_profile' for #<#<Class:0x000000044d6c60>:0x00000005d64110>
My question is, how do I create a variable named current_profile that would contain the current profile, like current_user that devise does?
The usual setup for this is to add a Profile model with a user_id:integer field.
Define an assocition on the User model
has_one :profile
Then you can access it directly using
current_user.profile
You can do the following:
class User
has_one :profile
# ...
class Profile
belongs_to :user
# ...
module ApplicationHelper # app/helpers/application_helper.rb
def current_profile
#current_profile ||= current_user.try(:profile)
#current_profile
end
# ...
# view
<% if user_signed_in? && current_profile.blank? %>
<%= link_to 'You have not created your profile! Please create your profile first.', update_profile_index_path, :class => 'navbar-link' %>
<% else %>
<%= yield %>
<% end %>
I'm implementing a classified website where I want to let user to create classified even if he is not registered. In case he is not registered I take his name, email and phone number. Its like those form on website where one can still create record without registering by only giving his email and name because asking new user to create account would turn away potential customers I am using devise and rails 4 and was wondering how can I implement this ideally.
Class User < ActiveRecord::Base
has_many :classifieds
end
class Classified < ActiveRecord::Base
belongs_to :user
end
I'm wondering if I should create a guest user as an instance of User or need to create new model to store classified poster that is not registered.
How you do this will depend mainly on how you're going to implement the user authentication
I see you've got devise as a tag - so I'll give you some ideas for it!
--
Devise
Devise has a helper called user_signed_in? - basically tells you if your current_user object is defined (and thus that your user is logged in).
In views, you can use this helper to determine how things work. A good example is in navigation:
#app/views/elements/nav.html.erb
<% if user_signed_in? %>
<%= link_to "Logout", user_session_destroy_path, method: :delete %>
<% else %>
<%= link_to "Login", new_user_session_path %>
<% end %>
In the same way, you can use the conditional nature of user_signed_in? for your form
--
Form
You'll basically need to ensure that you're able to process the form regardless of whether the user is signed in or not (I.E handle the credentials), but you could also use a conditional statement to determine which attributes to use:
<%= form_for #classified do |f| $>
<%= f.text_field :title %>
<%= f.text_field :description %>
<% if user_signed_in? %>
<%= f.fields_for :user do |user| %>
<%= user.text_field :name %>
<%= user.text_field :email %>
<%= user.text_field :phone_number %>
<% end %>
<% end %>
<% end %>
--
Controller
When you get the controller, you'll then need to consider whether the data has been submitted as form data or not. This is where user_signed_in? will again come in handy:
#app/controllers/classifieds_controller.rb
Class ClassifiedsController < ApplicationController
def new
#classified = Classified.new
#classified.build_user unless user_signed_in?
end
def create
#classified = Classified.new(classified_params)
#classified.user = current_user if user_signed_in?
end
private
def classified_params
params.require(:classified).permit(:title, :body, user_attributes(:name, :email, :phone)
end
end
What you can do is inside your create method for classifieds, you can look for a user and if he/she doesn't exist then create a dummy user with some random password and build classifieds for that dummy user. This will also keep your associations intact. Inside your create method you can do something like this:
def create
#user = User.find(params[:user_id])
if !#user
#user = User.create(attributes = {}, ...)
end
#classified = #user.classifieds.build(attributes = {}, ...)
if #classified.save
redirect_to your_path
else
render action: "new"
end
end
You can clean it more by using rails find_or_create_by method
I'm using fields_for to create a page for editing multiple user objects in my app. I've been using this Railscast video as a point of reference. http://railscasts.com/episodes/198-edit-multiple-individually The issue I am running into is that rather than using the user id when generating the html, the form builder is inserting the user's name. I have no idea why. Below is my controller, view, and some of the html generated.
View
Manage Your User Licenses
User License Management for <%= #org.title %>
<%= form_tag update_many_user_licenses_path, :method => :put do %>
<% for user in #users %>
<%= fields_for "users[]", user do |user_fields| %>
<div><%= user.name %></div>
<div><%= user_fields.label :active_license %>
<%= user_fields.check_box :active_license %></div>
<% end %>
<% end %>
<%= submit_tag "Mark as Complete" %>
<% end %>
Controller
class UserLicensesController < ApplicationController
before_filter :authenticate_user!
def manage
#org = current_user.organization
#users = #org.users
end
def update_many
#users = User.find(params[:users])
#users.each do |user|
user.update_attributes!(params[:user].reject { |k,v| v.blank? })
end
flash[:notice] = "Updated users licenses."
redirect_to manage_user_licenses_path
end
end
HTML
<div>Tyrel Denison</div>
<div><label for="users_Tyrel-Denison_active_license">Active license</label>
<input name="users[Tyrel-Denison][active_license]" type="hidden" value="0" /><input id="users_Tyrel-Denison_active_license" name="users[Tyrel-Denison][active_license]" type="checkbox" value="1" /></div>
While I'm not familiar with the LinkedIn API Gem, based on our discussion, it seems the to_param method is being overwritten in your User model.
From the comments, this is apparently what your to_param method looks like:
def to_param # TODO USe something better than this plz
self.name.gsub(/\s+/, '-')
end
You reported that rather than using the user id when generating the html, the form builder is inserting the user's name, and as you can see, this is precisely what is happening in that method. Ultimately, fields_for calls to_param, and you don't have a choice in that matter.
I would be quite astonished that the LinkedIn gem required you to override that method, as it would most definitely break any model that used it, as you experienced (and I can't explain why the other developer decided to do that - it's possible they innocently wrote the method without realizing it already exists in the base class)
I can't give you more detailed information without examining the system more closely, however I would suggestion trying to find how/where to_param is being used (assuming it is being called explicitly somewhere), and create a separate method instead.
I'm just starting out with Ruby and Rails, trying out Devise with Rails 3. I've got a loop around a list of Posts, each of which has an associated user. I only want to display editing controls for those posts which are associated with the current user.
<% #posts.each do |post| %>
<%= link_to "show" %>
<% if current_user = post.user %>
<%= link_to "edit" %>
<% end %>
<% end %>
(The above is simplified, and from memory, so I'm sure the syntax isn't entirely right - but you get the gist.)
If no user is logged in, the posts show as intended - there's a Show link, but no Edit link. However, if I am logged in at all, all of the Edit links show up, even fir posts created by a different user.
I've verified in the console that User.find(1) != User.find(2), but for some reason the current_user = post.user evaluates to true no matter who is currently logged in. Is this to do with current_user being a helper as opposed to a "real" user object? How can I use current_user to get at the ACTUAL current user to make my comparison?
Thanks,
Dan
You're assigning rather than testing - use == - i.e.
<% if current_user == post.user %>