ruby-on-railsruby-on-rails-4image-processingcarrierwaverailscasts

In Rails 4 Create Images from one Model on the Show Page of second Model


I am having a heck of a time figuring this out...I am basically trying to follow a railscast for adding gallery images to a page, but in this case the scenario is as follows:

I have a Projects Model and a BodyImages model. The bodyimages model uses a carrierwave uploader to attach an image file to each newly created "bodyimage". While logged in as admin and viewing the Projects Show page...I aim to allow my admin user to create the BodyImage (& upload the associated carrierwave image) directly from a div in this Projects Show page. These BodyImages should display right there underneath where the upload button is (also on this Project Show Page). Doing this as two models might be ridiculous, but am just hoping to figure this out because I've been beating my head against the wall all night. I currently get this error message when I upload an image and click the 'create bodyimage' button:

Routing Error
uninitialized constant BodyimagesController

*the URL it redirects me to is localhost:3000/bodyimages for some reason (i thought i redirected in the code to the project page)

Much thanks in advance for any help:

ROUTES.RB

devise_for :users
resources :projects
resources :contacts, only: [:new, :create]

resources :bodyimages, only: [:new, :create]

get 'home/index'
root 'home#index'

get '*path' => redirect('/')

VIEWS/PROJECTS/SHOW.HTML.ERB (where the admin will upload photos and they are displayed on the same page just underneath to anyone)

<div class="gallery_admin_add_images">
  <%= form_for Bodyimage.new do |f| %>

    <%= f.hidden_field :project_id %>
    <p>
      <%= f.file_field :image %>
    </p>
    <p><%= f.submit %></p>
<% end %>

<div class="gallery_public_view_images">
  <% for bodyimage in @project.bodyimages %>
    <div class="col-md-6">
      <%= image_tag bodyimage.image_url.to_s %>
    </div>
  <% end %>
</div>

MODELS/PROJECT.RB

has_many :categorizations
  has_many :categories, through: :categorizations
  has_many :bodyimages, dependent: :destroy
end

MODELS/BODYIMAGE.RB

class Bodyimage < ActiveRecord::Base
  belongs_to :project

  mount_uploader :image, ImageUploader
end

CONTROLLERS/PROJECTS_CONTROLLER.RB

class ProjectsController < ApplicationController
  before_action :find_project, only: [:show, :edit, :update, :destroy]
  before_action :authenticate_user!, except: [:index, :show]

  def index
    @projects = Project.order('created_at DESC').paginate(page: params[:page], :per_page => 5)
  end

  def new
    @project = Project.new
  end

  def create
    @project =  Project.new project_params

    if @project.save
      redirect_to @project, notice: "your projects were successfully updated!"
    else
      render 'new', notice: "your projects could not be updated."
    end
  end

  def show
  end

  def edit
  end

  def update
    if @project.update project_params
      redirect_to @project, notice: "your projects were successfully updated!"
    else
      render 'edit'
    end
  end

  def destroy
    @project.destroy
    redirect_to projects_path
  end

  private

    def project_params
      params.require(:project).permit(:title, :description, :link, :coverimage, :slug, :remote_coverimage_url, category_ids: [])
    end

    def find_project
      @project = Project.friendly.find(params[:id])
    end

end

CONTROLLERS/BODY_IMAGES_CONTROLLER.RB

class BodyImagesController < ApplicationController
  def new
    @bodyimage = @project.bodyimages.build(project_id: current_project.id)
  end

  def create
    @project = Project.find(params[:project_id])
    @bodyimage = @project.bodyimages.build(bodyimage_params)
    if @bodyimage.save
      flash[:notice] = "Successfully added bodyimage."
      redirect_to project_path(@project)
    else
      render :action => 'new'
    end
  end

  def index
    @bodyimages = Bodyimage.all, params[:project_id]).paginate(page: params[:page]).per_page(36)
  end


  private

  def find_project
    @project = Project.find(params[:project_id])
  end

  def bodyimage_params
    params.require(:bodyimage).permit(:project_id, :image)
  end
end

Lastly, I don't think there are issues with the uploader file, but i'll include that also

UPLOADERS/IMAGE_UPLOADER.RB

# encoding: utf-8

class ImageUploader < CarrierWave::Uploader::Base

  # Include RMagick or MiniMagick support:
  include CarrierWave::RMagick
  # include CarrierWave::MiniMagick

  # Choose what kind of storage to use for this uploader:
  # storage :file if development & fog if in production
  if Rails.env.production?
    storage :fog
  else
    storage :file
  end

  include CarrierWave::MimeTypes
  process :set_content_type

  # Override the directory where uploaded files will be stored.
  # This is a sensible default for uploaders that are meant to be mounted:
  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  # Provide a default URL as a default if there hasn't been a file uploaded:
  # def default_url
  #   # For Rails 3.1+ asset pipeline compatibility:
  #   # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
  #
  #   "/images/fallback/" + [version_name, "default.png"].compact.join('_')
  # end

  # Process files as they are uploaded:
  # process :scale => [200, 300]
  #
  # def scale(width, height)
  #   # do something
  # end

  # Create different versions of your uploaded files:
  # version :thumb do
  #   process :resize_to_fit => [50, 50]
  # end
  version :thumb do
    process :resize_to_limit => [200, 200]
  end

  # Add a white list of extensions which are allowed to be uploaded.
  # For images you might use something like this:
  # def extension_white_list
  #   %w(jpg jpeg gif png)
  # end

  # Override the filename of the uploaded files:
  # Avoid using model.id or version_name here, see uploader/store.rb for details.
  # def filename
  #   "something.jpg" if original_filename
  # end

end

Solution

  • Routing Error uninitialized constant BodyimagesController

    Your Model name is Bodyimage, so the controller name should be Bodyimagescontroller. But you have BodyImagesController.

    Changing your controller file name to bodyimages_controller.rb and the class name to BodyimagesController should solve your problem

    Update

    ActiveRecord::RecordNotFound in BodyimagesController#create Couldn't find Project with 'id'=

    The error is due to this line redirect_to project_path(@project), here @project is nil because you are not passing value to the hidden_field project_id

    Changing <%= f.hidden_field :project_id %> to <%= f.hidden_field :project_id, @project.id %>