Reputation: 2595
Few years ago I develop aps in Rails 4 and now many things change.
I user Shire GEM in this example to upload photos:
Ok, my models:
Photo model:
class Photo < ApplicationRecord
include ImageUploader::Attachment(:image)
belongs_to :user
end
User model ( i put only few lines):
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_one :profile, :dependent => :destroy
has_many :photos, :dependent => :destroy
end
PhotosController:
class PhotosController < ApplicationController
before_action :set_photo, only: %i[ show edit update destroy ]
before_action :authenticate_user!
def create
@photo = Photo.new(photo_params)
respond_to do |format|
if @photo.save
format.html { redirect_to @photo, notice: "Photo was successfully created." }
format.json { render :show, status: :created, location: @photo }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @photo.errors, status: :unprocessable_entity }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_photo
@photo = Photo.find(params[:id])
end
# Only allow a list of trusted parameters through.
def photo_params
params.require(:photo).permit(:title, :image_data, :image, :user_id)
end
end
UsersController:
class UsersController < ApplicationController
private
# Only allow a list of trusted parameters through.
def set_user
@user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:id)
end
end
And now last thing, form for add photos in view:
<%= form_with(model: photo) do |form| %>
<% if photo.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(photo.errors.count, "error") %> prohibited this photo from being saved:</h2>
<ul>
<% photo.errors.each do |error| %>
<li><%= error.full_message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= form.label :title %>
<%= form.text_field :title %>
</div>
<div class="field">
<%= form.label :image %>
<%= form.file_field :image %>
</div>
<%= current_user.id %> // SHOWS USER ID
//// THIS GENERATE ERROR ////
<%#= form.hidden_field :user_id => current_user.id %>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
And where I have problem. When I to it in that way I see in logs unpermited parameters :user_id.
But when I submit form I see error "User must exist".
I found solution and change in PhotosController this line:
def create
@photo = Photo.new(photo_params)
to:
def create
@photo = current_user.photos.new(photo_params)
and it start working. Photo have user_id in table. But I want to know why I can't add user_id for photos in form in view like:
<%= form.hidden_field :user_id => current_user.id %>
Upvotes: 0
Views: 430
Reputation: 102222
Never pass the user id as plaintext through the parameters. Get it from the session instead. Its trivial for any malicous user to use the web inspector and simply fill in the hidden input and then upload a unseemly picture as ANY user.
The session cookie is encrypted and much more difficult to tamper with.
class PhotosController < ApplicationController
before_action :authenticate_user!
def create
# build the record off the current_user
@photo = current_user.photos.new(photo_params)
respond_to do |format|
if @photo.save
format.html { redirect_to @photo, notice: "Photo was successfully created." }
format.json { render :show, status: :created, location: @photo }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @photo.errors, status: :unprocessable_entity }
end
end
end
private
# Only allow a list of trusted parameters through.
def photo_params
params.require(:photo).permit(:title, :image_data, :image)
end
end
But I want to know why I can't add user_id for photos in form in view like:
<%= form.hidden_field :user_id => current_user.id %>
Because you're calling the method with the wrong arguments. The signature is hidden_field(object_name, method, options = {})
but as already stated its a bad idea.
Upvotes: 1