使用关联模型的参数创建Rails模型?

时间:2012-11-24 00:14:46

标签: ruby-on-rails ruby model routing associations

我有两个模型,UserPushupReminder,以及我的PushupReminder控制器中的方法create_a_reminder(这是放置它的最佳位置吗?)我想创建一个当我向其传递用户ID时,给定用户的PushupReminder的新实例。我通过user_id列在我的PushupReminder表格中正常工作,我测试了我可以创建提醒和放大器通过Rails控制台正确发送提醒电子邮件。

以下是型号代码的片段:

class User < ActiveRecord::Base
    has_many :pushup_reminders
end

class PushupReminder < ActiveRecord::Base
    belongs_to :user
end

create_a_reminder方法:

def create_a_reminder(user)
    @user = User.find(user)

    @reminder = PushupReminder.create(:user_id => @user.id, :completed => false, :num_pushups => @user.pushups_per_reminder, :when_sent => Time.now)

    PushupReminderMailer.reminder_email(@user).deliver
end

我对如何在我的代码中为给定用户运行create_a_reminder方法感到茫然(最终将在我所有用户的cron作业中)。如果有人可以帮助我在正确的轨道上思考,我真的很感激。

谢谢!

2 个答案:

答案 0 :(得分:3)

编辑I've posted a sample Rails app here在我的回答中展示了我正在谈论的内容。我还发布了一个new commit, complete with comments,演示了如何在非嵌套方式提供 时处理俯卧撑提醒。

保罗在正确的轨道上肯定是这样。您将在两个地方想要这个创建功能,如果您想将其作为一个cron作业运行,第二个很重要。

  1. PushupRemindersController中,作为User的嵌套资源;为了通过网络创建俯卧撑提醒。
  2. 在rake任务中,它将作为一个cron作业运行。
  3. Rails已经为您提供了所需的大部分代码,而且大多数代码都已经在ActiveRecord关联中设置了。对于#1,在routes.rb中,设置nested routes ...

    # Creates routes like...
    #   /users/<user_id>/pushup_reminders
    #   /users/<user_id>/pushup_reminders/new
    #   /users/<user_id>/pushup_reminders/<id>
    resources :users do
      resources :pushup_reminders
    end
    

    你的PushupRemindersController应该看起来像......

    class PushupRemindersController < ApplicationController
      before_filter :get_user
    
      # Most of this you'll already have.
    
      def index
        @pushup_reminders = @user.pushup_reminders
        respond_with @pushup_reminders
      end
    
      # This is the important one.
      def create
        attrs = {
          :completed => false,
          :num_pushups => @user.pushups_per_reminder,
          :when_sent => Time.now
        }
        @pushup_reminder = @user.pushup_reminders.create(attrs)
        respond_with @pushup_reminder
      end
    
      # This will handle getting the user from the params, thanks to the `before_filter`.
      def get_user
        @user = User.find(params[:user_id])
      end
    end
    

    当然,您将有一个new操作,可以向用户提供Web表单等。

    对于第二个用例cron任务,请在项目的lib/tasks目录中设置as a Rake task。这使您可以通过cron任务自由设置在需要时设置的动作。您可以完全访问所有Rails模型等,就像控制器操作一样。真正的诀窍是:如果您有用于设置提醒的疯狂自定义逻辑,请将其移至PushupReminder模型中的操作。这样你可以从rake任务中激活一个创建方法,从控制器中激活一个创建方法,你不必重复编写任何创建逻辑。请记住,不要重复自己(干)!

    我发现在设置cron任务时非常有用的一个宝石是whenever gem。在Ruby中编写特定于站点的cron作业,并获得您需要粘贴到cron选项卡的确切输出(如果您通过Capistrano部署,则需要对cron作业进行全面的免提管理)!

答案 1 :(得分:1)

尝试将attr_accessible设置为:user而不是:user_id。

attr_accessible :user

然而,更好的方法是做

@user.pushup_reminders.create

这样就会自动分配user_id。

使用这样的嵌套路线:

:resources :users do
  :resources :pushup_reminders
end

这会给你参数[:user_id]&amp; params [:id]所以你可以在db中找到你的对象。

如果您通过会话了解您的用户,则无需嵌套您的路线,而是可以使用它来保存路线。

使用restful路由,我建议在pushup_reminders控制器中使用create action。这将是进行此类对象创建的最常规和最安静的方式。

def create
  @user = User.find(params[:user_id]
  @reminder  = @user.pushup_reminders.create()
end

如果您需要检查对象创建是否成功,请尝试使用.new.save