【问题标题】:How to get an attribute from a Rails association如何从 Rails 关联中获取属性
【发布时间】:2016-01-26 15:35:32
【问题描述】:

我有一个用于搜索特定模型(订单)的搜索表单。它工作正常,但我想在我的搜索方法中添加一个来自关联(事务)的参数,该参数嵌套如下:[“params”][“transaction_id”]。使用下面的代码,我收到错误ActiveRecord::StatementInvalid in Orders#index 因为我无法以正确的方式表达它。我该如何解决这个问题?

型号:

class Order < ActiveRecord::Base
  has_many :transactions, :class_name => "OrderTransaction"

  def self.search(params)
    query = order('created_at DESC').joins(:transactions)
    query = query.where('name LIKE ? OR email LIKE ? OR phone LIKE ? OR address1 LIKE ? OR state LIKE ? OR city LIKE ? OR **params.transaction_id** LIKE ?', "%#{params[:search]}%", "%#{params[:search]}%", "%#{params[:search]}%", "%#{params[:search]}%", "%#{params[:search]}%", "%#{params[:search]}%", "%#{params[:search]}%").order('created_at DESC') if params[:search].present?
    query
  end
end

控制器:

def index
  @orders = Order.search(params)
end

查看:

<%= form_tag orders_path, :method => 'get' do %>
  <p>
    <%= text_field_tag :search, params[:search],id: "search_text", placeholder: "   Search order" %>
    <%= submit_tag "Search", :name => nil, class: "btn btn-success", id: "search_but_order" %>
  </p>
<% end %>

解决方案 正如@Lanny Bose 建议我的那样,我为我的订单模型创建了一个新列,并将序列化参数的值传递给它。通过这种方式,我现在可以将其添加到我的搜索方法中。

【问题讨论】:

  • 您的意思是您正在搜索交易的 id 属性吗?
  • 是的,但它在关联模型“事务”中并且是嵌套的。
  • 那你想要transactions.id而不是params.transaction_id
  • 不是这样嵌套的#&lt;ActiveRecord::Associations::CollectionProxy [#&lt;OrderTransaction id: 118, order_id: 124, action: "purchase", params: {"transaction_id"=&gt;"5795241933376546"}
  • 所以你正在序列化参数并将它们存储在数据库中?

标签: ruby-on-rails


【解决方案1】:

嘿,你可以试试这个方法。如果您的列是序列化的,那么您可以在传递搜索字符串之前使用.to_yaml 转换器,在这种情况下,您需要创建与存储时序列化相同的哈希

我们可以使用 yaml 创建您的字符串:

 yml_str = {:transcation_id => params[:search] }.to_yaml.gsub("-","").squish

您可以使用.squish 和gsub 方法从字符串中删除不需要的--- 和\n

将特定列中的查询简化为

Order.includes(:transactions).where("order_transactions.params like ?", "%#{yml_str}%")

你的方法

def self.search(params)

    query = order('created_at DESC').joins(:transactions)
    query = query.where('name LIKE ? OR email LIKE ? OR phone LIKE ? OR address1 LIKE ? OR state LIKE ? OR city LIKE ? OR order_transactions.params LIKE ?', "%#{params[:search]}%", "%#{params[:search]}%", "%#{params[:search]}%", "%#{params[:search]}%", "%#{params[:search]}%", "%#{params[:search]}%", "%#{yml_str}%").order('created_at DESC') if params[:search].present?
    query
  end

【讨论】:

    【解决方案2】:

    在我开始之前,Order.search 中有一个逻辑错误。您设置query = 两次,这意味着您只是在另一个查询上编写一个查询。您想将它们链接在一起。

    至于如何构造查询,你是在正确的轨道上。

    型号

    def self.search(term)
      if term
        Order.order('created_at DESC').joins(:transactions).where("name LIKE :t OR email LIKE :t", t: term)
      else
        nil
      end
    end
    

    注意:t 周围的新语法。 Rails 调用占位符条件in the Rails Guide,这意味着您不必一遍又一遍地复制搜索变量。

    另外,我意识到我只与name 和email 进行了比较。我会让你输入其余的字段。 :)

    编辑

    对不起,我忘了把这个说清楚。我会在控制器中进行参数处理,所以我只是将一个字符串传递给模型。

    控制器

    @orders = Order.search(params[:search])
    

    ...我相信,这绝对是风格重于实质的问题。

    【讨论】:

    • Nice and DRY 你的代码,但它不起作用。另外我的问题是如何访问 ["params"]["transaction_id"]。
    • 我进行了编辑。如果它仍然不适合您,您能否更具体地说明出现了什么错误?
    • undefined method each for nil:NilClass。在我看来,我迭代了我的 @orders 变量。似乎在这一行&lt;% @orders.each do |order| %&gt;
    • 您可以在 Rails 控制台中尝试使用您确定在数据库中的值进行查询吗?
    • 我不知道该怎么做。
    【解决方案3】:

    你考虑过使用作用域吗?

    class Order < ActiveRecord::Base
      scope :name, -> (name) { where("name like ?", "#{name}%")}
      scope :email, -> (email) { where("email LIKE ?", "#{email}%")}
      scope :phone, -> (phone) { where("phone LIKE ?", "#{phone}%")}
      scope :address1, -> (address1) { where("address1 LIKE ?", "#{address1}%")}
      scope :state, -> (state) { where("state LIKE ?", "#{name}%")}
      scope :city, -> (city) { where("city LIKE ?", "#{city}%")}
    
      scope :custom, -> (field, value) { where("#{field} LIKE ?", "#{value}%")}
    
    end
    

    现在我们可以通过以下方式解决嵌套参数问题:

    q=params[:search]
    if q.present?
       result = Order.name(q).or.email(q).or.phone(q).or.address1(q).or.state(q).or.city(q)
        if params[:nested_query]
           hash.each do |key, value|
              result=result.or(key,value)
           end
        end
    end
    

    【讨论】:

    • 我从未使用过示波器。我会试试的,我会告诉你的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-21
    相关资源
    最近更新 更多