3

I'm trying to create a join table called :books_users where a column in books, :claim, is a boolean, where if a person clicks the link to "review this book", the claim action in the books controller does this:

def claim
    book = Book.find(params[:id])
    book.claims << current_user unless book.claims.include?(current_user)
    redirect_to current_user
    flash[:notice] = "You have a new book to review!"
  end

The purpose of this is for my users who are signed up as reviewers can go onto book show pages, and if they decide to review a book uploaded by an author which the reviewer finds through the genres? Then they essentially indicate they're gonna review that book, which their reveiew will eventually show up on amazon as a verified purchased review, not a cheesy text review on the site on the books show page (this will make the author who signs up for the review service very happy).

My models look like this:

book.rb 

class Book < ApplicationRecord
  mount_uploader :avatar, AvatarUploader
  belongs_to :user
  has_and_belongs_to_many :genres
  has_and_belongs_to_many :claims, join_table: :books_users, association_foreign_key: :user_id

end

user.rb

class User < ApplicationRecord
mount_uploader :avatar, AvatarUploader

  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
  has_many :books
  enum access_level: [:author, :reviewer]

  has_and_belongs_to_many :claims, join_table: :books_users, association_foreign_key: :book_id
end

When the reviewer clicks on the link to review the book I get a NameError in BooksController#claim

uninitialized constant Book::Claim

I have tried to specify in the hmbtm relationships in the model after the foreign_key_association is named, I do a class_name: ClassName, thinking that might take care of the error, but I get a new one saying A class was passed to :class_name but we are expecting a string.

I'm really confused and need someone to explain this to me. Thanks!

dmberko11
  • 427
  • 7
  • 17

1 Answers1

6

The error says you should pass string as class_name argument or you can use undocumented class option:

class Foo < AR
  has_many :bars, class_name: to_s 
  # to_s returns the class name as string the same as Bar.class.to_s
end

or:

class Foo < AR
  has_many :bars, class: Baz # returns the class
end
Roman Kiselenko
  • 43,210
  • 9
  • 91
  • 103
  • Thanks! Appreciate the quick answer. Glad it was an easy fix like that and no further errors. – dmberko11 Oct 01 '18 at 05:35
  • 2
    And a quick note that `class` isn't working anymore as of Rails 6.0.0. `Unable to load application: ArgumentError: Unknown key: :class. Valid keys are: :class_name, :anonymous_class, :foreign_key, :validate, :autosave, :table_name, :before_add, :after_add, :before_remove, :after_remove, :extend, :primary_key, :dependent, :as, :through, :source, :source_type, :inverse_of, :counter_cache, :join_table, :foreign_type, :index_errors` – wangguoqin1001 Sep 02 '19 at 13:08
  • 2
    Here is the pull request that deprecated taking a constantized class: https://github.com/rails/rails/pull/27551. For readability purposes, I would suggest using `class_name: Baz.name` to return the stringified version of `Baz`. – chemturion Dec 11 '19 at 20:50