我目前正在开发一个食谱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
谢谢!
答案 0 :(得分:0)
您需要一个存储数据的位置,以确定用户是否已阅读某个步骤。因此,我们将添加一个新的&#34; join-table&#34;在User
和Step
模型之间。
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 %>