【问题标题】:Rails 4 has_many :through association: use Devise current_user in other parent model after_create callbackRails 4 has_many:通过关联:在其他父模型 after_create 回调中使用设计 current_user
【发布时间】:2015-08-28 14:44:18
【问题描述】:

我有三个模型,具有has_many :through 关联:

class User < ActiveRecord::Base
  has_many :administrations
  has_many :calendars, through: :administrations
end

class Calendar < ActiveRecord::Base
  has_many :administrations
  has_many :users, through: :administrations
end

class Administration < ActiveRecord::Base
  belongs_to :user
  belongs_to :calendar
end

joinAdministration 模型具有以下属性:

id
user_id
calendar_id
role

这是我目前的路线:

devise_for :users, :path => 'account'

resources :users do
  resources :calendars
end

更新

这里是Calendars#create 代码:

def create
    @user = current_user
    @calendar = @user.calendars.create(calendar_params)
    respond_to do |format|
      if @calendar.save
        format.html { redirect_to user_calendar_path(@user,@calendar), notice: 'Calendar was successfully created.' }
        format.json { render :show, status: :created, location: @calendar }
      else
        format.html { render :new }
        format.json { render json: @calendar.errors, status: :unprocessable_entity }
      end
    end
  end

每当user 创建一个新的calendar 时,我想将这个特定的user 分配给“所有者”的role — 在administration 连接模型中。

我认为最好的方法是在calendar 模型中使用after_create 回调,如下所示:

class Calendar < ActiveRecord::Base
  has_many :administrations, dependent: :destroy
  has_many :users, through: :administrations

  after_create :set_default_role

  protected

  def set_default_role
    current_user.calendar.role = "Owner"
  end

end

但是,当我继续尝试创建新日历时,出现以下错误:

NameError in CalendarsController#create
undefined local variable or method `current_user' for #<Calendar:0x007f88f8f26998>

Extracted source (around line #10):

  def set_default_role
    current_user.calendar.role = "Owner"
  end

end

经过一番研究,我发现this question on Quora的答案如下:

模型直接了解 当前用户;这是与应用程序“状态”或会话相关的 问题。控制器应该管理当前用户。

我不得不说我有些困惑:一般原则是通过将逻辑放在模型中来保持控制器的精简。但是,上面的答案建议做相反的事情,因为模型不应该知道当前用户。

那么,回到我最初的问题:如何在用户创建新日历时为他定义默认角色?

我应该使用after_create 回调,使用其他东西而不是current_user 来获取他的id,还是使用完全不同的解决方案?

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-4 devise callback has-many-through


    【解决方案1】:

    更新: 该模型没有 current_user。从日历模型中删除 set_default_role 并添加到管理模型中:

    class Calendar < ActiveRecord::Base
      has_many :administrations, dependent: :destroy
      has_many :users, through: :administrations
    end
    
    class Administration < ActiveRecord::Base
      belongs_to :user
      belongs_to :calendar
    
      before_create :set_default_role
    
      def set_default_role
        self.role = "Owner"
      end
    end
    

    【讨论】:

    • 感谢您的回复。我了解您在日历模型中推荐的更改。但是,我不确定我是否得到了日历控制器中的部分。我用日历控制器中的代码更新了我的问题。
    • 我应该只使用您在Calendar 模型中推荐的代码。
    • 当我在日历模型中添加after_create :set_default_role protected def set_default_role self.role = "Owner" end end 并尝试创建新日历时,我收到以下错误:NoMethodError in CalendarsController#create undefined method 'role=' for #&lt;Calendar:0x007f88fc8a9e40&gt;
    • 日历表中有“角色”字段吗?
    • 并将“after_create”更改为“before_create”
    【解决方案2】:

    将此添加到 CalendarsController 创建操作:

    @calendar.administrations.first.role = 'Owner'
    

    我认为它会起作用。

    【讨论】:

    • 谢谢。我理解你的代码,除了first 部分。请问你为什么推荐这个?
    • 我试过你的代码。日历已创建。但是,当我在控制台中签入时,角色仍然设置为nil。知道这里有什么问题吗?
    • 您在日历模型中有 :has_many 关联,因此 @calendar.administratins 将返回一个管理数组。在创建时将有 1 个元素。所以 .first 会返回那个。
    • 谢谢。同意。但是当我尝试这段代码时,不幸的是它没有工作,因为控制台中的角色仍然为零。知道如何进行这项工作吗?
    • 首次创建日历时尝试使用 .build 而不是 .create。
    【解决方案3】:

    这就是我最终要做的。

    首先,在User模型中,我定义了如下方法:

    def set_default_role(calendar_id, role)
      self.administrations.find_by(calendar_id: calendar_id).update(role: role)
    end
    

    然后,我更新Calendars#Create如下:

    def create
      @user = current_user
      @calendar = @user.calendars.create(calendar_params)
      respond_to do |format|
        if @calendar.save
          current_user.set_default_role(@calendar.id, 'Owner')
          format.html { redirect_to user_calendar_path(@user,@calendar), notice: 'Calendar was successfully created.' }
          format.json { render :show, status: :created, location: @calendar }
        else
          format.html { render :new }
          format.json { render json: @calendar.errors, status: :unprocessable_entity }
        end
      end
    end
    

    现在,每当user 创建一个新的calendar 时,如果保存了新的calendar,那么current_user 默认分配给所有者的role

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-12
      • 1970-01-01
      • 1970-01-01
      • 2013-05-06
      相关资源
      最近更新 更多