1
  • ユーザーとして、お気に入りの本をブック リストに追加できます。
  • 別のユーザーが同じ本をブック リストに追加します。
  • データベースには書籍のインスタンスが 1 つしかないはずですが、ユーザーと書籍の関連付けは 2 つ必要です。

    class User
      has_many :bookReferences
      has_many :books, through: :bookReferences
    
    class Book
      validates_uniqueness_of :title
      has_many :bookReferences
      has_many :users, through: :bookReferences
    
    class BookReference
      belongs_to :user
      belongs_to :book
    

最初の問題は、書籍が既にシステムに存在する場合、書籍が一意ではないため、2 番目のユーザーの bookReference が作成されないことです。

そのため、書籍が既にシステムに存在する場合は、bookReference テーブルに関連付けレコードを作成するだけです。

2 番目の問題は、ユーザーが本を削除したときに、その本を参照している唯一のユーザーでない限り、本への参照のみを削除することです。

基本的に、これは私が達成しようとしている使用法の完全な概要です。

    user1.books.first
      => id: 1, title: "Moby Dick"
    user2.books.first
      => id: 1, title: "Moby Dick"
    books.all
      => id: 1, title: "Moby Dick"


    user1.books.first.destroy
    user1.books.first
      => nil
    books.all
      => id: 1, title: "Moby Dick"
    user2.books.first
      => id: 1, title: "Moby Dick"
    user2.books.first.destroy
      => nil
    books.all
      => nil

アップデート

これらの回答に基づいて、おそらく私はあまり明確ではありませんでした. もう一度試してみましょう... book コントローラーには、次の基本的な CRUD create メソッドがあります。

    def create
      current_user.books.create(name: params[:book][:title])

has_many による関連付けが現在設定されている方法では、ブックが一意である場合にのみ作成されます。すでにシステムにある場合は、false を返します。私がやりたいことは、あたかも新しいレコードであるかのように、既存の本との関連付けを作成することです。これは、これを達成するためにアプリケーションで現在行っていることですが、間違っていると感じています。

   def create
     book = Book.where(name: params[:book][:title]).first_or_create!
     BookReference.where(book_id: book.id, user_id: current_user.id).first_or_create!

2 つ目の問題は、ユーザーが自分のアカウントから書籍を削除した場合です。従来の CRUD destroy を実行すると、すべてのアカウントから削除されます。

    def destroy
      book = current_user.books.find(params[:id])
      book.destroy

これを回避するために、私は現在次のことを行っています。繰り返しますが、これは「正しい」とは感じません。

    def destroy
      book = current_user.books.find(params[:id])
      # if book was unique to user
      if BookReference.where(book_id: book.id).count == 1
        # remove book from system
        book.destroy  
      else
        # remove book reference but not book
        current_user.books.delete(book)
      end
end  
4

2 に答える 2

0

私はまだRailsにも少し慣れていませんが、これが私が思いついたものです。

book = user1.books.first
if book.users.size > 1 
  user1.books.first.destroy
else
  book.destroy 
end
# in order to delete the book's dependency, you will need
class Book
has_many :bookReferences, :dependent => :destroy

お役に立てれば。

注:のような名前のモデルがある場合は、BookReferenceモデルを次のように参照し:book_reference ます。この場合、次のように変更する必要があります。

class User
  has_many :book_references
  has_many :books, through: :book_references

class Book
  validates_uniqueness_of :title
  has_many :book_references
  has_many :users, through: :book_references

class BookReference
  belongs_to :user
  belongs_to :book

アップデート:

データベースに存在しないときに新しい本を作成したいので、利用できる1つのrailsメソッドはですBook.find_or_create()。詳細については説明しませんが、後でオートコンプリート機能を使用して本を検索したいと思います。オートコンプリートでこのレールキャストをご覧ください。Ryan Batesは、オートコンプリートを設定し、見つからない場合は新しいエントリを作成するという素晴らしい仕事をしました。これがあなたが探しているものです。

さらに、ユーザーが複数の本を追加できるようにするためのより簡単な方法が必要な場合は、トークンフィールドについて説明する別のレールキャストがあります

于 2012-12-31T03:09:39.483 に答える
0

関連付けを介して has_many を使用すると、Rails は自動的に bookreference を作成します。

ユーザーモデルに :book_ids という「隠し列」を作成します。

したがって、使用するユーザーに本を「保存」するフォームで

<%= form_for (@user) do |f| %>
.
.
.
<%= f.label :book_ids %>
<%= f.select :book_ids, Book.all.collect {|x| [x.name, x.id]}, {}, :multiple => true %>

ブックリファレンスは自動的に入力され、ビューに表示できます。編集と破棄も自動的に行われます。削除または編集すると、bookreference テーブルのみになります。

協会についてもっと知りたい場合は、

http://api.rubyonrails.org/

ActiveRecord::Associations を検索します

于 2012-12-31T19:43:15.737 に答える