簡體   English   中英

從Ruby on Rails中的連接表中有效地繪制值,以便在javascript中使用

[英]Efficiently drawing values from joined tables in Ruby on Rails for use in javascript

我已經看到了一些關於我的問題的相關問題,但沒有任何內容完全涵蓋我需要的內容。 我們有3個數據庫表,在我們的javascript中需要訪問的展位上拆分數據。 我將提取此數據以將其轉換為javascript對象數組。 我遇到的問題是嘗試在這3個表之間執行聯接,然后以不會浪費太多資源的有效方式將某些值推入對象。 我的3個對象在這里列出 我對RoR還不是很熟悉,所以我先在SQL中寫出了我的查詢:

SELECT b.BoothNumber, bt.Width, bt.Depth, bl.room_id, bl.x, bl.y
FROM Booths b
LEFT JOIN booth_types bt ON bt.id = b.booth_type_id
JOIN booth_locations bl ON bl.id = b.booth_location_id
WHERE bl.room_id = @room_ID_provided_by_javascript

我可以在JS中做最后一行,但是為了清楚起見,我將其包括在內。 什么是我最好的選擇? 我的第一次嘗試看起來像下面的代碼。 當然,它不起作用,因為room_id /等。 不屬於“ booth”對象。

    <% Booth.includes(:booth_location, :booth_type).find_each do |booth| %> 
        if(roomIds.indexOf(<%= booth.room_id%>) > -1){//If index in roomIds (is this room in the event?)
            booths.push({boothId: <%= booth.id %>, roomId: <%= booth.roomId %>, x: <%= booth.x %>, y: <%= booth.y %>,
                boothNumber: <%= booth.boothNumber %>, companyId: <%= booth.companyId %>, width: <%= booth.width %>, depth: <%= booth.depth %>});
        }
    <% end %>

我在控制器中的這些表之間有基本的belongs_tohas_many連接,但僅此而已。 我知道我需要在我的控制器中包含某種使用through關鍵字的方法,但我真的不知道這些應該如何與我的數據庫設置方式保持一致。 我已經看到答案不同,從每個控制器添加20多行到在我的開始Ruby行上寫一些額外的單詞。 什么對我有用?

學習has_many :through與推動Javascript不同。 MVC的一部分是從HTML中刪除DB邏輯。 它應該在模型中完成(盡管通常也在控制器中完成)。 我有時會在HTML中編寫DB邏輯,但這是一種懶惰的方法。

這是一個解釋has_many :through的示例:

假設Post表有一個user_id列,Tag表有一個post_id列。 換句話說,一個用戶有很多帖子,每個帖子都有很多標簽。 我們正在嘗試鏈接用戶和標記列,以便我們可以說用戶有很多標記。 我們可以寫下面的關聯:

  • 在post.rb: belongs_to :user
  • 在tag.rb中: belongs_to :post; has_one :user, through: :post belongs_to :post; has_one :user, through: :post
  • 在user.rb中: has_many :posts; has_many :tags, through: :posts has_many :posts; has_many :tags, through: :posts

請注意,沒有belongs_to with through ,您需要使用has_one

您可以使用source選項在命名方面獲得更多靈活性。

class Tag
  has_one :post_author, through: :post, source: :author
  # if for example "post.author" were used instead of "post.user"
end

這是建立聯接表關聯的最簡單方法。 還有其他更復雜的方法。

has_manybelongs_to這樣的方法正在為你的模型創建一個getter方法。 如果您對ActiveRecord查詢語法感到滿意,則可以自己編寫。

例如:

class User
  def tags
    Tag.joins(:posts).where("posts.user_id = ?", self.id)
    # Make sure this method returns an ActiveRecord_Relation,
    # not an array. 
  end
end

user實例方法的行為方式與使用has_one through定義它的方式相同。 這種方法更具可定制性,但對於簡單的情況, has_one方法的輸入較少。

還有scopes的概念,它具有用於編寫這些方法的特定於域的語法。

所以,對於Javascript,我建議稍微改變你的方法。 通過ERB標記將所有數據從Ruby傳遞到Javascript可能會變得難以處理。 在將數據發送到Javascript之前,最好將數據轉換為JSON。 有很多用於將數據轉換為Javascript的Rails助手,例如to_json 我將向您展示如何將分層數據集轉換為JSON的示例:

class User
  def attributes
    super.merge(
      posts: self.posts.map(&:attributes),
      tags: self.tags.map(&:attributes)
    )
  end
end

然后我將創建一個控制器方法來響應JSON:

render json: { user: @user.attributes }.to_json

這將構建數據,以便您可以編寫user["posts"]user["tags"]

如果你想在帖子中嵌套標簽,即你可以寫user["posts"][0]["tags"]

您也可以覆蓋Post屬性:

class Post
  def attributes
    super.merge(
      tags: self.tags.map(&:attributes)
    )
  end
end

但是要注意不要引入遞歸。

將Ruby數據傳遞給Javascript的最后一步是使用AJAX進行獲取。

Rails有AJAX的視圖助手,但我個人更喜歡用Javascript / jQuery編寫代碼,而不是用ERB編寫代碼。 有關Javascript方法的一些信息,請參閱此問題

暫無
暫無

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

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