我是RoR的初学者,甚至是网络编程。所以我想我的问题对很多开发人员来说都很容易!
我正在实施简单的周历,它应该有一天的名字和两个“按钮” - “下周”和“前一周”。这一切都是为了开始!
我有控制器的索引操作:
def index
@today = Date::today
@monday = @today.beginning_of_week
@sunday = @today.end_of_week
@currentweek = @monday..@sunday
end
以及其他两项行动:
def go_next_week
@monday = @sunday + 1
@sunday = @monday.end_of_week
end
def go_prev_week
@sunday = @monday - 1
@monday = @sunday.beginning_of_week
end
索引视图代码:
<div class="wrapper">
<table class="data">
<thead>
<tr class="month-names">
<td><%= form_tag(work_days_go_prev_week_path, method: "get") do %>
<%= submit_tag(l(("workdays_show_prev" + period).to_sym)) %>
<% end %>
</td>
<td><%= render :partial => 'days_names_header' %></td>
<td><%= form_tag(work_days_go_next_week_path, method: "get") do %>
<%= submit_tag(l(("workdays_show_next" + period).to_sym)) %>
<% end %>
</td>
</tr>
</thead>
</table>
</div>
路线档案:
RedmineApp::Application.routes.draw do
match 'work_days/go_next_week' ,:to => 'work_days#go_next_week', via: [:get]
match 'work_days/go_prev_week' ,:to => 'work_days#go_prev_week', via: [:get]
match 'work_days/(:action(/:id))',via: [:get], :controller => 'work_days'
end
短期内该阶段的主要目标是:
Controller有一个Date变量'monday','sunday'和Range 'currentweek'
索引视图显示根据变量
索引视图有2个“按钮”:“下周”和“上周”
单击此按钮可更改Controller的变量
索引视图应该使用已更改的Controller变量“刷新”
此代码无效。点击“上个月”按钮时,我在日志中出现了这样的错误:
开始GET “/ work_days / go_prev_week?tf8 =%E2%9C%93&amp; commit = Previous + week”for 127.0.0.1 at 2015-12-09 14:00:27 +0600由WorkDaysController处理#go_prev_week作为HTML参数: {“utf8”=&gt;“✓”,“commit”=&gt;“上周”}当前用户:admin(id = 1) 在3ms内完成500内部服务器错误(ActiveRecord:0.2ms)
NoMethodError(未定义的方法` - '代表nil:NilClass)
答案 0 :(得分:3)
我是RoR的初学者,甚至是网络编程。
欢迎!
您的问题是,您使用@instance_variables
填充控制器操作,这些操作相互依赖:
def go_next_week
@monday = @sunday + 1 # needs @sunday
@sunday = @monday.end_of_week # needs @monday
end
在旧式编程中,这可能会导致无法识别的参考错误或堆栈溢出错误,通常是由于无限recursion。
错误证实了这一点:
未定义的方法` - '为nil:NilClass
Ruby
与大多数其他语言的不同之处在于它将未声明的变量分配给NilClass
对象。这使得开发人员很难确定错误 - 基本上如果您收到undefined method for NilClass
,那就是您没有声明您的变量。
-
修复方法是将您尝试操作的数据导入到类的实例中。这可以通过before_action
过滤器来实现:
#app/controllers/work_days_controller.rb
class WorkDaysController < ApplicationController
before_action :set_dates
def index
#@today, @monday, @sunday will be available in here.
end
private
def set_dates
@today = Date::today
@monday = @today.beginning_of_week
@sunday = @today.end_of_week
end
end
您还可以改进路线以使用resources
指令:
#config/routes.rb
resources :work_days do
get :go_next_week, on: :collection
get :go_prev_week, on: :collection
end
答案 1 :(得分:1)
您可能应该在before_action
中初始化这些实例变量。
例如:
class MyController < ActionController
before_action :set_dates
def index
# ... Your index implementation
end
def go_next_week
@monday = @sunday + 1
@sunday = @monday.end_of_week
end
def go_prev_week
@sunday = @monday - 1
@monday = @sunday.beginning_of_week
end
private
def set_dates
@today = Date::today
@monday = @today.beginning_of_week
@sunday = @today.end_of_week
@currentweek = @monday..@sunday
end
end
通过这种方式,日期将在每个动作中初始化。不过要小心!上面的这个实现只允许进一步前进一周。要使每周工作,您必须提供param
当前周。
我希望这会有所帮助,如果您需要更多信息,欢迎您。 :)
答案 2 :(得分:1)
看起来您希望拥有相同的控制器操作和视图,但仅限于其他日期。
如果是这种情况,我建议您这样:
class MyController < ApplicationController
before_action :set_date
def index
end
private
def set_date
if params[:week].present? && params[:year].present?
@today = Date.commercial(params[:year].to_i, params[:week].to_i)
end
@today ||= Date::today # <= Just use date today if it's not set already
@monday = @today.beginning_of_week
@sunday = @monday - 1
@monday = @sunday.beginning_of_week
end
end
路线:
RedmineApp::Application.routes.draw do
get 'calendar' => 'my_controller#index', as: :index_action
end
然后您可以添加下一个/上一个链接到您的视图,如下所示:
<%= link_to "Next", index_action_path(year: @today.year, week: @today.cweek + 1) %>
<%= link_to "Previous", index_action_path(year: @today.year, week: @today.cweek - 1) %>
我还没有测试过这个实现,但它应该可行。无论如何你应该添加测试。
但是如果参数正确,你应该明确地检查它们。例如,如果它们一周在1到52的范围内,依此类推。否则,如果周超出范围,它将引发异常。
还要尝试不将逻辑放入视图中,而是放在辅助方法中。
我希望这有助于编码。 :)
答案 3 :(得分:0)
你在动作go_prev_week中使用@monday,你没有在方法中计算@monday,@ monday是一个实例变量,默认值为nil。
您有两种方法可以解决此问题 -
首先 -
def go_prev_week
index
@sunday = @monday - 1
@monday = @sunday.beginning_of_week
end
第二 - 计算@monday
def go_prev_week
@today = Date::today
@monday = @today.beginning_of_week
@sunday = @monday - 1
@monday = @sunday.beginning_of_week
end
你必须在行动 go_next_week
中做同样的事情