rails user_id add to a picture - ruby-on-rails

I let users to upload photos using paperclip, but there is no ownership in the photo. Which means, I don't know who uploaded the photos at all.
Here, I would like when someone uploads a picture you know which user uploaded it. i have a user_id column. but i dont know how to implement the code in the pic controller
How do I do that? Thanks!
class PicsController < ApplicationController
before_action :find_pic, only: [:show, :edit, :update, :destroy]
def index
#user = User.find( params[:user_id])
#pics = Pic.all.order("created_at DESC")
end
def show
end
def new
#pic = Pic.new
end
def create
#pic.user = current_user
#pic = Pic.new(pic_params)
if #pic.save
redirect_to #pic, notice: "Yes it was posted"
else
render 'new'
end
end
def edit
#user = User.find(params[:user_id])
#profile = #user.profile
end
def update
if #pic.update(pic_params)
redirect_to #pic, notice: "Congrates Pic was upaded"
else
render 'new'
end
end
def destroy
#pic.destroy
redirect_to users_path
end
private
def pic_params
params.require(:pic).permit(:title, :description, :profile_id)
end
def find_pic
#pic = Pic.find(params[:id])
end
end
class UsersController < ApplicationController
before_action :authenticate_user!
def index
#pics = Pic.all.order("created_at DESC")
end
def show
#user = User.find(params[:id])
#pics = User.find_by(user_name: params[:user_name])
end
end
class ProfilesController < ApplicationController
before_action :authenticate_user!
before_action :only_current_user
def new
#user = User.find( params[:user_id])
#profile = Profile.new
end
def create
#user = User.find(params[:user_id])
#profile = #user.build_profile(profile_params)
if #profile.save
redirect_to user_path( params[:user_id])
else
render action: :new
end
end
def edit
#user = User.find(params[:user_id])
#profile = #user.profile
end
def update
#user = User.find(params[:user_id])
#profile = #user.profile
if #profile.update_attributes(profile_params)
flash[:success] = "Profile Updated"
redirect_to user_path(params[:user_id])
else
render action: :edit
end
end
private
def profile_params
params.require(:profile).permit(:avatar, :user_name, :contact_email, :description)
end
def only_current_user
#user = User.find(params[:user_id])
redirect_to(root_url) unless #user == current_user
end
end

If the user can be identified during the upload process, you can try to pass the user_id in a hidden_field during upload. You said you already created the user_id column.
<%= f.hidden_field :user_id , value: #user.id %>
for this code to work you need to find the #user in your controller action. Similar to what you are doing already in your 'index' action: find user by the :user_id
If you are using devise for User you can use current_user.id instead.

Related

Data cannot be saved to database the first time

