I want to show the image title above the image after redirecting to user profile. I upload an image with a title and it only shows the image with the tags and user. I tried by adding the code in show.html.haml below but the title doesn't show at all. What I am doing wrong?
photos_controller.rb
class PhotosController < ApplicationController
def create
@user = User.find(params[:user_id])
if params[:photo][:title] == ""
flash[:alert] = "Please enter an image title"
redirect_to :back
elsif params[:photo][:image] == nil
flash[:alert] = "Please upload a photo"
redirect_to :back
else
@photo = Photo.create(photo_params)
@photo.user_id = @user.id
@photo.save
flash[:notice] = "Successfully uploaded a photo"
redirect_to user_path(@user)
end
end
def new
@user = User.find(params[:user_id])
@photo = Photo.create()
end
private
def photo_params
params.require(:photo).permit(:image, :title)
end
end
photo.rb
class Photo<ActiveRecord::Base
belongs_to :user
has_many :tags
has_attached_file :image, :styles => { :medium => "300x300>", :thumb => "100x100>" }
validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/
validates :title, :presence => true
end
20150318211456_photos_table.rb
class PhotosTable < ActiveRecord::Migration
def change
create_table :photos do |photons|
photons.column :user_id, :integer
photons.column :title, :string
photons.timestamps
end
end
end
new.html.haml
%h1 Add a Photo
= form_for Photo.new(), :url => user_photos_path, :html => {:multipart => true} do |form|
= form.label :title
= form.text_field :title
%br
%br
= form.file_field :image
%br
%br
%br
= form.submit 'Upload', class: "btn btn-primary btn-lg"
show.html.haml
= link_to @user_photos_path do
= @photo.title
= image_tag @photo.image.url
= image_tag @photo.image.url(:thumb)
CodePudding user response:
You can add a field for :caption
just like you've done with :image
:
class PhotosController < ApplicationController
...
def new
@user = User.find(params[:user_id])
@photo = Photo.new() # don't create the photo yet
end
private
def photo_params
params.require(:photo).permit(:image, :caption) # allow caption field
end
end
new.html.erb
<h1>Add a Photo</h1>
<%= form_for Photo.new(), :url => user_photos_path, :html => {:multipart => true} do |form| %>
<%= form.text_field :caption %>
<%= form.file_field :image %>
<%= form.submit 'Upload'%>
<% end %>
show.html.erb
<p><%= @photo.caption %></p>
<%= image_tag @photo.image.url %>
<%= image_tag @photo.image.url(:thumb) %>
CodePudding user response:
Your attempt is creative but it doesn't really have anything to do with how you actually do CRUD in Rails:
class User < ActiveRecord::Base
has_many :photos
end
class PhotosController < ApplicationController
before_action :set_user
# POST /users/1/photos
def create
@photo = @user.photos.new(photo_params)
if @photo.save
flash[:notice] = "Successfully uploaded a photo"
redirect_to @user
else
render :new
end
end
# GET /users/1/photos/new
def new
@photo = @user.photos.new
end
private
def set_user
@user = User.find(params[:user_id])
end
def photo_params
params.require(:photo)
.permit(:image, :caption)
end
end
You are confusing the Photo.new
method which is used to initialize new instances in memory and the Photo.create
method which will also save the record in the database - you don't want to do that in the new
method in your controller.
if params[:photo] == nil
is pointless. params.require(:photo)
will raise a ActionController::ParameterMissing
exception is the parameter is not present. If you want to ensure that the user has uploaded a photo or that the caption is present you use validations in your model.
What you're not checking is the one thing thats actually important - that the record is actually valid and was saved in the DB.
Use form_with
instead of the older form_for
which is slated for eventual deprechiation and bind the form to the model instance you create in your controller:
<h1>Add a Photo</h1>
<%= form_with model: [@user, @photo], html: { multipart: true} do |form| %>
<div >
<%= form.label :image %>
<%= form.file_field :image %>
</div>
<div >
<%= form.label :caption %>
<%= form.text_field :caption %>
</div>
<div >
<%= form.submit 'Upload'%>
</div>
<% end %>
That way the form will retain the user input when there is an invalid form submission. Thats why you call render :new
instead of redirect_to :back
. The later also doesn't actually work in case the client doesn't send a HTTP_REFERRER header (in other words don't use it).