【问题标题】:How to populate example data to my Rails application in production?如何在生产中将示例数据填充到我的 Rails 应用程序?
【发布时间】:2019-04-02 12:46:23
【问题描述】:

我有一个 n00b 问题。我正在使用 Rails 5,并希望在应用程序中有示例数据。当用户创建一个新项目时,该项目应该已经包含用户可以删除或编辑的示例“任务”。

我知道我可以使用 seed.rb 在我的开发环境中创建示例数据。在新用户的生产环境中,最好的方法是什么?如何做?我应该使用 seed.rb、迁移还是 rake 任务?

示例控制器:

  def create
    @project = Project.new(project_params)
    @project.user = current_user

    if @project.save
       // add sample content
       redirect_to @project 
    else
       render :new
    end
  end

在项目模型中:

 belongs_to :user
 has_many :tasks, dependent: :destroy

当新用户加入并创建新项目时,如何在用户创建的新项目中自动添加示例“任务”?

更新:

要创建一个任务,我需要一个描述和当前用户的id(我使用的是Devise,所以我可以使用current_user helper),例如:

@project.tasks.create!(description: "hello", user_id: current_user.id)

【问题讨论】:

  • 一种解决方案可能是创建一个服务,您将在其中放置示例项目的数据,然后在创建用户时执行此服务(使用参数中创建的用户)。用户将能够删除或编辑此示例项目。此外,当一个已经注册的用户创建一个项目时,您将能够获取示例数据并根据需要将 if 传递给他的新项目

标签: ruby-on-rails


【解决方案1】:

您可以构建一个简单的 ServiceObject 来完成这项工作。它允许你保持你的控制器瘦,你可以使用你的current_user设计助手来跟踪哪个用户正在创建项目

if @project.save 
  SetupBaseProject.new(project).call
  redirect_to @project
else 
  # handle errors
end

app/services/setup_base_project.rb

class SetupBaseProject 
  def initialize(project, user) 
    @project = project
  end

  def call
    # Create example tasks and any additional setup you want to add
    @project.tasks.create(description: 'Hello World', user: @project.user)
  end    
end 

【讨论】:

    【解决方案2】:

    考虑到您的问题,有两种可能的情况。

    1. 用户创建的第一个项目需要默认包含示例任务
    2. 无论何时创建新项目,都会默认创建示例任务。无论用户是新用户/现有用户。

    对于第一种情况, 我们需要通过向用户添加一个布尔字段来跟踪项目是否由新用户创建,例如:new_user,默认为true。 我们可以在项目创建后使用活动记录回调来生成示例任务。

    例如, 项目模型:

    belongs_to :user
    has_many :tasks, dependent: destroy
    after_create :generate_tasks
    def generate_tasks
       if self.user.new_user #This conditional block can be modified as needed
         (1..3).each do |n|
           self.tasks.create!(description: "Sample task #{n}", user_id: self.user.id)
         end
       end
    end
    

    对于第二种情况, 我们可以使用相同的项目模型文件,只需删除有助于在项目创建后创建示例任务的条件语句。

    如果您需要任何澄清,请发表评论。

    【讨论】:

    • 谢谢@dharmesh!我有一个问题,在我的任务中我还必须添加一个 user_id,但我不能在模型中使用设计 current_user 帮助器。也许 after_create 逻辑应该在控制器中?我会更新问题。
    • @userden 我现在已经清楚地理解了您的问题,这可以使用活动记录回调本身来完成。我已经更新了我的答案以实现这一目标。请验证更新的答案。如果有任何其他澄清,请告诉我。!
    • @userden,你试过了吗?如果您需要对我的回答进行任何澄清,请告诉我。
    • 是的,它有效,我喜欢它。我只是在等待并思考这样做的“最佳”或“正确”方法是什么?我也喜欢使用简单的 ServiceObject 的想法,这是文森特在他的回答中建议的。无论如何,我很快就会批准你的答案,我只是再测试一件事。
    • 谢谢@dharmesh,抱歉我花了一段时间才回来!
    【解决方案3】:

    过去我已经做过很多次了。 根据我的经验,您最终必须让其他人能够管理这些默认设置(产品所有者、营销等)

    我过去所做的是让一个测试用户使用一个充当“默认”项目的项目。

    只要有人想创建一个新项目,你就克隆它。

    我为此使用了https://github.com/amoeba-rb/amoeba。它提供了一种非常简单的方式来覆盖我想要更改的属性,并且可以将克隆级联到您想要克隆的任何关联。

    【讨论】:

      【解决方案4】:

      假设样本数据位于模型Detail 上,该模型填充了seeds.rb 并属于“项目”。您可以复制该记录并将其分配给新项目(未测试):

      def create
          @project = Project.new(project_params)
          @project.user = current_user
          @project.details << Detail.find_by_name('sample').dup
      
          if @project.save 
             redirect_to @company 
          else
             render :new
          end
        end
      

      此外,在多个模型上保存数据时,请考虑使用事务。

      【讨论】:

        【解决方案5】:

        完全披露,我在 Rails 4 工作...

        如果是我,我会使用FactoryBot 来获取您想要的虚拟数据。工厂非常适合测试,所以如果您使用它们进行测试,为什么不借用它们呢?这个post 显示了一个示例,其中有人想在控制台中模拟虚拟数据,同样的想法可以在这里适用。

        一旦你把你的工厂模型化了......也许是为了完成以下任务:

        require 'faker'
        FactoryBot.define do
          factory :task do
            transient do
              parent_project { nil }
            end
        
            description { Faker::Hacker.say_something_smart }
            project_id { parent_project.id }
          end
        end
        

        也许在项目模型中创建一个方法,例如:

        def create_dummy_data
          require 'factory_bot'
          require 'faker'
          include FactoryBot::Syntax::Methods
        
          # create_list will spit out 3 tasks associated with your project
          create_list(:task, 3, parent_project: self)
        end
        

        然后在你的例子中:在调用 save...

        if @project.save
           @project.create_dummy_data  
           redirect_to @company 
        else
        

        我想不出你不能走这条路的原因......在控制台中闲逛我没有任何问题,但我会将此答案视为起点,而不是最终解决方案=P

        【讨论】:

          猜你喜欢
          • 2017-01-13
          • 1970-01-01
          • 2011-03-12
          • 2015-05-07
          • 2021-11-17
          • 1970-01-01
          • 1970-01-01
          • 2022-10-24
          • 1970-01-01
          相关资源
          最近更新 更多