I have a simple blog application. When posts are added, i want the users id to be added to the post so that when a user is logged in, he can only see his posts. The id i want to add to the post, is the id of the user currently logged in.
How and where could the id attribute be added to the posts model?
Session controller:
class SessionsController < ApplicationController
def new
end
def create
user = User.authenticate(params[:username], params[:password])
if user
session[:user_id] = user.id
redirect_to blog_url, :notice => "Logged in!"
else
flash.now.alert = "Invalid email or password"
render "new"
end
end
def destroy
session[:user_id] = nil
redirect_to root_url, :notice => "Logged out!"
end
end
Application controller:
class ApplicationController < ActionController::Base
protect_from_forgery
before_filter :authenticate
helper_method :current_user
private
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
def authenticate
redirect_to log_in_path unless session != nil
end
end
Posts controller:
class PostsController < ApplicationController
# GET /posts
# GET /posts.json
def index
#posts = Post.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #posts }
end
end
# GET /posts/1
# GET /posts/1.json
def show
#post = Post.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #post }
end
end
# GET /posts/new
# GET /posts/new.json
def new
#post = Post.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #post }
end
end
# GET /posts/1/edit
def edit
#post = Post.find(params[:id])
end
# POST /posts
# POST /posts.json
def create
#post = Post.new(params[:post])
post.user_id = session
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render json: #post, status: :created, location: #post }
else
format.html { render action: "new" }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# PUT /posts/1
# PUT /posts/1.json
def update
#post = Post.find(params[:id])
respond_to do |format|
if #post.update_attributes(params[:post])
format.html { redirect_to #post, notice: 'Post was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
#post = Post.find(params[:id])
#post.destroy
respond_to do |format|
format.html { redirect_to posts_url }
format.json { head :no_content }
end
end
end
Thanks in advance!
In PostsController
def create
#post = current_user.posts.build(params[:post])
...
end
Related
I was coding my Devise/CanCan combo authorization setup and running some debugging.
I keep encountering this statement everytime I refresh my browser.
Processing by Admin::UsersController#index as HTML
DEPRECATION WARNING: Relation#first with finder options is deprecated. Please bu
ild a scope and then call #first on it instead. (called from C:in `first':)
The deprecation warning says that it comes from the C:in 'first'.
But what does that supposed to mean?!?
Where am I supposed to find that in my RoR environment? Looks like it's to be found on a C folder. But my ROR project is on the D drive, not C!
Has anybody seen this warning before?
class Admin::UsersController < Admin::AdminController
load_and_authorize_resource
#def get_user
# #current_user = current_user
#end
# GET /users
# GET /users.json
def index
#users = User.all
##users = User.accessible_by(current_ability, :index).limit(20)
respond_to do |format|
format.json { render :json => #users }
format.xml { render :xml => #users }
format.html
end
end
# GET /users/1
# GET /users/1.json
def show
#user = User.find(params[:id])
respond_to do |format|
format.json { render :json => #user }
format.xml { render :xml => #user }
format.html
end
end
# GET /users/new
def new
#user = User.new
respond_to do |format|
format.json { render :json => #user }
format.xml { render :xml => #user }
format.html
end
rescue ActiveRecord::RecordNotFound
respond_to_not_found(:json, :xml, :html)
end
# GET /users/1/edit
def edit
#user = User.find(params[:id])
respond_to do |format|
format.json { render :json => #user }
format.xml { render :xml => #user }
format.html
end
rescue ActiveRecord::RecordNotFound
respond_to_not_found(:json, :xml, :html)
end
# POST /users
# POST /users.json
def create
#user.attributes = params[:user]
#user.role_ids = params[:user][:role_ids] if params[:user]
#user = User.new(params[:user])
respond_to do |format|
if #user.save
flash[:notice] = flash[:notice].to_a.concat #user.errors.full_messages
format.html { redirect_to root_url, notice: 'Signed Up!' }
format.json { render action: 'show', status: :created, location: #user }
else
flash[:notice] = flash[:notice].to_a.concat #user.errors.full_messages
format.html { render action: 'new' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /users/1
# PATCH/PUT /users/1.json
def update
#user = User.find(params[:id])
if params[:user][:password].blank?
[:password,:password_confirmation,:current_password].collect{|p| params[:user].delete(p) }
else
#user.errors[:base] << "The password you entered is incorrect" unless #user.valid_password?(params[:user][:current_password])
end
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to #user, notice: 'User was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
rescue ActiveRecord::RecordNotFound
respond_to_not_found(:js, :xml, :html)
end
# DELETE /users/1
# DELETE /users/1.json
def destroy
user = User.find(params[:id])
#user.destroy
respond_to do |format|
format.html { redirect_to users_url }
format.json { head :no_content }
end
rescue ActiveRecord::RecordNotFound
respond_to_not_found(:json, :xml, :html)
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
##user = User.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def user_params
params.require(:user).permit(:username, :password, :password_confirmation)
end
end
I've created an activity model and I'm trying to have it so that when a user deletes their activity it also deletes the corresponding status. I've been able to do it when deleting the status, it deletes the activity but not sure how to do it in the opposite direction. I tried finding the status by targetable_id but I get:
undefined method `find_by_targetable_id' for #<Class:0x8df4a70>
Parameters:
{"_method"=>"delete",
"authenticity_token"=>"s2wKOZxCBVarT5uge3AIFNXHepFuvNGM+kU/q+ArOjA=",
"id"=>"18"}
If you're familiar with the public_activity gem then targetable is the same thing as trackable and in this example, the activity id is 18 and it's corresponding status id is 53
ActivitiesController
class ActivitiesController < ApplicationController
before_filter :authenticate_member!, only: [:destroy]
before_filter :find_activity, only: [:destroy]
def index
following_ids = current_member.following_members.map(&:id)
#activities = Activity.where("member_id in (?)", following_ids.push(current_member.id)).order("created_at desc").all
end
def destroy
#status = Activity.targetable
if #status
#status.destroy
end
#activity.destroy
respond_to do |format|
format.html { redirect_to :back }
format.json { head :no_content }
end
end
private
def find_activity
#activity = current_member.activities.find(params[:id])
end
end
StatusesController
class StatusesController < ApplicationController
before_filter :authenticate_member!, only: [:new, :create, :edit, :update, :destroy]
before_filter :find_member
before_filter :find_status, only: [:edit, :update, :destroy, :show]
rescue_from ActiveRecord::RecordNotFound do
render file: 'public/404', status: 404, formats: [:html]
end
# GET /statuses
# GET /statuses.json
def index
#statuses = Status.order('created_at desc').all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #statuses }
end
end
# GET /statuses/1
# GET /statuses/1.json
def show
respond_to do |format|
format.html # show.html.erb
format.json { redirect_to profile_path(current_member) }
end
end
# GET /statuses/new
# GET /statuses/new.json
def new
#status = Status.new
#status.build_document
respond_to do |format|
format.html # new.html.erb
format.json { render json: #status }
end
end
# GET /statuses/1/edit
def edit
end
# POST /statuses
# POST /statuses.json
def create
#status = current_member.statuses.new(params[:status])
respond_to do |format|
if #status.save
current_member.create_activity(#status, 'created')
format.html { redirect_to :back }
format.json
else
format.html { redirect_to profile_path(current_member), alert: 'Post wasn\'t created. Please try again and ensure image attchments are under 10Mbs.' }
format.json { render json: #status.errors, status: :unprocessable_entity }
end
end
end
# PUT /statuses/1
# PUT /statuses/1.json
def update
if params[:status] && params[:status].has_key?(:user_id)
params[:status].delete(:user_id)
end
respond_to do |format|
if #status.update_attributes(params[:status])
format.html { redirect_to profile_path(current_member), notice: 'Status was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #status.errors, status: :unprocessable_entity }
end
end
end
# DELETE /statuses/1
# DELETE /statuses/1.json
def destroy
#activity = Activity.find_by_targetable_id(params[:id])
if #activity
#activity.destroy
end
#status.destroy
respond_to do |format|
format.html { redirect_to :back }
format.json { head :no_content }
end
end
private
def find_member
#member = Member.find_by_user_name(params[:user_name])
end
def find_status
#status = current_member.statuses.find(params[:id])
end
def sortable_date
created_at
end
end
Should not this line
#status = Activity.targetable
be
#status = #activity.targetable
?
Second note: it probably will be better to move status destroying to Activity model before_destroy callback.
In my Rails app, I have a comments scaffold which lets users comment on a movie.
I am faced with two problems.
The first problem is that anyone can create a comment, even if they are not signed in, how would I assign a comment to a user, so if there is a current_user, they can create a comment and I would be able to assign the user to the comment so <%= comment.user.first_name %>, and if they are not signed in, they cant create a comment. How would i do this? ( I am using devise )
The second problem is that when I create a comment, it takes me to this path (where 12 is :movie_id)
localhost:3000/movies/12/comments/new
This is fine but when i am creating the comment, I have to specify the movie_id (12), how this be done automatically, so rails sees that the movie_id for the comment is 12.
My Comments Controller, incase needed
class CommentsController < ApplicationController
# GET /comments
# GET /comments.json
before_filter :load_movie
def index
#comments = #movie.comments.all
#search = Movie.search(params[:q])
respond_to do |format|
format.html # index.html.erb
format.json { render json: #comments }
end
end
# GET /comments/1
# GET /comments/1.json
def show
#comment = Comment.find(params[:id])
#search = Movie.search(params[:q])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #comment }
end
end
# GET /comments/new
# GET /comments/new.json
def new
#comment = Comment.new
#search = Movie.search(params[:q])
respond_to do |format|
format.html # new.html.erb
format.json { render json: #comment }
end
end
# GET /comments/1/edit
def edit
#comment = Comment.find(params[:id])
#search = Movie.search(params[:q])
end
# POST /comments
# POST /comments.json
def create
#comment = Comment.new(params[:comment])
#search = Movie.search(params[:q])
respond_to do |format|
if #comment.save
format.html { redirect_to :back }
format.json { render json: #comment, status: :created, location: #comment }
else
format.html { render action: "new" }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
# PUT /comments/1
# PUT /comments/1.json
def update
#comment = Comment.find(params[:id])
#search = Movie.search(params[:q])
respond_to do |format|
if #comment.update_attributes(params[:comment])
format.html { redirect_to (#movie), notice: 'Comment was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
# DELETE /comments/1
# DELETE /comments/1.json
def destroy
#comment = Comment.find(params[:id])
#comment.destroy
respond_to do |format|
format.html { redirect_to comments_url }
format.json { head :no_content }
end
end
private
def load_movie
#movie = Movie.find_by_id(:movie_id)
end
end
First:
using devise, you can request that a user is signed in by saying at the top of your controller:
before_filter :authenticate_user!, only: [:new,:create]
so if someone not signed in tries to access these actions, they are redirected to the sign in page and after sign in forwarded to the original request.
Second:
As you can see from the routes, 12 is assigned to params[:movie_id]. So in your controllers new action write:
#movie = Movie.find(params[:movie_id])
#comment = #movie.comments.new
#comment.user=current_user
I have a website I am making that tracks a users companies through employments. I need to know what I am doing wrong because when I make a new user company the user doesn't know about it.
companies_controller.rb
class CompaniesController < ApplicationController
# GET /companies
# GET /companies.json
def index
#companies = current_user.companies
respond_to do |format|
format.html # index.html.erb
format.json { render json: #companies }
end
end
# GET /companies/1
# GET /companies/1.json
def show
#company = Company.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #company }
end
end
# GET /companies/new
# GET /companies/new.json
def new
#company = Company.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #company }
end
end
# GET /companies/1/edit
def edit
#company = Company.find(params[:id])
end
# POST /companies
# POST /companies.json
def create
#company = Company.new(params[:company])
current_user.employments.create!(company_id: #company.id)
respond_to do |format|
if #company.save
format.html { redirect_to #company, notice: 'Company was successfully created.' }
format.json { render json: #company, status: :created, location: #company }
else
format.html { render action: "new" }
format.json { render json: #company.errors, status: :unprocessable_entity }
end
end
end
# PUT /companies/1
# PUT /companies/1.json
def update
#company = Company.find(params[:id])
respond_to do |format|
if #company.update_attributes(params[:company])
format.html { redirect_to #company, notice: 'Company was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #company.errors, status: :unprocessable_entity }
end
end
end
# DELETE /companies/1
# DELETE /companies/1.json
def destroy
#company = Company.find(params[:id])
#company.destroy
respond_to do |format|
format.html { redirect_to companies_url }
format.json { head :no_content }
end
end
end
The problem is within your create action, specifically the line
current_user.employments.create!(company_id: #company.id)
this is executed before the company record is saved so it doesn't have an id (== nil). Just move that line after
if #company.save
and it should attach it to the current_user via the :through relationship.
I want my visitors to be able to edit or delete their comment up too 5-10 min after they created it.
How should I authenticate this with a session or cookie?
My comment controller:
class CommentsController < ApplicationController
# GET /comments
# GET /comments.xml
# GET /comments/new
# GET /comments/new.xml
def new
#comment = Comment.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #comment }
end
end
# GET /comments/1/edit
def edit
#comment = Comment.find(params[:id])
end
# POST /comments
# POST /comments.xml
def create
#blog = Blog.find(params[:blog_id])
params[:comment][:ip] = request.remote_ip
#comment = #blog.comments.create!(params[:comment])
redirect_to #blog
end
# PUT /comments/1
# PUT /comments/1.xml
def update
#comment = Comment.find(params[:id])
respond_to do |format|
if #comment.update_attributes(params[:comment])
format.html { redirect_to(admin_comments_path, :notice => 'Comment was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #comment.errors, :status => :unprocessable_entity }
end
end
end
# DELETE /comments/1
# DELETE /comments/1.xml
def destroy
#comment = Comment.find(params[:id])
#comment.destroy
respond_to do |format|
format.html { redirect_to(admin_comments_url, :notice => 'Indlæg slettet') }
format.xml { head :ok }
end
end
end
store the saved comment's id in the session and then at the time of delete or update, check the session for the comment's id and compare the current-time with the comment's created_at... this can go in a filter method.
Also, you can move the code of finding the comment with id in a filter and can follow DRY.
Here it goes:
class CommentsController < ApplicationController
before_filter :get_blog
before_filter :get_comment, :only => [:edit, :update, :destroy]
before_filter :authorize_comment, :only => [:edit, :update, :destroy]
private
def get_blog
#blog = Blog.find(params[:blog_id])
end
def get_comment
#comment = Comment.find(params[:id])
end
def authorize_comment
unless #comment
flash[:error] = "Comment Not Found"
redirect_to #blog and return
else
# checks whether the comment is there in sessions' recent_comments
# if true, it means, this comment was created by the same visitor who is now attempting to delete/update it again
if session[:recent_comments].include?(#comment.id)
# now check if the comment is editable w.r.t time or not
if #comment.created_at < 10.minutes.ago
# if true, it means comment can no longer be updated/deleted
# if you wish you can now remove this from the session's recent_comments
session[:recent_comments].delete(#comment.id)
flash[:error] = "Sorry, you can not change this comment now"
redirect_to #blog and return
else
# it means comment can be edited/updated
return true
end
else
flash[:error] = "Sorry, you can not change this comment now"
redirect_to #blog and return
end
end
end
public
def new
#comment = Comment.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #comment }
end
end
def edit
end
def create
params[:comment][:ip] = request.remote_ip
#comment = #blog.comments.create!(params[:comment])
unless session[:recent_comments].is_a?(Array)
session[:recent_comments] = []
end
session[:recent_comments] << #comment.id
redirect_to #blog
end
def update
respond_to do |format|
if #comment.update_attributes(params[:comment])
format.html { redirect_to(admin_comments_path, :notice => 'Comment was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #comment.errors, :status => :unprocessable_entity }
end
end
end
def destroy
#comment.destroy
respond_to do |format|
format.html { redirect_to(admin_comments_url, :notice => 'Indlæg slettet') }
format.xml { head :ok }
end
end
end