簡體   English   中英

提交前以Rails表單動態加載模型關聯

[英]Load model association dynamically in Rails form before submit

因此,我不確定如何實現此目標,或者不確定是否有可能,並且很難尋找類似的示例/答案。 但是,有沒有一種方法可以提交表單之前在表單中動態加載模型關聯,就像不知道實例變量會提前一樣?

我的模型如下:

Property
  has_many :owners, inverse_of: :property
  has_many :orders

Owners
  belongs_to :property

Orders
  belongs_to :property
  has_many :owners, through: :property

在我的orders.new表單中,我具有選擇框,以選擇一個屬性來創建新訂單的關聯(使用Select2插件):

<%= bootstrap_form_for(@orders, ...) do |f| %>
    ...
    <%= f.select :property_id, options_from_collection_for_select(Property.all, "id", "full_address"),
             { label: "Property:", include_blank: true }, { id: "orderPropSelect", data: { placeholder: "Select a Property"} } %>
    ...
<% end %>

因此,當有人為新訂單選擇property時,是否可以在提交表單之前加載owners屬性已經與之關聯的owners 即使只是能夠看到所有者已經存在也可以(可以對其進行編輯會更好,但我意識到那可能更復雜)

以下代碼當然不起作用,但按照以下方式尋找東西:

<%= f.static_control label: "Property Owners" do %>
  <% :property_id.owners.each do |owner| %>
    <%= owner.name %>
  <% end %>
<% end %>

我已經嘗試過使用fields_for變體,但是我不知道如何告訴嵌套字段基於上述select (當然,根據選擇的property來加載不同的所有者。我得到的錯誤是undefined method owners for nil:NilClass是合適的,因為我知道我沒有告訴rails正確的位置。

那有可能嗎?如果可以,我將如何實現呢?

(如果有人想知道表單語法,我會使用bootstrap表單gem。我也為其他表單加載了cocoon,因此,如果有使用方法,我就不會反對。)

更新工作代碼,對無關的條件進行了一些修改。

$("#orderPropSelect").off().on('change', function() {
    var id = $(this).val();
    console.log(id);
    if (id !== '') {
        $.ajax({
            url: '/properties/' + id + '/owners',
            dataType: "json",
            success: function (data) {
                owners_html = '';
                $.each(data['owners'], function () {
                    owners_html += '<p>' + this + '</p>';
                });
                if (owners_html === '') {
                    $("#propOwnersShow").html('<p>No owner added yet.</p>');
                } else {
                    $("#propOwnersShow").html($(owners_html));
                }
            },
            error: function (XMLHttpRequest, textStatus, errorThrown) {
                console.log(errorThrown);
            }
        });
    } else {
        $('#propOwnersShow').html('Please select a Property below to view its associated owners.')
    }

});

您需要確保它與您的基礎路線和內容相匹配,並可能處理沒有所有者的情況,以便隱藏所有者div。 如果您想做更復雜的事情,可以用.pluck代替構建帶有ID的更好的數組/哈希,然后還可以用來構建可以與之交互的元素(例如,從列表中刪除它們)

# your property controller

before_action :allowed, only [:owners]

def owners
  owners = Property.find(params[:id]).owners.pluck(:name)
  respond_to |format|
    format.json { render json: { owners: owners, success: true } }
  end
end

def allowed
  # logic to define if this user is allowed to request this data, if you have devise, it could be
  user_signed_in? && request.xhr?
end

# your routes.rb

get "properties/:id/owners", to: "properties#owners", as: "property_owners"

# or if you have resources
resources :properties do
  member do
    get :owners
  end
end

# js file

$("#property_id").off().on('change', function() {
  var id = $(this).val();
  $.ajax({
    url: '/properties/'+id+'/owners',
    dataType: "json",
    success: function(data) {
      owners_html = '';
      $.each(data['owners'], function() {
        owners_html += '<p>'+this+'</p>';
      });
      $("selector_where_you_want_to_show_owners").html($(owners_html));
    },
    error: function(XMLHttpRequest, textStatus, errorThrown) {
      console.log(errorThrown);
    }
  });
}

更新:

您可以改用find_by並確保始終返回[]來防止沒有所有者的問題,這樣也可以簡化前端的邏輯。

# on your controller instead use:

def owners
  # .find_by will return "nil" if no properties are found, which 
  # then we can leverage with .try. .try will "try" calling those
  # chained methods without raising an error. It usually returns
  # "nil" if the parent is "nil" but .try with .pluck though will
  # always return an [] no matter what the ancestors returned. 

  owners = Property.find_by(id: params[:id]).try(:owners).try(:pluck, :name]

  # actually looking at your relationships it seems you could instead
  # .where, since that will return an empty array, like so:

  # owners = Owner.where(property_id: params[:id]).pluck(:name)

  # this only does one database query where the other one does 2

  # here we're simply making sure we add something to the array so
  # that then on the front-end you can always deal with an array
  # without worrying with the "no properties found". .blank? will
  # return "true" if the value is nil, empty string, empty hash or
  # empty array which works fine for this. So if there's no value in
  # the array we add the "no owners" string.

  owners << 'No owner added yet.' if owners.blank?

  respond_to |format|
    format.json { render json: { owners: owners, success: true } }
  end
end

# And then since you'll always be returning an array you no longer
# have to worry about an empty array and your ajax function will
# look like this:

$.ajax({
  url: '/properties/' + id + '/owners',
  dataType: "json",
  success: function (data) {
    owners_html = '';
    $.each(data['owners'], function () {
      owners_html += '<p>' + this + '</p>';
    });
    $("#propOwnersShow").html($(owners_html));
  },
  error: function (XMLHttpRequest, textStatus, errorThrown) {
    console.log(errorThrown);
  }
});

希望這可以幫助

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM