Search code examples
ruby-on-railsrubyruby-on-rails-4activerecordstrong-parameters

Issue with join table and has_many through association in Rails 4


Guys this is my DB structure. AccountGrade.rb MODEL its a join table for account & grade models

class AccountGrade < ActiveRecord::Base
  belongs_to :account
  belongs_to :grade
  attr_accessor :grade
  attr_accessor :section
end

My account.rb MODEL

class Account < ActiveRecord::Base
  has_many :grades, :through => :account_grades
  has_many :account_grades
  belongs_to :user
  validates :school_name,:line_1,:city,:state,:country,:pincode,:phone_number, :presence => true
  validates :pincode,:phone_number,numericality: { only_integer: true }
end

My grade.rb MODEL

class Grade < ActiveRecord::Base
  has_many :accounts, :through => :account_grades
  has_many :account_grades
  attr_accessor :account_grades
end

My grades_controller.rb

class GradesController < ApplicationController
  def index
    @grades = Grade.all
    render json: {
      Grades:@grades
    }.to_json
  end

  def add_class_sections
    # unless params[:section]
      @account_grades = AccountGrade.new class_sections_params
      puts "Grades are #{@account_grades}"

      @grades.each do |grade|
        @account_grades = grade
        puts grade
        puts @account_grades
      end
    # end #unless ends here
  end #function add_class_sections ends here


  private

    def class_sections_params
      params.permit!
      # params.require(:gardes).permit(:section)#, :email, :password, :salt, :encrypted_password)
    end

end #class ends here

I am getting the below error in my terminal trace.

Started POST "/add_classes?grade_id[0]=1&section[0]=2&grade_id[1]=2&section[1]=1&grade_id[2]=3&section[2]=1" for 127.0.0.1 at 2015-11-17 12:43:47 +0530
  ActiveRecord::SchemaMigration Load (0.1ms)  SELECT `schema_migrations`.* FROM `schema_migrations`
Processing by GradesController#add_class_sections as */*
  Parameters: {"grade_id"=>{"0"=>"1", "1"=>"2", "2"=>"3"}, "section"=>{"0"=>"2", "1"=>"1", "2"=>"1"}}
Completed 500 Internal Server Error in 10ms (ActiveRecord: 0.8ms)

ActiveRecord::UnknownAttributeError (unknown attribute 'controller' for AccountGrade.):
  app/controllers/grades_controller.rb:11:in `add_class_sections'


  Rendered /home/anjan/.rvm/gems/ruby-2.2.1/gems/actionpack-4.2.4/lib/action_dispatch/middleware/templates/rescues/_source.erb (11.0ms)
  Rendered /home/anjan/.rvm/gems/ruby-2.2.1/gems/actionpack-4.2.4/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (1.7ms)
  Rendered /home/anjan/.rvm/gems/ruby-2.2.1/gems/actionpack-4.2.4/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (0.9ms)
  Rendered /home/anjan/.rvm/gems/ruby-2.2.1/gems/actionpack-4.2.4/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout (24.8ms)

Solution

  • Wow there are a lot of problems with your code.

    Regardless of your reasoning, this is how you should get it working...


    #app/controllers/grades_controller.rb
    class GradesController < ApplicationController
        def index
          @grades = Grade.all
          respond_to do |format|
             format.json { render json: @grades.to_json }
             format.html
          end
        end
    
        def create
          @account_grades = AccountGrade.new class_sections_params
          redirect_to @account.grades if @account_grades.save
        end
    
      private
    
        def sections_params
          params.require(:grades).permit(:section)
        end
    end
    

    If you get this code to work, you'll be in a much stronger position to understand why it's looking for a controller attribute (which is a strange error).

    You should also be aware of several conventions in Rails:

    1. Don't use puts in a controller - you have Rails.logger.info() to output to your console.
    2. Keep your actions restful -- although this can - and often is - broken, the restful nature of a Rails controller should be the foremost convention to follow. Don't call add_class_section unless you really have to -- instead, you should look at using the new & create methods as required.

    --

    Also, remove all the attr_accessor references, especially the ones which conflict with any of the association names.

    attr_accessor basically declares new getter/setter methods for your model. If these methods override any of the relations, they will actually prevent them from working.

    You don't need attr_accessor unless you want to create a semi-persistent attribute (IE one which doesn't save to the db). The most common use for attr_accessor in Rails is to create virtual attributes:

    enter image description here