Wasabi Developer
Wasabi Developer

Reputation: 3553

Rails 3.2.13 undefined method `photos_path' with nested resources with CarrierWave

I was hoping someone can give me some insights on how nested resources and more specifically how to tie it with CarrierWave.

I'm getting an error undefined method 'photos_path' and am a bit stuck on how do go about getting this to work.

I want to be able to have the following urls

Create a new photo

site.com/animal/dog/photos/new

Show photo

site.com/animal/dog/photos/my-dog-in-the-park

Should I be using a nested form? any help is much appreciated.

My Routes

root to: "home#index"

resources :animal do
  resources :photos
end

My home view

<%= link_to "Add Dog Photo", new_animal_photo_path(animal_permalink: "dog") %>

My _form partial

<%= form_for [@animal, @photo], :html => {:multipart => true} do |f| %>
  <%= f.hidden_field :animal_permalink %>
  <p>
    <%= f.label :title %><br />
    <%= f.text_field :title %>
  </p>
  <p>
    <%= f.file_field :image %>
  </p>
  <p>
  </p>
  <p><%= f.submit %></p>
<% end %>

My Photo model

class Photo < ActiveRecord::Base
  include ActiveModel::ForbiddenAttributesProtection

  before_create :set_permalink
  before_update :set_permalink

  belongs_to :dog
  mount_uploader :image, PhotoUploader

  def set_permalink
    self.permalink = title.parameterize
  end

  def to_param
    permalink.parameterize
  end
end

My Animal model

class Animal < ActiveRecord::Base
  include ActiveModel::ForbiddenAttributesProtection

  has_many :photos

  scope :dog, where(name: "Dog")

  def to_param
    permalink.parameterize
  end
end

My PhotoController

class PhotosController < ApplicationController

  def show
    @photo = Photo.find(params[:id])
  end

  def new
    @animal = Animal.find_by_permalink(params[:id])
    @photo = Photo.new
  end

  def create
    @photo = Photo.new(photo_params)
    if @photo.save
      flash[:notice] = "Successfully created photo."
      redirect_to root_url
    else
      render :action => 'new'
    end
  end

  def edit
    @photo = Photo.find(params[:id])
  end

  def update
    @photo = Photo.find(params[:id])
    if @photo.update_attributes(photo_params)
      flash[:notice] = "Successfully updated photo."
      redirect_to root_url
    else
      render :action => 'edit'
    end
  end

  def destroy
    @photo = Photo.find(params[:id])
    @photo.destroy
    flash[:notice] = "Successfully destroyed photo."
    redirect_to root_url
  end

  private

  def photo_params
    params.require(:photo).permit(:title, :image, :animal_id)
  end

end

Thanks for taking a look. Any help is much appreciated.

Upvotes: 0

Views: 566

Answers (1)

cgat
cgat

Reputation: 3909

I've made a few adjustments to your code.

Notice I've added an "s" to animal

root to: "home#index"

resources :animals do
  resources :photos
end

notice I've removed an "s" from animals. I've changed animal_permalink to id because that is the default that would be expected by a nested resource. Also, note that, in your photos controller new method you check for the "id" param, not the animal_permalink param.

new_animal_photo_path(id: "dog")

In your _form. set the value of the animal_permalink

<%= f.hidden_field :animal_permalink, value: @animal.permalink %>

This assumes that Photo will be able to recognize the animal_permalink attribute and that you've defined an animal.permalink method/attribute. I'm not familiar with the permalink approach, so you may have to fiddle around a bit, but this should steer you in the right direction (I would normally set the :dog_id/:animal_id attribute).

Let me know how that goes.

Upvotes: 1

Related Questions