我有一个名为Entry的模型,它有很多类别。我创建/编辑条目的页面包含每个类别的复选框。
当我编辑条目时,一切正常。当我创建Entry时,我得到@entry的错误:
:entry_categories=>["is invalid"]
我的想法是,rails无法创建entry_categories,因为它不知道条目的ID(它不应该,它还没有被分配id)
我觉得这是一件很常见的尝试。虽然我还没有找到答案。这里有代码垃圾邮件,必须有一些我缺少的东西,希望一些更有经验的眼睛能看到它。
entry.rb
class Entry < ActiveRecord::Base
validates_presence_of :contents
validates_presence_of :title
has_many :entry_categories, dependent: :destroy
has_many :categories, through: :entry_categories
belongs_to :book
validates_presence_of :book
end
entry_category.rb
class EntryCategory < ActiveRecord::Base
belongs_to :entry
belongs_to :category
validates_presence_of :entry
validates_presence_of :category
end
category.rb
class Category < ActiveRecord::Base
validates_presence_of :name
validates_uniqueness_of :name
has_many :entry_categories, dependent: :destroy
has_many :entries, through: :entry_categories
end
entries_controller.rb
class EntriesController < ApplicationController
before_action :find_entry, only: [ :show, :edit, :update, :destroy ]
before_action :find_book, only: [ :new, :create, :index ]
before_action :authenticate_admin!, only: [:new, :create, :edit, :update, :destroy ]
def new
@entry = Entry.new
end
def create
@entry = @book.entries.new( entry_params )
if @entry.save
redirect_to entry_path( @entry ), notice: 'Entry Created'
else
render :new
end
end
def show
@categories = Category.joins( :entry_categories ).where( "entry_categories.entry_id = #{@entry.id} " ).select( "name, categories.id " )
@category_class = @categories.first.name.downcase.gsub( / /, '_' ) if @categories.any?
end
def index
@entries = @book ? @book.entries : Entry.all
end
def edit
end
def update
if @entry.update( entry_params )
redirect_to entry_path( @entry ), notice: 'Entry Updated'
else
render :edit
end
end
def destroy
@book = @entry.book
@entry.destroy
redirect_to book_path( @book ) , notice: 'Entry Destroyed'
end
protected
def entry_params
params.require(:entry).permit( :title, :contents, :year, :month, :day, category_ids: [] )
end
def find_entry
@entry = Entry.find( params[:id] )
end
def find_book
@book = Book.find( params[ :book_id ] )
rescue
@book = nil
end
end
_form.html.erb
<%= form_for [ @book, @entry ] do | form | %>
<%= content_tag :p, title %>
<%= form.text_field :title, placeholder: 'Title', required: true %>
<%= form.number_field :year, placeholder: 'Year' %>
<%= form.number_field :month, placeholder: 'Month' %>
<%= form.number_field :day, placeholder: 'Day' %>
<%= form.text_area :contents %>
<fieldset>
<legend>Categories</legend>
<%= form.collection_check_boxes(:category_ids, Category.all, :id, :name ) %>
</fieldset>
<%= form.submit %>
<% end %>
再次,entry_categories在create方法中无效,在更新中它们没问题。它是相同的html文件。
在尝试保存EntryCategory之前,必须有某种方法告诉rails保存Entry吗?
感谢。
答案 0 :(得分:1)
我设法通过从EntryCategory中获取验证来实现这一点:
class EntryCategory < ActiveRecord::Base
belongs_to :entry
belongs_to :category
validates_presence_of :category
end
我对这个解决方案并不是特别高兴,并且仍然会欣赏其他想法。
答案 1 :(得分:0)
试试这个:
替换此代码:
<%= form.collection_check_boxes(:category_ids, Category.all, :id, :name ) %>
使用:
<% Category.all.order(name: :asc).each do |category| %>
<div>
<%= check_box_tag "entry[category_ids][]", category.id %>
<%= category.name %>
</div>
您可以使用fieldset
代替div
答案 2 :(得分:0)
我认为您可以使用以下任何一种方法:
您可以使用Active Record关联的autosave功能。这样,当您保存EntryCategory
时,它也会自动保存Entry
。
class EntryCategory < ActiveRecord::Base
belongs_to :entry , autosave: true
#rest of the code
end
您还可以使用活跃记录的before_save回调。这样,无论何时保存EntryCategory
,它都会先调用指定的方法,而不是继续保存。
class EntryCategory < ActiveRecord::Base
before_save :save_associated_entries
#rest of the code
def save_associated_entries
# code to save associated entries here
end
end