Rails:find_or_create关系

时间:2015-10-20 12:38:23

标签: ruby-on-rails ruby ruby-on-rails-4 relational-database

如果我为锻炼创建一个新锻炼,我的字段member_id为空。

workout.rb

     belongs_to :member
     has_and_belongs_to_many :exercises

     def add_exercise_with_name(exercise_name)
        self.exercises << Exercise.find_or_create_by(name: exercise_name)
      end

exercise.erb

has_and_belongs_to_many :workouts
belongs_to :member

exercise_controller.erb

def create
    @workout = current_user.workouts.find(params[:workout_id])
    @exercise = @workout.add_exercise_with_name(exercises_params['name'])
    redirect_to workout_path(@workout)
end

我如何添加锻炼成员?

3 个答案:

答案 0 :(得分:3)

将id作为额外参数传递给方法。

def add_exercise_with_name(exercise_name, member_id)
  self.exercises << Exercise.find_or_create_by(name: exercise_name, member_id: member_id)
end

这有副作用。现在find_or_create调用会在查找练习时考虑member_id。如果不希望这样,请使用create_with(member_id: member_id)

self.exercises << Exercise.create_with(member_id: member_id).find_or_create_by(name: exercise_name)

此外,您可以使用块语法:

  self.exercises << Exercise.find_or_create_by(name: exercise_name) do |exercise|
    exercise.member_id = member_id
  end

答案 1 :(得分:1)

Workout型号上试试这个:

def add_exercise_with_name(exercise_name, member)
  self.exercises << Exercise.find_or_create_by(name: exercise_name, member: member)
end

然后传入控制器中的成员:

member = Member.find_by whatever_column: 'value'
@exercise = @workout.add_exercise_with_name(exercises_params['name'], member)

答案 2 :(得分:0)

如果您关注关联,则会自动填充外键。 在控制器中,您还可以通过关联使用ActiveRecord请求:

class Member < ActiveRecord::Base
  has_many :workouts
  has_many :exercises, through: :workouts
end


class Workout < ActiveRecord::Base
  belongs_to :member
  has_and_belongs_to_many :exercises
end


class Exercise < ActiveRecord::Base
  belongs_to :member
  has_and_belongs_to_many :workouts
end


class ExercisesController < ActionController::Base
  before_action :get_workout

  def create
    @workout.exercises.where(name: exercises_params['name']).first_or_create
    redirect_to workout_path(@workout)
  end

  private

  def get_workout
    @workout = current_user.workouts.find(params[:workout_id])
  end
end