1

I have form for inputing albums and also the songs that belong to the album. Albums are saving to database, but individual songs are not saving.

Albums model

class Album < ActiveRecord::Base
    belongs_to :user
    has_many :songs, :dependent => :destroy
    accepts_nested_attributes_for :songs
    has_attached_file :image, :styles => { :large => "500x500>", :medium => "300x300>", :thumb => "100x100>" }

    validates :image, presence: true
    validates :title, presence: true

    extend FriendlyId
    friendly_id :title, use: :slugged


end

Songs model

class Song < ActiveRecord::Base
    belongs_to :album

    extend FriendlyId
    friendly_id :title, use: :slugged
end

Albums controller

class AlbumsController < ApplicationController
  before_action :set_album, only: [:show, :edit, :update, :destroy]
  before_action :authenticate_user!, except: [:index, :show]
  before_filter :verify_is_admin, except: [:index, :show]


  def index
    @albums = Album.all.order("created_at DESC").paginate(:page => params[:page], :per_page => 8)
  end

  def show
  end

  def new
    @album = current_user.albums.build
    3.times { @album.songs.build }
  end

  def edit
  end

  def create
    @album = current_user.albums.build(album_params)
    if @album.save
      redirect_to @album, notice: 'Album was successfully created.'
    else
      render action: 'new'
    end
  end

  def update
    if @album.update(album_params)
      redirect_to @album, notice: 'Album was successfully updated.'
    else
      render action: 'edit'
    end
  end

  def destroy
    @album.destroy
    redirect_to albums_url
  end


  private

    def verify_is_admin
      (current_user.nil?) ? redirect_to(root_path) : (redirect_to(root_path) unless current_user.admin?)
    end

    # Use callbacks to share common setup or constraints between actions.
    def set_album
      @album = Album.find_by_slug(params[:id])
    end

    def correct_user
      @album = current_user.albums.find_by(id: params[:id])
      redirect_to albums_path, notice: "Not authorized to edit this album" if @album.nil?
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def album_params
      params.require(:album).permit(:title, :image, :embed, :embed_html)
    end
end

Songs controller

class SongsController < ApplicationController
  before_action :set_song, only: [:show, :edit, :update, :destroy]


  def index
    @songs = Song.all
  end

  def show
  end

  def new
    @song = Song.new
  end

  def edit
  end

  def create
    @song = Song.new(song_params)

    respond_to do |format|
      if @song.save
        format.html { redirect_to @song, notice: 'Song was successfully created.' }
        format.json { render action: 'show', status: :created, location: @song }
      else
        format.html { render action: 'new' }
        format.json { render json: @song.errors, status: :unprocessable_entity }
      end
    end
  end

  def update
    respond_to do |format|
      if @song.update(song_params)
        format.html { redirect_to @song, notice: 'Song was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: 'edit' }
        format.json { render json: @song.errors, status: :unprocessable_entity }
      end
    end
  end

  def destroy
    @song.destroy
    respond_to do |format|
      format.html { redirect_to songs_url }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_song
      @song = Song.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def song_params
      params.require(:song).permit(:title)
    end
end

and here is the form for the new album view

<%= form_for @album, html: { multipart: true } do |f| %>
  <% if @album.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@album.errors.count, "error") %> prohibited this album from being saved:</h2>

      <ul>
      <% @album.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="form-group">
    <%= f.label :Artwork %>
    <%= f.file_field :image, class: "form-control" %>
  </div>

  <div class="form-group">
    <%= f.label :title %>
    <%= f.text_field :title, class: "form-control" %>
  </div>

  <div class="form-group">
  <%= f.fields_for :songs do |builder| %>
    <fieldset>
      <%= builder.label :title, "Song" %><br />
      <%= builder.text_field :title, :rows => 3 %>
    </fieldset>
  <% end %>
  </div>

  <div class="form-group">
    <%= f.submit class: "btn btn-primary" %>
  </div>

<% end %>

1 Answer 1

2

You need to tell your strong parameters about the song params:

def album_params
  params.require(:album).permit(:title, :image, :embed, :embed_html,
                                :songs_attributes => [:id, :_destroy, :title])
end

Don't forget to include all of the song's attributes that you want to be able to update.

Sign up to request clarification or add additional context in comments.

Comments

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.