Add record to a has_and_belongs_to_many relationsh

2020-05-14 19:16发布

I have two models, users and promotions. The idea is that a promotion can have many users, and a user can have many promotions.

class User < ActiveRecord::Base
  has_and_belongs_to_many :promotions
end

class Promotion < ActiveRecord::Base
  has_and_belongs_to_many :users
end

I also have a promotions_users table/model, with no id of its own. It references user_id and promotions_id

class PromotionsUsers < ActiveRecord::Base
end

So, how do I add a user to a promotion? I've tried something like this:

user = User.find(params[:id])
promotion = Promotion.find(params[:promo_id])
promo = user.promotions.new(promo)

This results in the following error:

NoMethodError: undefined method `stringify_keys!' for #<Promotion:0x10514d420>

If I try this line instead: promo= user.promotions.new(promo.id)

I get this error:

TypeError: can't dup Fixnum

I'm sure that there is a very easy solution to my problem, and I'm just not searching for the solution the right way.

4条回答
再贱就再见
2楼-- · 2020-05-14 19:21
user = User.find(params[:id])
promotion = Promotion.find(params[:promo_id])
user.promotions << promotion

user.promotions is an array of the promotions tied to the user.

See the apidock for all the different functions you have available.

查看更多
再贱就再见
3楼-- · 2020-05-14 19:23

This is also useful

User.promotion.build(attr = {})

so, promotion object saves, when you save User object.

And this is

User.promotion.create(attr = {})

create promotion you not need to save it or User model

查看更多
ゆ 、 Hurt°
4楼-- · 2020-05-14 19:29

If you want to add a User to a Promotion using a prototypical PromotionsController CRUD setup and you're not using Rails form helpers, you can format the params as:

params = {id: 1, promotion: { id: 1, user_ids: [2] }}

This allows you to keep the controller slim, e.g., you don't have to add anything special to the update method.

class PromotionsController < ApplicationController

  def update
    promotion.update(promotion_params)

    # simplified error handling
    if promotion.errors.none?
      render json: {message: 'Success'}, status: :ok
    else
      render json: post.errors.full_messages, status: :bad_request
    end
  end

  private

  def promotions_params
    params.require(:promotion).permit!
  end

  def promotion
    @promotion ||= Promotion.find(params[:id])
  end
end

The result would be:

irb(main)> Promotion.find(1).users
=> #<ActiveRecord::Associations::CollectionProxy [#<User id: 2 ...>]>
查看更多
祖国的老花朵
5楼-- · 2020-05-14 19:41

You can do just

User.promotions = promotion #notice that this will delete any existing promotions

or

User.promotions << promotion

You can read about has_and_belongs_to_many relationship here.

查看更多
登录 后发表回答