Home > Software engineering >  Ruby on Rails: How to show the image title? (Edited)
Ruby on Rails: How to show the image title? (Edited)

Time:11-21

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).

  • Related