撒拉嘿哟木头 2014-09-05 03:37 采纳率: 100%
浏览 39

Rails Ajax更新div

Hi i'm new to rails and i want to move a user story in its correct column depending on its state (to be done, in progress,..) with ajax my show template contains four divs with classed (ToBeDone, InProgress, ToBeVerified, Completed)

my update.js.erb

$("div.<%= @user_story.state.underscore %>:first").append("<%= j render(@user_story)%>");

and my update action

 if !@user_story.users.include? current_user
      @user_story.users << current_user
    end
    format.html { redirect_to @user_story.project, notice: 'User story was successfully updated.' }
    format.json { render :show, status: :ok, location: @user_story }
    format.js

and my user_story partial (this form is submitted when the user selects state)

<%= form_for [@project, user_story], remote: true  do |f|%>
  <div class="field" id='my_select_chzn'>
    <%= f.label :state %>
    <%= f.select :state, ['To be done', 'In progress', 'To be verified', 'Completed'], {:selected => user_story.state }, :id =>'select-state', :class => 'chosen-select'%>
  </div>
<%end%>

Please help, thanks and sorry for this long post.

  • 写回答

1条回答 默认 最新

  • weixin_33736048 2014-09-05 10:08
    关注

    Several things you'l benefit from:


    Ajax

    When you mention you're using "ajax", you must remember that ajax has to be called. You currently are using the remote: true functionality (totally fine), but also mention that you want to call it when you change the select box.

    The problem here is that remote: true is rails UJS, and is scripted to only fire when an "action" has been triggered on your element. In short, for forms, it will only trigger when you submit the form.

    This means you have to ensure the ajax actually fires:

    #app/assets/javascripts/application.js
    $(document).on("change", "#select-state", function() {
       $(this).parent().submit();
    });
    
    #app/views/controller/view.html.erb
    <%= form_for [@project, user_story], remote: true  do |f|%>
      <div class="field" id='my_select_chzn'>
        <%= f.label :state %>
        <%= f.select :state, ['To be done', 'In progress', 'To be verified', 'Completed'], {:selected => user_story.state }, :id =>'select-state', :class => 'chosen-select'%>
      </div>
    <% end %>
    

    This should trigger the Ajax request for you. If you want to learn more about Ajax, just comment me on here!


    DIV

    To update your div, you need to be able to capture the Ajax response.

    This can be done in two ways: by capturing with JS, or by using the Rails UJS mechanisms (which is what you're doing). When you call update.js.erb, you're creating the JS which you'd like to be run on your page

    This means you may want to do something like this:

    #app/controllers/your_controller.rb
    ...
      def update
        @user_story.users << current_user unless @user_story.users.include? current_user
        respond_to do |format|
           format.js
           format.html { redirect_to @user_story.project, notice: 'User story was successfully updated.' }
           format.json { render :show, status: :ok, location: @user_story }
        end
      end
    

    Then, in your .js.erb file, you'll want to make sure your div elements are present for your JS to work on. I see you're calling $("div.<%= @user_story.state.underscore %>:first") - you need to ensure this div actually exists.

    Moreover, I'd actually say that having 4 separate divs is bad. In keeping the DRY principles at the core of Rails, you'll be best keeping a single div, populating with the data you want & styling with different CSS classes


    State Machine

    Your use of "state" is almost the picture-perfect implementation of a state_machine.

    This is a type of programming functionality (I believe used in electronics too), to give your objects state - meaning that instead of having to set a series of "strings" for your state column, you should be able to give it object orientated functionality

    I believe using one of the state machine gems for Rails will give your application a much deeper and more thorough implementation of your desired functionality:

    All of these (from my experience) work in a very similar way -- they update a central state column with relative data you set in your state machine. The major difference is that you'll be dealing with things on an object / model level, rather than setting a string.

    It will be easier to understand if you look through the state_machine documentation, especially pertaining to the methods you get from implementing one of these gems. This should demonstrate the object-orientated nature of the state of your model - which you can implement below:

    #app/models/user_story.rb
    class UserStory < ActiveRecord::Base
      include AASM
    
      aasm do
        state :to_be_done, :initial => true
        state :in_progress
        state :to_be_verified
        state :completed
    
        event :complete do
          transitions :from => [:to_be_done, :in_progress, :to_be_verified], :to => :completed
        end
    
        event :progress do
          transitions :from => [:to_be_done, :to_be_verified, :completed], :to => :in_progress
        end
    
        event :verify do
          transitions :from => [:to_be_done, :in_progress, :completed], :to => :to_be_verified
        end
      end
    end
    

    This will give you the ability to call the various methods which attach themselves to the UserStory object:

    @user_story = UserStory.find 1
    
    @user_story.state # -> "to be verified"
    @user_story.completed? #-> true / false
    @user_story.in_progress? #-> true / false
    
    @user_story.complete! # -> state = "completed"
    

    Now, this won't help you directly in setting a "state" for your object. The only way this will really help is if you structure your object creation around the various methods you'll get as a result of using the state machine

    A good example of this would be if you wanted to send a "bulk" email - you'd be able to use the following:

    #app/models/message.rb
    class Message < ActiveRecord::Base
       after_create :send
    
       private
    
       def send
          self.broadcast!
       end
    end
    

    If you'd like more information about this, please let me know in the comments!

    评论

报告相同问题?

悬赏问题

  • ¥50 安卓adb backup备份子用户应用数据失败
  • ¥20 有人能用聚类分析帮我分析一下文本内容嘛
  • ¥15 请问Lammps做复合材料拉伸模拟,应力应变曲线问题
  • ¥30 python代码,帮调试
  • ¥15 #MATLAB仿真#车辆换道路径规划
  • ¥15 java 操作 elasticsearch 8.1 实现 索引的重建
  • ¥15 数据可视化Python
  • ¥15 要给毕业设计添加扫码登录的功能!!有偿
  • ¥15 kafka 分区副本增加会导致消息丢失或者不可用吗?
  • ¥15 微信公众号自制会员卡没有收款渠道啊