简体   繁体   中英

Create join table record automatically, rails 3

Right now my Posts model has_many :tags, :through => :tag_joins

When I add tags, while creating a post, the tag_join records are automatically created.

Now here is what I'm trying to accomplish: While viewing the show view of posts I want to be able to add a new tag.

I tried @post.tag = Tag.new didn't work (returns a "nomethoderror" for tag=)

So I'm trying to figure out how I can add tags and still create those joins automatically.

I am using accepts_nested_attributes etc.

UPDATE: I originally asked how to do this on the index view, but I have changed it to the show view - because I expect it to be a little easier.

You're not too far off with @posts.tags = Tag.new . Here's a couple of ways to do it;

@post.tags << Tag.create(params[:tag])
@post.tags.create params[:tag]

I see a couple of approaches to this problem.. One is to pass through the id of the post with the tag form using either a hidden_field or by using nested routes for tags. Then you can use that in the controller to retrieve the post and use a syntax similar to above.

While that would work, the problem is that it's a bit ugly.. It means your tag controller would be dealing with finding a post (which isn't necessarily wrong, but it shouldn't need to worry about posts. Unless tags can only be associated with posts, that is).

The more graceful way of dealing with it would be to make the form you're showing be a form for the post instance, not a tag. Then you could use nested attributes to create the tag as part of a post.

The key observation here is the difference between .new and .create. For my Devour.space application, I was running into the same issue. If you create the object in memory using:

tag = @post.tags.new(tag_params)
tag.save

There will be no tag_joins entry saved to the database. @post.tags will not return your new tag. You must use .create at the moment of instantiation or the association will not be recorded in the JOIN table:

tag = @post.tags.create(tag_params)
@post.tags.last # tag

In my situation, this required a change in how my create action handled requests and errors:

has_many :deck_shares
has_many :decks, through: :deck_shares
....

deck = current_user.decks.new(deck_params)
if deck.save # Does not create entry in DeckShares table
  render json: deck
else
  render json: deck.errors, as: :unprocessable_entity
end

This became:

begin
  deck = current_user.decks.create(deck_params) # creates DeckShare
rescue Exception => e
  render json: e, as: :unprocessable_entity
end
render json: deck unless e

Take a look at the build_xxx or create_xxx methods that the association (belongs_to, has_many etc) add to the models . You need to create your tag through the post for rails to 'connect' it automatically.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM