在Rails中,使用check_box_tag,如何在提交查询后保持复选框的选中状态?

3

好的,我知道这是关于SaaS课程的内容,人们也在提出相关问题,但我已经花费了很多时间尝试和阅读,现在卡住了。首先,当您有一个名为Movie的模型时,使用Ratings作为模型并将它们关联起来是否更好,还是只是在空间中保留Ratings数组?其次,在我的控制器中,这是我现在拥有的:

def index

@movies = Movie.where(params[:ratings].present? ? {:rating => (params[:ratings].keys)} :   {}).order(params[:sort])
@sort = params[:sort]
@ratings = Ratings.all

end

现在,我决定创建一个评分模型,因为我认为这会更好。以下是我的看法:

= form_tag movies_path, :method => :get do

Include:
- @ratings.each do |rating|
 = rating.rating
 = check_box_tag "ratings[#{rating.rating}]"
= submit_tag "Refresh"

我尝试了所有与在复选框标签中使用条件三元运算符有关的方法,以“ .include?(rating)? true:“”结尾。我尝试了所有应该有效的方法,但都不起作用。我不需要确切的答案,只需要指导。谢谢!
更新(控制器方法):
以下是控制器中的 index 方法,用于读取此哈希表 - 为了清晰起见。对于之前的模糊,我感到抱歉。
def index    
  @all_stores = Product.all_stores
  @selected_stores = params[:stores] || session[:stores] || {}

  if @selected_stores == {}
    @selected_stores = Hash[@all_stores.map {|store| [store, store]}]
  end
  if params[:stores] != session[:stores]
    # session[:stores] = @selected_stores
    session[:stores] = params[:stores]
    redirect_to :stores => @selected_stores and return
  end
  @products = Product.order("created_at desc").limit(150).find_all_by_store(@selected_stores.keys).group_by { |product| product.created_at.to_date}
. . . etc

在我看来,数据库的主要目的是存储相对短时间内可能会发生变化的数据。您电影的评级集合相对静态,因此我建议将其作为数组常量存储在您的电影类中,例如 RATINGS = ['R', 'PG', etc.] - cdesrosiers
一个常量?那很有道理。我没有想到过。起初我有一个实例变量@ratings = ['R','PG',等等],然后我想也许我得使用一个模型。谢谢。 - user866503
没问题,这会让它变得更简单。 - cdesrosiers
这是我所做的,我刚刚读到应该将常量放入我的模型中。很好。 - user866503
1个回答

12

有几件事情需要注意:

1) .order(params[:sort]) 存在 SQL 注入攻击的风险,攻击者可以通过在查询字符串中加入以下内容来删除所有用户:

http://localhost:3000/movies?sort=email%3B+DELETE+from+users+--

请参见rails 3 activerecord order - what is the proper sql injection work around?,使用 .where 方法不会出现这个问题,Rails 会为 where 方法验证输入。

2) AREL 延迟实际调用数据库直到您迭代集合,因此您可以“构建”查询,这种语法可能比使用三元运算符更容易理解?

@movies = Movie.order(xxxxxx)
@movies = @movies.where(:rating => params[:ratings].keys) if params[:ratings].present?

3) 对于你的评级,像cdesrosiers说的那样,使用常量即可,然后是你的视图

Movie::RATINGS.each do |rating|
  check_box_tag "ratings[]", rating # <input type="checkbox" name="ratings[]" value="PG" />

编辑:保留所选值

# controller
@selected_ratings = (params[:ratings].present? ? params[:ratings] : [])

# view
Movie::RATINGS.each do |rating|
  check_box_tag "ratings[]", rating, @selected_ratings.include?(rating)
  # <input type="checkbox" name="ratings[]" value="PG" checked="checked" />

注意复选框名称中的[],这将在您的控制器操作中使params[:ratings]成为一个数组。

@movies = @movies.where("rating IN (?)", params[:ratings]) if params[:ratings].present? and params[:ratings].any?

一些链接


谢谢,伙计!是的,每当我尝试解决问题时,我总是直接进行查询,这是一个坏习惯。总有一天我会忘记在真实环境中更改它。 - user866503
其实我不确定你的答案。我还是卡在同一个地方。我试图保持复选框被选中!我知道我可以得到一个选中值的数组。但我很难查询这个数组。这就是我所说的三元运算符。不是控制器中的那个。我的意思是我在视图中做了这个:@movie.ratings.include?(rating) ? true: ""。但那行不通。我该如何保持复选框被选中? - user866503
我也尝试过使用params[:ratings].include?(rating),但似乎太菜了。我尝试了很多方法。大多数情况下,我会在尝试了两天后才来这里求助。我有一个很大的自我意识。 - user866503
更新的答案 - 基本上它正在执行 params[:ratings].include?(rating),只是在它不存在的情况下存储并初始化一个空数组。 - house9
伙计,我不知道发生了什么事,但我只是在我的视图中写了这个:= check_box_tag "ratings[#{rating}]",rating,params[:ratings].include?(rating),就这样。我已经尝试了15次,现在它终于可以工作了!!我真的一点也不明白。 - user866503

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接