【问题标题】:UJS, AJAX, Rails 4, form_for collection_select to pass value into method and return value back to formUJS、AJAX、Rails 4、form_for collection_select 将值传递给方法并将值返回给表单
【发布时间】:2014-07-27 05:59:22
【问题描述】:

我对 Rails 很陌生,因此在同时处理 AJAX、UJS 和 Rails 时有很多困惑。我查看了 railscast,几个 SO 答案,尝试了 freenode 上的#rubyonrails IRC 频道。 唉,我还是卡住了。

无论如何,这是我的问题。

所以我有两个模型,建筑和财产。属性属于_to Building 和 Building has_many Properties。

我已将外键添加到 Property 作为 building_id。

现在,在我的建筑模型中,我有一个方法:self.search(search) 并给出正确的地址(例如 999 Decarie),它将正确返回数据库中 Building 表中的 building_id。

def self.search(search)
    #search.instance_variables.map {|v| "#{v}: #{search.instance_variable_get(v)}\n"}.join
    if ((search.nil?) || (search == ""))
        nil
    else
        search = search.to_s
        d { search }
        split = search.split(' ', 2)
        stnum = split.first
        d { stnum }
        stname = split.last
        d { stname }
        Building.where("streetno = ?", stnum).where("streetname = ?", stname).pluck(:id).first
    end
end

在我的属性部分 _form 中,我有一个 form_for 循环,它使用一个 collection_select 来允许用户选择任何建筑地址(例如 999 Decarie),(因此它呈现为一个选择/选项 HTML 下拉列表)。

<div class="field" id="selection">
   <%= f.collection_select :buildinginfo, Building.all, :half_address, :half_address, {:label => "Building Info"}%>
</div>  

那么,我该如何使用不显眼的 javascript/ajax

A.用户在表单中选择后立即获取集合select的选择值,并将其传递给上面提到的建筑模型方法(self.search(search)),该方法返回正确的建筑ID。

B.立即获取方法返回的建筑物 ID 并将其存储在表单上的隐藏字段中(对应于 Properties 模型中的 building_id 字段)。 (在下面的代码中,我想将值 1 替换为建筑物 ID)

 <div class="field" id="selection_id">
         <%= f.hidden_field :building_id, :value => 1 %>  
      </div>    

因此,允许我的关联工作,这样当我删除建筑物时,其所有相关属性也会被删除。

如果您需要更多代码,请告诉我,我正在使用 Rails 4,非常感谢!

【问题讨论】:

    标签: ruby-on-rails ajax form-for ujs collection-select


    【解决方案1】:

    Ajax

    在 Rails 中,Ajax 的工作方式与网络上其他任何地方完全相同 - 您使用 Javascript 发送异步请求、服务器处理并发送响应。

    Rails 的诀窍是让您的代码尽可能地模块化,这就是为什么ujs 的东西经常在应用程序中使用。你最好阅读Rails' ujs ajax capabilities here

    一旦用户选择它

    听起来你需要.on("change"

    #app/assets/javascripts/application.js
    $(document).on("change", function(){
       $.ajax({
           url: "your/path",
           data: {search: $(this).val()},
           success: function(data) {
               // ... do stuff here
           }
       });
    });
    

    这基本上会将请求发送到您的服务器,允许您根据需要处理响应。

    立即获取该方法返回的建筑物ID,并将其存储在隐藏字段中

    你会想要这样做:

    #Ajax method
    success: function(data) {
        $("#element").val(data);
    }
    

    这需要在您的控制器中附有respond_to 块,如下所示:

    #app/controllers/your_controller.rb
    respond_to :js, :json
    def search
       @search = Model.search params[:search]
       respond_with @search
    end
    

    --

    数据

    有趣的一点 - 您可以使用 .find_by 代替多个 where 查询,如下所示:

    Model.find_by(name: value, name: value).pluck(:id)
    

    【讨论】:

      【解决方案2】:

      感谢您花时间解释这个 Rich。

      虽然您的方法有意义,但我使用了不同的方法,因为我的最终目标只是在建筑物 (has_many) 和属性 (belongs_to) 之间创建关联,当我删除建筑物时,我还希望删除与其关联的所有属性也是。

      因此,在创建/更新属性时,我需要将其添加到 Building.properties 数组中,该数组会自动更新属性的 building_id 字段。

      这是我在 properties_controller 中的最终代码:

      def create
        @property = Property.new(property_params)
      
        **b_id = Building.search(@property.buildinginfo)**
        **Building.find_by(id: b_id).properties << @property**
      
        respond_to do |format|
          if @property.save
            format.html { redirect_to @property, notice: 'Property was successfully created.' }
            format.json { render :show, status: :created, location: @property }
          else
            format.html { render :new }
            format.json { render json: @property.errors, status: :unprocessable_entity }
          end
        end
      end
      
      def update
      respond_to do |format|
        if @property.update(property_params)
      
          **b_id = Building.search(@property.buildinginfo)**
          **Building.find_by(id: b_id).properties << @property**
      
          format.html { redirect_to @property, notice: 'Property was successfully updated.' }
          format.json { render :show, status: :ok, location: @property }
        else
          format.html { render :edit }
          format.json { render json: @property.errors, status: :unprocessable_entity }
        end
      end
      end
      

      Building.search 函数(在建筑模型中):

          def self.search(search)
      
          if ((search.nil?) || (search == ""))
              nil
          else
              search = search.to_s
              split = search.split(' ', 2)
              stnum = split.first
              stname = split.last
              s = Building.where("streetno = ?", stnum).where("streetname = ?",  stname).pluck(:id).first
              s
          end
      end
      

      【讨论】:

        【解决方案3】:

        这里有一个与此问题相关的示例,希望对您有所帮助。 在本例中,我们将验证电子邮件。

        users_controller定义一个方法,在routes.rb设置路由

        class UsersController < ApplicationController
        
        def check_email
            @email = User.exists?(:email=> params[:email])  
            respond_to do |format|
                if @email
                 format.json { render json: @email }
                else
                 format.json { render json: @email }
                end
            end
        end
        

        routes.rb get "check_email" =&gt; "users#check_email"

        现在来到register.html.erb页面,添加javascript为:

        $('#email').blur(function(){
        
        var re = /[A-Z0-9._%+-]+@[A-Z0-9.-]+.[A-Z]{2,4}/igm;
        
        if($('#email').val().trim()=="" || !re.test($('#email').val()))
        {
            $("#lbl_email").text("*Please enter a valid email address");
            $('#lbl_email').show();      
            return false;           
        }
        else
        {
            $('#lbl_email').hide();
        
            $.ajax({
                type: "GET",
                url: "/check_email",
                data:{ email: $(this).val() },
                dataType: "json",
                success:function(data){
                  $('#lbl_email').show(); 
                  $("#lbl_email").text("*Oppss! Email already exists");
                  return false;
        
                },
                error: function() {
                    $('#lbl_email').hide(); 
                }
            });
        }
        });
        

        【讨论】:

          猜你喜欢
          • 2023-04-01
          • 1970-01-01
          • 1970-01-01
          • 2012-07-14
          • 1970-01-01
          • 1970-01-01
          • 2010-11-03
          • 2014-02-02
          • 2015-09-27
          相关资源
          最近更新 更多