Ruby on Rails:点击列表按钮为Session赋值对应ISBN的问题
问题原因与解决方案
问题根源
你当前的写法里,link_to的:onclick参数中直接执行session[:isbn] = book["isbn13"],这行代码是服务器端在渲染页面时就会执行的,而非用户点击按钮时触发。当循环遍历所有书籍时,每一次循环都会用当前书籍的ISBN覆盖session中的值,循环结束后session里自然只保留最后一本书的ISBN,所以不管点击哪个按钮,表单都会显示最后一个值。
解决方案
方案一:通过URL参数传递ISBN(推荐)
这种方式无需依赖session,直接把ISBN作为参数传到新建帖子页面,更符合Rails的RESTful设计规范。
修改书籍列表视图代码:
<% @books.list_new['books'].each do |book| %> <p class="title is-4"><%= link_to book['title'], book['url'] %></p> <%= link_to "Create a post!", new_post_path(isbn: book["isbn13"]), class:"button" %> <% end %>将ISBN作为查询参数附加到
new_post_path后。修改
PostsController的new方法:def new @post = Post.new @post.isbn = params[:isbn] if params[:isbn].present? end把URL参数中的ISBN赋值给
@post的对应属性。简化表单代码(无需再从session取值):
<%= simple_form_for @post do |f| %> <%= f.input :isbn, input_html: {class: 'integer'}, wrapper: false, label_html: {class: 'label'} %> <% end %>由于
@post.isbn已被赋值,simple_form会自动预填充输入框。
方案二:通过表单提交设置Session(适合必须用Session的场景)
如果一定要用Session存储ISBN,需要通过表单提交请求后端接口来设置Session(前端无法直接操作服务器端Session):
添加路由(
routes.rb):post 'set_isbn_session', to: 'posts#set_isbn_session'在
PostsController中添加对应动作:def set_isbn_session session[:isbn] = params[:isbn] redirect_to new_post_path end修改书籍列表视图,用表单替代链接:
<% @books.list_new['books'].each do |book| %> <p class="title is-4"><%= link_to book['title'], book['url'] %></p> <%= form_tag set_isbn_session_path, method: :post, class: 'inline' do %> <%= hidden_field_tag :isbn, book["isbn13"] %> <%= submit_tag "Create a post!", class:"button" %> <% end %> <% end %>表单代码保持不变:
<%= simple_form_for @post do |f| %> <%= f.input :isbn, input_html: {class: 'integer', value: session['isbn']}, wrapper: false, label_html: {class: 'label'} %> <% end %>
内容的提问来源于stack exchange,提问作者FlavioR
相关产品推荐
相关产品推荐