I have this code, it works perfectly for me, the problem is that it does not save me in the database the first time, I must reload the page and then try again to make it work.
I can't find the error
then I am going to leave you the code of my controller so that you can give me a hand of what may be happening
class EvolutionsController < ApplicationController
before_action :load_patient
before_action :set_evolution, only: :show
before_action :verify_permission, only: %i[new show create edit update destroy]
def index
#evolutions = #patient.evolutions # You could skip this and just use #patient.evolutions in your view if you like
end
def show
end
def new
#evolution = #patient.evolutions.build
end
def create
#evolution = #patient.evolutions.build(evolution_params)
if #evolution.save
redirect_to patients_url, notice: 'La evolucion fue agregada con exito'
else
render :new
end
end
def edit
end
def destroy
#evolution = #patient.evolutions.find(params[:id])
#evolution.destroy
redirect_to patient_path(#patient)
flash[:notice] = "EvoluciĆ³n eliminada"
end
private
def load_patient
#patient = Patient.find(params[:patient_id])
end
def set_evolution
#evolution = #patient.evolutions.find(params[:id])
end
def verify_permission
redirect_to patients_path if !user_signed_in? || #patient.user != current_user
end
def evolution_params
params.require(:evolution).permit(:motivo, :entrevista, :patient_id)
end
end

The action 'destroy' could not be found for MessagesController 1

I keep getting the error destroy action can not be found in the messagesController. But i have the destroy action setup i don't get why i am getting this message error. Can some one tell me why i can getting this error?
class MessagesController < ApplicationController
before_action :find_message, only: [:show, :edit, :update, :destroy]
def index
#messages = Message.all.order("created_at DESC")
end
def show
end
def new
#message = Message.new
end
def create
#message = Message.new(message_params)
if #message.save
redirect_to root_path
else
render 'new'
end
def edit
end
def update
if #message.update(message_params)
redirect_to message_path
else
render 'edit'
end
end
def destroy
#message.destroy
redirect_to root_path
end
end
private
def message_params
params.require(:message).permit(:title, :description)
end
def find_message
#message = Message.find(params[:id])
end
end
You missed an end closure for your create action. The right way should be this:
def create
#message = Message.new(message_params)
if #message.save
redirect_to root_path
else
render 'new'
end
end
def edit
end
Your create action is missing an end statement:
def create
#message = Message.new(message_params)
if #message.save
redirect_to root_path
else
render 'new'
end
# This is defined before create is closed
def edit
end

User can't be blank on Rails

Hello I am learning rails and I have made a mistake that error message shows when I submit the article but can't seem to know where the problem is. I think it's a controller?
Github files of my code:
GitHub Project
users_controller.rb
class UsersController < ApplicationController
def index
#users = User.all
end
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
flash[:success] = "welcome to the alpha blog #{#user.username}"
redirect_to articles_path
else
render 'new'
end
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
if #user.update(user_params)
flash[:success] = "Your account was updated successfully"
redirect_to articles_path
else
render 'edit'
end
end
def show
#user = User.find(params[:id])
end
private
def user_params
params.require(:user).permit(:username, :email, :password)
end
end
articles_controller.rb
class ArticlesController < ApplicationController
before_action :set_article, only: [:edit, :update, :show, :destroy]
# Helppppp!
def index
#articles = Article.all
end
def new
#article = Article.new
end
def edit
#article = Article.find(params[:id])
end
def create
#article = Article.new(article_params)
#article.user = User.new
if #article.save
flash[:success] = "Article was successfully created"
redirect_to article_path(#article)
else
render :new
end
end
def update
if #article.update(article_params)
flash[:success] = "Article was successfully updated."
redirect_to article_path(#article)
else
render 'edit'
end
end
def show
end
def destroy
#article.destroy
flash[:danger] = "Article was successfully deleted"
redirect_to articles_path
end
private
def set_article
#article = Article.find(params[:id])
end
def article_params
params.require(:article).permit(:title, :description)
end
end
Look at your method:
def create
#article = Article.new(article_params)
#article.user = User.new
...
end
You are trying to assign empty user to your article object. You should pass user_id as a param (don't forget to add it as a permitted param in article_params) and your code should be:
#article.user = User.find(article_params[:user_id])
Fixed it by defining current_user method in the application_controller.rb and added the following:
**application_controller.rb**
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
helper_method :current_user, :logged_in?
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
def logged_in?
!!current_user
end
def require_user
if !logged_in?
flash[:danger] = "You must be logged in to perform that action"
redirect_to root_path
end
end
end
articles_controller.rb
class ArticlesController < ApplicationController
before_action :set_article, only: [:edit, :update, :show, :destroy]
before_action :require_user, except: [:index, :show]
before_action :require_same_user, only: [:edit, :update, :destroy]
def index
#articles = Article.paginate(page: params[:page], per_page: 5)
end
def new
#article = Article.new
end
def edit
end
def create
#article = Article.new(article_params)
#article.user = current_user #code that needs fix
if #article.save
flash[:success] = "Article was successfully created"
redirect_to article_path(#article)
else
render :new
end
end
def update
if #article.update(article_params)
flash[:success] = "Article was successfully updated."
redirect_to article_path(#article)
else
render 'edit'
end
end
def show
end
def destroy
#article.destroy
flash[:danger] = "Article was successfully deleted"
redirect_to articles_path
end
private
def set_article
#article = Article.find(params[:id])
end
def article_params
params.require(:article).permit(:title, :description)
end
def require_same_user
if current_user != #article.user
flash[:danger] = "You can only edit or delete your own article"
redirect_to root_path
end
end
end

Displaying most recent comments in my def show action

I am having a bit of trouble displaying the most recent created comments based from the time/date that they were created in my views/post/show.htmlerb file. I just got my posts_controller to display the most recent created posts from the def index action but now in my def show action the following code doesn't work:
#comment_date_order = Comment.find(params[:id]).comments.order('created_at DESC')
this is my full posts_controller.rb file:
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :vote]
before_action :require_user, only: [:new, :create, :edit, :update, :vote]
before_action :require_creator, only:[:edit, :update]
def index
#posts = Post.page(params[:page]).order('created_at DESC').per_page(10)
end
def show
#comment = Comment.new
#comment_date_order = Post.find(params[:id]).comments.order('created_at DESC')
end
def new
#post = Post.new
end
def create
#post = Post.new(post_params)
#post.creator = current_user
if #post.save
flash[:notice] = "You created a post!"
redirect_to posts_path
else
render :new
end
end
def edit
end
def update
#post = Post.find(params[:id])
if #post.update(post_params)
flash[:notice] = "You updated the post!"
redirect_to post_path(#post)
else
render :edit
end
end
def vote
Vote.create(voteable: #post, creator: current_user, vote: params[:vote])
respond_to do |format|
format.js { render :vote } # Renders views/posts/vote.js.erb
end
end
private
def post_params
params.require(:post).permit(:url, :title, :description)
end
def set_post
#post = Post.find(params[:id])
end
def require_creator
access_denied if #post.creator != current_user
end
end
comments_controller.erb file:
class CommentsController < ApplicationController
before_action :require_user
def create
#post = Post.find(params[:post_id])
#comment = Comment.new(params.require(:comment).permit(:body))
#comment.post = #post
#comment.creator = current_user
if #comment.save
flash[:notice] = "Your comment was created!"
redirect_to post_path(#post)
else
render 'posts/show'
end
end
def edit
#comment = Comment.find(params[:id])
#post = Post.find(params[:post_id])
end
def update
#comment = Comment.find(params[:id])
if #comment.update(comment_params)
flash[:notice] = "You updated your comment!"
redirect_to post_path(#post)
else
render :edit
end
end
private
def comment_params
params.require(:comment).permit(:body)
end
def set_comment
#comment = Comment.find(params[:id])
end
end
First you would need a relation between Post and Comment if you dont already.
I would just create a def in the Post model.
class Post < ActiveRecord::Base
has_many :comments
def newest_comments
self.comments.order('created_at DESC')
end
end
That way you could also make a oldest_post method and uses it directly in the view
<%= #post.newest_post.each do |comment| %>
Also as best practice. Try and not to create too many instance vars in your controller. Remember fat models, skinny controllers.

Best way to avoid duplication of related objects in the actions new and create

To create an user in the example bellow I have to load #projects and #companies as they are mandatory for creating user.
class UsersController < ApplicationController
def new
#user = User.new
# duplication here
#projects = Project.all
#companies = Company.all
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to #user
else
# and here
#projects = Project.all
#companies = Company.all
render :action => "new"
end
end
end
I have to load these dependencies in both (duplication) cases, for the new and create action when the user is invalid.
I can refactor by encapsulating these dependencies in a method load_user_dependencies.
class UsersController < ApplicationController
def new
#user = User.new
load_user_dependencies
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to #user
else
load_user_dependencies
render :action => "new"
end
end
private
def load_user_dependencies
#projects = Project.all
#companies = Company.all
end
end
Or by adding them as a helper_methods.
class UsersController < ApplicationController
helper_method :projects, :companies
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to #user
else
render :action => "new"
end
end
def projects
#projects ||= Project.all
end
def companies
#companies ||= Company.all
end
end
I can also create a View Object
class UserView
def products
#products ||= Product.all
end
def companies
#companies ||= Company.all
end
end
class UsersController < ApplicationController
def new
#user = User.new
#user_view = UserView.new
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to #user
else
#user_view = UserView.new
render :action => "new"
end
end
end
Other option is to use a Presenter
class UserPresenter < SimpleDelegator
def products
#products ||= Product.all
end
def companies
#companies ||= Company.all
end
end
class UsersController < ApplicationController
def new
#user = UserPresenter.new User.new
end
def create
#user = UserPresenter.new User.new(params[:user])
if #user.save
redirect_to #user
else
render :action => "new"
end
end
end
How do you guys usually deal with scenario?
It's a bit of a personal taste issue, but in our projects if it's suitable we do it in the view, and if it's complex we do it in a before_filter.
View - suitable if it's something that doesn't have any logic, no need to create a variable for this. Super useful if your form is contained in a partial as it's only done once so easily maintained.
<%= form.select :project_id, Project.all, :id, :name %>
If it's something that can change depending on any factors then a before_filter in controller:
MyController
before_filter :find_projects, :except => [:destroy, :some_method] # Will load the values but not for the destroy or some_method actions
def find_projects
#projects = Project.where(:some conditions => true)
end

Resources