Ruby 在 Rails。通过视图更改控制器的变量并呈现更新的视图
Ruby On Rails. Change controller's variable through view and render updated view
我在 RoR 甚至网络编程方面都是初学者。所以我想我的问题对很多开发者来说太简单了!
我正在实施简单的周日历,它应该有日期名称和两个 "buttons" - 'next week' 和 'previous week'。这就是开始!
我有带索引操作的控制器:
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'
索引视图根据变量
显示 table 天
索引视图有 2 个 "buttons":'next week' 和 'previous week'
点击这个按钮应该会改变控制器的变量
索引视图应 "refresh" 更改控制器的变量
此代码无效。单击 'Previous month' 按钮时,我在日志中遇到这样的错误:
Started GET
"/work_days/go_prev_week?tf8=%E2%9C%93&commit=Previous+week" for
127.0.0.1 at 2015-12-09 14:00:27 +0600 Processing by WorkDaysController#go_prev_week as HTML Parameters:
{"utf8"=>"✓","commit"=>"Previous week"} Current user: admin (id=1)
Completed 500 Internal Server Error in 3ms (ActiveRecord: 0.2ms)
NoMethodError (undefined method `-' for nil:NilClass)
您可能应该在 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
当前一周。
我希望这对您有所帮助,如果您需要更多信息,欢迎您。 :)
您在操作中使用了@monday go_prev_week,您没有在方法中计算@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
I'm very beginner in RoR and even in web-programming.
欢迎光临!
你的问题是你用 @instance_variables
填充你的控制器操作,它们相互依赖:
def go_next_week
@monday = @sunday + 1 # needs @sunday
@sunday = @monday.end_of_week # needs @monday
end
在旧式编程中,这可能会导致无法识别的引用错误或堆栈溢出错误,通常是由于无限 recursion.
错误证实了这一点:
undefined method `-' for nil:NilClass
Ruby
与大多数其他语言的不同之处在于它将未声明的变量分配给 NilClass
对象。这使得开发人员很难确定错误 - 基本上,如果您收到 undefined method for NilClass
,那是因为您没有声明变量。
--
解决方法是将您尝试操作的数据获取到 class 的实例中。这可以通过 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
您似乎希望拥有相同的控制器操作和视图,但仅限于其他日期。
如果是这样,我会向您推荐这样的东西:
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
然后您可以将 next/previous 链接添加到您的视图,如下所示:
<%= 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 的范围内,依此类推。否则,如果周超出范围,它将引发异常。
也尽量不要将逻辑放在视图中,而是放在辅助方法中。
我希望这对您有所帮助,祝您编码愉快。 :)
我在 RoR 甚至网络编程方面都是初学者。所以我想我的问题对很多开发者来说太简单了!
我正在实施简单的周日历,它应该有日期名称和两个 "buttons" - 'next week' 和 'previous week'。这就是开始!
我有带索引操作的控制器:
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'
索引视图根据变量
显示 table 天
索引视图有 2 个 "buttons":'next week' 和 'previous week'
点击这个按钮应该会改变控制器的变量
索引视图应 "refresh" 更改控制器的变量
此代码无效。单击 'Previous month' 按钮时,我在日志中遇到这样的错误:
Started GET "/work_days/go_prev_week?tf8=%E2%9C%93&commit=Previous+week" for 127.0.0.1 at 2015-12-09 14:00:27 +0600 Processing by WorkDaysController#go_prev_week as HTML Parameters: {"utf8"=>"✓","commit"=>"Previous week"} Current user: admin (id=1) Completed 500 Internal Server Error in 3ms (ActiveRecord: 0.2ms)
NoMethodError (undefined method `-' for nil:NilClass)
您可能应该在 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
当前一周。
我希望这对您有所帮助,如果您需要更多信息,欢迎您。 :)
您在操作中使用了@monday go_prev_week,您没有在方法中计算@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
I'm very beginner in RoR and even in web-programming.
欢迎光临!
你的问题是你用 @instance_variables
填充你的控制器操作,它们相互依赖:
def go_next_week
@monday = @sunday + 1 # needs @sunday
@sunday = @monday.end_of_week # needs @monday
end
在旧式编程中,这可能会导致无法识别的引用错误或堆栈溢出错误,通常是由于无限 recursion.
错误证实了这一点:
undefined method `-' for nil:NilClass
Ruby
与大多数其他语言的不同之处在于它将未声明的变量分配给 NilClass
对象。这使得开发人员很难确定错误 - 基本上,如果您收到 undefined method for NilClass
,那是因为您没有声明变量。
--
解决方法是将您尝试操作的数据获取到 class 的实例中。这可以通过 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
您似乎希望拥有相同的控制器操作和视图,但仅限于其他日期。
如果是这样,我会向您推荐这样的东西:
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
然后您可以将 next/previous 链接添加到您的视图,如下所示:
<%= 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 的范围内,依此类推。否则,如果周超出范围,它将引发异常。
也尽量不要将逻辑放在视图中,而是放在辅助方法中。
我希望这对您有所帮助,祝您编码愉快。 :)