I've been fighting using the Rails has_many :through all week long. Initially I had issues getting the collection_select form helper to save .
I eventually got that to work, and moved to trying to get a json post request to support adding a new Author. I modeled the json after the request params created by using the now functioning form. It worked the very first time I made the request with these params:
{
"author": {
"name": "Author Name",
"post_ids": [
"1", "2"
]
}
}
I started testing my validations, and ran into an issue where if a post_id is sent that does not exist in the database Rails will bomb on the @author.new method:
Request:
{
"author": {
"name": "Author Name",
"post_ids": [
"23"
]
}
}
Error:
ActiveRecord::RecordNotFound (Couldn't find Post with 'id'=23):
app/controllers/authors_controller.rb:32:in `create'
Controller
def create
@author = Author.new(author_params)
respond_to do |format|
if @author.save
format.html { redirect_to @author, notice: 'Author was successfully created.' }
format.json { render :show, status: :created, location: @author }
else
format.html { render :new }
format.json { render json: @author.errors, status: :unprocessable_entity }
end
end
end
It is bombing on this line
@author = Author.new(author_params)
I attempted to use validations to make sure the id exists, but it's erroring before it ever makes it to validations. It seems that rails is creating the associations in the new method.
How can I catch this? I've written a check before the Author.new call to make sure the author_ids sent exist, but if rails provides this ability I'd like to be able to use the built in functionality to catch it and send it back with other validation messages instead.
Models:
class Author < ActiveRecord::Base
has_many :post_authors
has_many :posts, :through => :post_authors
accepts_nested_attributes_for :post_authors
end
class Post < ActiveRecord::Base
end
class PostAuthor < ActiveRecord::Base
belongs_to :post
belongs_to :author
end
Schema
ActiveRecord::Schema.define(version: 20150120190715) do
create_table "authors", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "post_authors", force: :cascade do |t|
t.integer "post_id"
t.integer "author_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "posts", force: :cascade do |t|
t.string "title"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
Thanks for any help.
Validation Attempt
I put the following validation below in all 3 models. I added breakpoints and the log messages. None of them hit before the error occurs, so at this point I'm getting nowhere with validations happening to even be able to make a check.
class Author < ActiveRecord::Base
has_many :post_authors
has_many :posts, :through => :post_authors
accepts_nested_attributes_for :post_authors
validate :post_exists
def post_exists
Rails.logger.debug("Validate")
end
end
According to the rails guide validations are only triggered when following methods are called:
So I reckon that your best chance would be to rescue the ActiveRecord::RecordNotFound
in your controller as it is explained in this question:
how to handle ActiveRecord::RecordNotFound in rails controller?
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.