我有一个简单的应用程序,用户可以在其中创建projects
和timetrackers
,belong_to
和projects
基本上是时间戳。 timetrackers
有一个start_time
和一个end_time
(两者均为:datetime),现在我想计算两个值之间的持续时间并将其保存到{float中的timespan
中。
为此,我在set_timespan
中有一个timetrackers_controller
动作
def set_timespan
@job = Job.find(params[:job_id])
@timetracker = Timetracker.find(params[:id])
@timetracker.timespan = (@timetracker.end_time - @timetracker.start_time).round / 3600
end
创建动作
def create
@job = Job.find(params[:job_id])
@timetrackers = @job.timetrackers.new(timetracker_params)
@timetrackers.user_id = current_user.id
@timetrackers.job_id = @job.id
#set_timespan
respond_to do |format|
if @timetrackers.save
format.html { redirect_to @job, notice: 'Timestamps created successfully.' }
format.json { render :show, status: :created, location: @job }
else
format.html { redirect_to new_timetracker_path, notice: "Please fill out the form." }
format.json { render json: @job.errors, status: :unprocessable_entity }
end
end
end
当我尝试在create
之前的@timetrackers.save
动作中拍摄动作时,出现Couldn't find Timetracker without an ID
错误。我也被重定向到jobs/3/timetrackers
。为什么找不到ID?如何正确触发控制器中的操作来计算时间跨度?以后我想总结一下时间跨度。
答案 0 :(得分:1)
作为一个简单的解决方案,您仍然可以访问@timetrackers
实例变量:
def set_timespan
@job = Job.find(params[:job_id])
@timetrackers.timespan = (@timetracker.end_time - @timetracker.start_time).round / 3600
end
我将更进一步,并完全删除该方法,因为@job
也可用,并且只需在create动作中直接使用相关行即可:
def create
# ...
@timetrackers.job_id = @job.id
# v here v
@timetrackers.timespan = (@timetrackers.end_time - @timetrackers.start_time).round / 3600
respond_to do |format|
# ...
end
作为最终的,也许是理想的解决方案,您可以在Timespan
模型中使用before_create
回调:
# timespan.rb
before_create -> { self.timespan = (end_time - start_time).round / 3600 }
这样,您的timespan
将在创建时自动设置。
答案 1 :(得分:0)
我意识到您已经有了一个喜欢的答案,但是...
另一种方法是修饰timetracker_params
,以便使用诸如new_timetracker_attributes
之类的方法包含所有适当的数据。也许是这样的:
def create
@job = Job.find(params[:job_id])
@timetrackers = @job.timetrackers.new(new_timetracker_attributes)
respond_to do |format|
if @timetrackers.save
format.html { redirect_to @job, notice: 'Timestamps created successfully.' }
format.json { render :show, status: :created, location: @job }
else
format.html { redirect_to new_timetracker_path, notice: "Please fill out the form." }
format.json { render json: @job.errors, status: :unprocessable_entity }
end
end
end
private
def new_timetracker_attributes
timetracker_params.merge(
user_id: current_user.id,
timespan: ((end_time-start_time).round/3600)
)
end
def timetracker_params
params.require(:timetracker).permit(:start_time, :end_time)
end
def start_time
timetracker_params[:start_time]
end
def end_time
timetracker_params[:end_time]
end
您可以通过多种方法来修饰timetracker_params
,这只是一个主意。
重点是,您已将新实例属性的 all 全部设置在一个地方进行,而不是在应用程序的各个位置涂抹。 IMO,这使了解情况和调试是否呈梨形变得容易了一点。