如何在rails中的发布页面之间安排和触发延迟?

时间:2017-12-06 10:56:14

标签: ruby-on-rails ajax

我目前正在开发一个食谱Web应用程序,每个用户都可以喜欢一个食谱。配方由几个步骤组成。

当用户喜欢食谱时,他应该接收食谱的第一步。他可以看到它出现在steps / index.html.erb页面上。接下来还没有看到。 然后,当他打开它时,(recipes /:recipe_id / steps / 1 / show.html.erb),它显示第一步,并在同一时间触发时间间隔(可配置),然后显示第二步步骤,依此类推,直到配方的最后一步。

步骤的等待和幻影必须发生一次。加载步骤时,它始终显示在列表中而不等待。 为了安排这个,有人解释我使用ajax请求。但是我没有很好地描述我的问题,并且正在努力,我遇到了困难......现在我怀疑所有人的结构并感到有些失落!

如果您有任何想法, 事先非常感谢;)

这是我的代码:

模特:

class Recipe < ApplicationRecord
belongs_to :user
has_many :steps
has_many :favorites
has_many :favorited_by_users, :through => :favorites, :source => 'user'

class Step < ApplicationRecord
belongs_to :recipe
end

class Favorite < ApplicationRecord
belongs_to :recipe
belongs_to :user
end

class User < ApplicationRecord
has_many :recipes
has_many :favorites
has_many :favorite_recipes, :through => :favorites, :source => 'recipe’

devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable
end

在我的步骤控制器中,我有:

  def index
  @recipe = Recipe.find(params[:recipe_id]) 
  @steps = @recipe.steps
  end

谢谢!

1 个答案:

答案 0 :(得分:0)

您需要一个存储数据的位置,以确定用户是否已阅读某个步骤。因此,我们将添加一个新的&#34; join-table&#34;在UserStep模型之间。

bash / terminal:

rails generate model steps_user step:belongs_to user:belongs_to is_read:boolean

推荐:更改为上面生成的迁移文件,使default: false, null: false

is_read

应用/配置/ routes.rb中

resources :steps do
  resources :steps_users, only: [] do
    put :create_or_update, on: :collection, as: 'create_or_update_steps_user'
  end
end

应用/控制器/ steps_users_controller.rb

class StepsUsersController < ApplicationController
  def create_or_update
    @step = Step.find(params[:step_id])
    @steps_user = @step.steps_users.find_or_initialize_by(user: current_user)

    # you can further refactor this to use `save()` and not `save!()`
    # but for simplicity, I'll just use this to raise exception when there is a validation error
    if @steps_user.save!(steps_user_params)
      render status: :ok
    end
  end

  private 

  def steps_user_params
    params.require(:steps_user).permit(:is_read)
  end
end

应用/模型/ step.rb

class Step < ApplicationRecord
  has_many :steps_users

  def previous_step
    # you might want to update this as I do not know if you have your own Step attribute that determines the "order" of the Steps
    recipe.steps.order(id: :desc).where('id < ?', id).first
  end
  # ...

应用/控制器/ steps_controller.rb:

class StepsController < ApplicationController
  def show
    @step = Step.find(params[:id])

    # add some authorization here to prevent anyone from reading this step unless they have already read the previous steps (example code is below)
    # if @step.previous_step && !@step.previous_step.is_read?
    #   render status: :forbidden
    # end
  end
  # ...

应用/视图/步骤/ show.html.erb:

<script type='text/javasript'>
  $(function() {
    var delay = 30000; // 30 seconds

    var updateStepsUserAsRead = function() {
      $.ajax({
        type: 'POST',
        url: '<%= j create_or_update_steps_user_path(step_id: @step.id) %>',
        contentType: 'application/json; charset=utf-8',
        headers: {
          'X-CSRF-Token': Rails.csrfToken()
        },
        data: {
          _method: 'put',
          steps_user: {
            is_read: true
          }
        }
      })
    }

    setTimeout(updateStepsUserAsRead, delay);
  })
</script>

...
  

以上JS脚本会将is_read标记为true以获取current_user的steps_user记录

应用/视图/步/ index.html.erb

<% @steps.each do |step| %>
  <% if !step.previous_step || (step.previous_step && step.previous_step.is_read?) %>
    <%= link_to 'Step #', step # <<<<< update this %> 
  <% end %>
<% end %>