Search code examples
ruby-on-railsmodel-associations

Rails Many-to-many :through association


I'm a noob to Rails and have been working on this for 3-4 days. I've created a many-to-many :through association, but when I submit a new object, I get this error:

#<ActiveModel::Errors:0x007fbced7cda88 @base=#<BlogPost id: nil, created_at: nil, updated_at: nil, title: "title 13", content: "pajfposjpfej 13", posted_by: "poster 13", comments: nil, blog_pic: nil>, @messages={:"categorizations.blog_post"=>["must exist"], :title=>[], :posted_by=>[], :content=>[], :blog_pic=>[]}, @details={"categorizations.blog_post"=>[{:error=>:blank}]}>

My form submission I'm submitting I'm selecting a category so it shouldn't be empty as the error indicates. Really appreciate any help with this. Demoralized for days now.

models:

class BlogPost < ApplicationRecord
    has_many :categorizations
    has_many :categories, :through => :categorizations
    accepts_nested_attributes_for :categorizations
    has_many :comments
    mount_uploader :blog_pic, BlogPicUploader
end

class Categorization < ApplicationRecord
    belongs_to :blog_post
    belongs_to :category
end

class Category < ApplicationRecord
    has_many :categorizations
    has_many :blog_posts, :through => :categorizations 
end

views/blog_posts/new.html.erb

<%= form_for @blog_post do |b| %>
            <%= b.label :title %>
            <%= b.text_field :title %><br>

            <%= b.fields_for :categorizations do |cat| %>
              <%= cat.label :category_name, "Category 1" %>
              <%= cat.collection_select(:category_id, Category.all, :id, :category_name, include_blank: "Select Category") %><br>
            <% end %>

            <%= b.submit "Submit", class: "btn btn-primary" %>
      <% end %> 

controller:

class BlogPostsController < ApplicationController

    def index
      @blog_posts = BlogPost.order(id: :desc)
    end

    def new
      @blog_post = BlogPost.new
      @categorizations = @blog_post.categorizations.build
      @categories = @blog_post.categories.build
    end


...

    def create
      @blog_post = BlogPost.new(blog_post_params)
      respond_to do |format|
          if @blog_post.save
            format.html { redirect_to @blog_post, notice: 'Your blog was submitted successfully' }
            format.json { render :show, status: :created, location: @blog_post }
          else
            format.html { render :new }
            format.json { render json: @blog_post.errors, status: :unprocessable_entity }
          end
        end
        puts @blog_post.errors.inspect
    end

private

  def blog_post_params
    params.require(:blog_post).permit(:title, :content, :posted_by, :comments, :blog_pic, {categorizations_attributes: [:category_id, :category_name]})
  end

end

Solution

  • The answer here had nothing to do with the code - simply put - in Rails 5, they've made a change that now requires belongs_to association by default, where as in Rails 4, this was optional. See link below that explains:

    http://blog.bigbinary.com/2016/02/15/rails-5-makes-belong-to-association-required-by-default.html

    You have to change this line in config/initializers/new_framework_defaults from true to false:

    Rails.application.config.active_record.belongs_to_required_by_default = false