0

Description:

I'm working on a Rails application where I have a Picture model that has a nested Pictureclass model. The index (the gallery of pictures) and the show (a detail of the picture) are showing their category, tipu, and style values. The form for editing/creating also works well, but when I try to create/update a Picture record, I encounter the following error:

NoMethodError in PicturesController#update undefined method `category_id' for an instance of Picture

Controller

class PicturesController < ApplicationController
  before_action :set_picture, only: %i[ show edit update destroy ]

  def index
    @pictures = Picture.where('start_date >= ?', Date.today).order(start_date: :asc)
    @pictureclasses = Pictureclass.where(picture_id: @pictures.pluck(:id)).includes(:category, :ritme, :tipu)
    @categories = @pictureclasses.map(&:category)
    @styles = @pictureclasses.map(&:style)
    @tipus = @pictureclasses.map(&:tipu)
  end

  def show
    @pictureclasses = Pictureclass.where(picture_id: @picture.id).includes(:category, :ritme, :tipu)
    @categories = @pictureclasses.map(&:category)
    @styles = @pictureclasses.map(&:style)
    @tipus = @pictureclasses.map(&:tipu)
  end

  def edit
    @picture = Picture.find_by(slug: params[:id])
    @picture.build_pictureclass if @picture.pictureclass.nil?
    @pictureclasses = Pictureclass.where(picture_id: @picture.id).includes(:category, :ritme, :style)
  end

  def update
    if @picture.update(picture_params)
      redirect_to @picture, notice: "Picture was successfully updated."
    else
      render :edit, status: :unprocessable_entity
    end
  end

  private

  def set_picture
    @picture = Picture.friendly.find(params[:id])
  end

  def picture_params
    params.require(:picture).permit(:start_date, :start_time, :start_point, :title, :descripcio, :ruta_foto, :Km, :slug, :max_inscrits, :min_inscrits, :num_dies, :fi_ndies, :oberta, pictureclass_attributes: [:id, :category_id, :tipu_id, :style_id])
  end
end

Models:

class Picture < ApplicationRecord
  has_one :pictureclass, dependent: :destroy
  accepts_nested_attributes_for :pictureclass, allow_destroy: true
  has_one :category, through: :pictureclass
  has_one :tipu, through: :pictureclass
  has_one :style, through: :pictureclass

end

class Pictureclass < ApplicationRecord
  belongs_to :category
  belongs_to :style
  belongs_to :tipu
  belongs_to :picture
end

class Category < ApplicationRecord
  has_many :pictureclasses, dependent: :destroy
  has_many :pictures, through: :pictureclasses
end

class Tipu < ApplicationRecord
  has_many :pictureclasses, dependent: :destroy
  has_many :pictures, through: :pictureclasses
end

class Style < ApplicationRecord
  has_many :pictureclasses, dependent: :destroy
  has_many :pictures, through: :pictureclasses
end

Form

<%= form_with(model: @picture, class: "contents text-sm") do |form| %>
  <%= form.fields_for :pictureclass do |pictureclass_form| %>
    <div class="field">
      <%= pictureclass_form.label :category_id %>
      <%= pictureclass_form.collection_select :category_id, Category.all, :id, :name %>
    </div>
    <div class="field">
      <%= pictureclass_form.label :tipu_id %>
      <%= pictureclass_form.collection_select :tipu_id, Tipu.all, :id, :name %>
    </div>
    <div class="field">
      <%= pictureclass_form.label :style_id %>
      <%= pictureclass_form.collection_select :style_id, Style.all, :id, :name %>
    </div>
  <% end %>
<% end %>

Steps Taken:

  • Ensured that accepts_nested_attributes_for is set up in the Picture model.
  • Verified that the form is correctly structured to handle nested attributes.
  • Checked that the picture_params method permits the nested attributes.

Question:

What might be causing the NoMethodError for category_id when updating a Picture record, and how can I resolve it?

5
  • do you have validations in the Picture class? Commented Aug 18, 2024 at 4:26
  • Thanks, @Alex. The validations have to be in the Pictureclass model and not in the Picture model. I have moved the validations to Pictureclass, and now the edit and create actions are working well. Commented Aug 18, 2024 at 6:59
  • code class Sortideclass < ApplicationRecord belongs_to :category belongs_to :ritme belongs_to :tipu belongs_to :sortide validates :category_id, presence: true validates :tipu_id, presence: true validates :ritme_id, presence: true end code Commented Aug 18, 2024 at 7:00
  • 1
    you don't actually need these validations. belongs_to associations are already required by default, they have their own validation. Commented Aug 18, 2024 at 8:48
  • Your assocations are most likely backwards. If you want to ensure that a Picture can only have one Pictureclass you should store pictureclass_id on the pictures table and use belongs_to :pictureclass instead of has_one which is really just has_many with LIMIT 1 stuck on the end of the query. Commented Aug 21, 2024 at 14:03

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.