Rails 5.1,组内搜索范围

时间:2018-02-07 12:33:34

标签: ruby-on-rails search scope model ruby-on-rails-5

我对搜索范围有一点问题 用户可以通过提供令牌来加入群组。用户还可以创建支出,并且可以在组中共享它们。我们在一个小组的展示视图中。这是我循环每个用户在此组中的支出的地方。看起来像这样:

<% group_spendings_paginate_search.each do |groupspending| %>
    <%= groupspending.member.user.firstname %>
    <%= groupspending.spending.title %>
    <%= groupspending.spending.description %>
    <%= '%.02f' % groupspending.spending.amount %>
    <%= groupspending.spending.currency.symb %>
    <%= groupspending.created_at.strftime("%d/%m/%Y") %>
<% end %>

group_spendings_paginate_search来自帮助者,代表:

def group_spendings_paginate_search
        @search.scope.order('created_at DESC').paginate(:page => params[:page], :per_page => 10)
end

搜索表单看起来像这样,就在循环之上:

<%= form_tag group_path(@group), method: :get do %>
        <%= date_field_tag "search[date_from]", @search.date_from %>
        <%= date_field_tag "search[date_to]", @search.date_to %>
        <%= select_tag "search[user_id]", options_from_collection_for_select(@group.users.all, :id, :firstname, params[:user_id]), include_blank: "All Users" %>
        <%= select_tag "search[currency_id]", options_from_collection_for_select(Currency.all, :id, :name, params[:currency_id]), include_blank: "All Currencies" %>
        <%= submit_tag "Search", name: nil %> 
<% end %>

请注意,我必须使用Currency.all,而不是用户使用的货币。例如,他们可能只使用欧元,所有列表都会弹出,这也不是很酷。宁愿只显示用户根据组和支出使用的货币。但是嘿,它已经足够复杂,所以现在我会保持简单并稍后回来。但如果有人有想法,请随意。

我的控制器:

def show
    @search = GroupspendingSearch.new(params[:search])
end

最后我的GroupspendingSearch.rb

class GroupspendingSearch
    attr_reader :date_from, :date_to, :user_id, :currency_id


    def initialize(params)
        params ||= {}
        @date_from = parsed_date(params[:date_from], 1.month.ago.to_date)
        @date_to = parsed_date(params[:date_to], Date.tomorrow)
        @user_id = params[:user_id]
        @currency_id = params[:currency_id]
    end

    def scope
        launch = Groupspending.where('groupspendings.created_at BETWEEN ? AND ?', @date_from, @date_to)
        launch = launch.where(member_id: find_member) if find_member.exists?
        launch = launch.where(spending_id: find_currency) if find_currency.exists?

        launch
    end

    private

    def parsed_date(date_string, default)
        Date.parse(date_string)
    rescue ArgumentError, TypeError
        default
    end

    def find_member
        Member.where(user_id: @user_id)
    end

    def find_currency
        Spending.where(currency_id: @currency_id)
    end
end

范围实际上是有效的。唯一的问题是它适用于所有的Groupspending而不是@group.groupspendings。这意味着,如果我进入任何一组,我会看到所有的花费,我当然希望避免这种情况。此外,我必须明智地找到user_id和currency_id。使用表Groupspending只给我member_id和spend_id。使用此模型中的group_id或token,一切都会更容易...... 基本上我不知道如何在范围内指定@group是否有意义。

我想到了几件事。第一个是在控制器中,并指定一个像@search = GroupspendingSearch.new(params[:search],@group)这样的其他参数,并将其添加到模型def initialize(params, group)中,但要成为真正的我真的不知道我在做什么,是的...
我在这里干,有人帮忙吗?也许我在这里完全错了,还有另一种方法。

模特关系(不要注意链接和通知,它是另一个故事^^):

class Currency < ApplicationRecord

    has_many :spendings, dependent: :destroy
    has_many :users, through: :spendings

end

class Group < ApplicationRecord
has_secure_token :auth_token

    has_many :members, :dependent => :destroy
    has_many :users, through: :members, source: :user
    belongs_to :owner, class_name: "User"

    has_many :links, through: :grouplinks
    has_many :grouplinks, through: :members

    has_many :spendings, through: :groupspendings
    has_many :groupspendings, through: :members

    has_many :notifications, dependent: :destroy

    def to_param
        auth_token
    end

end

class Groupspending < ApplicationRecord

    belongs_to :spending
    belongs_to :member

end

class Member < ApplicationRecord

  belongs_to :user
  belongs_to :group
  has_many :grouplinks, dependent: :destroy
  has_many :groupspendings, dependent: :destroy

  validates :user_id, :presence => true
  validates :group_id, :presence => true
  validates :user_id, :uniqueness => {:scope => [:user_id, :group_id]}

end

class Spending < ApplicationRecord

    belongs_to :user
    belongs_to :currency
    has_many :groupspendings, dependent: :destroy

end

class User < ApplicationRecord

    has_secure_password

  has_many :spendings, dependent: :destroy
  has_many :currencies, through: :spendings

  has_many :links, dependent: :destroy

  has_many :notifications, dependent: :destroy

  has_many :members, :dependent => :destroy
  has_many :groups, :through => :members
  has_one :owned_group, foreign_key: "owner_id", class_name: "Group"

end

编辑:

我刚刚意识到实际上范围是不正确的...我寻找member_id:find_member,这适用于所有具有member_id:X的成员。这意味着如果用户是许多成员分组很好......它显示了多个条目。我疯了^^

1 个答案:

答案 0 :(得分:0)

好的,我想我得到了它,但我想确保没有错误或安全问题......

以下是我改变的内容:

辅助

def group_spendings_paginate_search
    m =  Member.where(group_id: @group.id)
    gs = Groupspending.where(member_id: m)
    @search.scope.where(member_id: gs.all.map(&:member_id) ).order('created_at DESC').paginate(:page => params[:page], :per_page => 10)
end

我没有更改视图,也没有更改GroupspendingSearch。有了这个新的帮助器,我只检索组中的成员,这些成员会阻止&#34;阻止&#34;搜索查询。我想......

我不知道它是否是最好的,我不知道它是否安全。在URL中,如果我尝试将user_id更改为其他人,如果他/她不是该组的一部分,则它不会显示。所以它看起来不错。当然,我必须通过仅限制组成员来保护节目视图。但是从那开始,那会没关系吗?