1

У меня был индексный метод, который выглядел, ужасно, как это:Rails: коллекция на основе Params

def index 
    if params[:brand] 
     @users = User.includes(:brand).where(brand_id: params[:brand]).order("#{sort_column} #{sort_direction}").page(params[:page]).per(10) 
    elsif params[:search] 
     @user = User.includes(:brand).find_by_client_code(params[:search]) 
     redirect_to edit_user_path(@user) 
    elsif params[:page] == 'all' 
     @users = User.includes(:brand).order("#{sort_column} #{sort_direction}").all 
    elsif params[:state] 
     @users = User.includes(:brand).where(state: params[:state]).page(params[:page]).per(10) 
    else 
     @users = User.includes(:brand).order("#{sort_column} #{sort_direction}").page(params[:page]).per(10) 
    end 
    end 

Довольно грязный, я знаю, но это сработало. Теперь я пытаюсь реорганизовать его, и я не могу найти лучший способ разделить его на более мелкие коллекции, не усложняя мои маршруты.

def index 
    [:brand, :page, :search, :state].each do |param| 
     if params[:page] == 'all' 
     @users = User.includes(:brand).order(column + ' ' + direction) 
     elsif params.key?(param) 
     param 
     else 
     @users = User.includes(:brand).order(column + ' ' + direction) 
        .page(params[:page]).per(10) 
     end 
    end 
    end 

    def brand 
    @users = User.includes(:brand).where('brand_id in (?)', params[:brand]) 
       .order(column + ' ' + direction).page(params[:page]).per(10) 
    end 

    def state 
    @users = User.includes(:brand).where(state: params[:state]) 
       .page(params[:page]).per(10) 
    end 

    def search 
    @user = User.includes(:brand).find_by_client_code(params[:search]) 
    redirect_to edit_user_path(@user) 
    end 

Вышеупомянутое не работает, но вы получаете эту идею. Кто-нибудь знает хороший способ справиться с этим типом ситуации? Приветствия.

+1

Я просто прошел тот же путь обучения. Я использовал все мои запросы AJAX в действии шаблона, но теперь я помещаю их в свои собственные методы. Я не мог найти много рекомендаций в Интернете по этой теме tbh.Я надеюсь, что кто-то более опытный будет прослушивать, но я отделил большинство запросов AJAX от своих собственных действий и маршрутов и доволен результатами. Логику легче следовать, и мои действия не загромождают. Мой файл маршрутов более заполнен, но с надлежащей организацией он по-прежнему выглядит чистым. Хороший вопрос! – Steve

+0

Какую версию рубина вы используете? – Surya

+0

Я использую Ruby '2.1.2'. –

ответ

1

Я бы, наверное, сделать это таким образом -

Во-первых, обновлять этот код, в котором вы определили sort_column и sort_direction методы имеют значения по умолчанию:

def sort_column 
    colum_name = params[:colum_name] 
    colum_name ||= 'id' 
end 

def sort_direction 
    direction = params[:direction] 
    direction ||= 'ASC' 
end 

Добавить новый способ иметь per_page (в том же месте, где у вас есть sort_column и sort_direction) из Params или отказа от User класса:

def per_page 
    per = params[:per_page] 
    per ||= User.per_page 
end 

в приложения/модель/user.rb:

scope :with_brand_id, ->(id) { where(brand_id: id) } 
scope :with_state, ->(state) { where(state: state) } 
scope :order_with, ->(column_name, direction) { order("#{sort_column} #{sort_direction}") } 

# never use/avoid magic numbers in your application at multiple places as they gets unmanageable as your application grows 
# single place to manage your per page entries for users. 
def self.per_page 
    10 
end 

# easy to use key:value based arguments since you're using Ruby 2, cheers! 
def self.fetch_with_brand(brand: nil, state: nil, page: nil, sort_column: 'id', sort_direction: 'ASC', per_page: User.per_page) 
    user_scope, pagination_scope_applies = if brand.present? 
    [self.with_brand_id(brand), true] 
    elsif state.present? 
    [self.with_state(state), true] 
    else 
    [self.scoped, (page != 'all')] 
    end 

    user_scope.merge(pagination_scope(page, per_page)) if pagination_scope_applies 
    user_scope.includes(:brand).order_with(sort_column, sort_direction) 
end 

# since I am not sure about your implementation of `page` and `per` methods, I'd create a class method, otherwise you can create a `scope` for this, too 
def self.pagination_scope(page_number, per_page) 
    self.page(page_number).per(per_page) 
end 

Вы з строки: [self.scoped, (page != 'all')] в коде уже упоминалась выше? Здесь self.scoped равно self.all (при оценке), но мы будем использовать scoped вместо all как в Rails 3 это дает массив, в то время как в Rails 4 это будет ActiveRecord :: Отношение объект, так что вы можете используйте self.all, если вы находитесь на Rails 4. ПРИМЕЧАНИЕ: scoped устарел в Rails 4 в пользу all.

Кроме того, я хотел бы указать здесь здесь. В вашем коде вы отдаете приоритет состоянию params[:page] == 'all', а затем - params[:search]. В коде, который я упомянул выше, отдается приоритет search, а затем до page, но вы получаете эту идею, не так ли?

Теперь давайте добавим пользовательский метод конкретного Params в контроллере:

def user_params 
    params.slice(:brand, :page, :state).merge!({sort_column: sort_column, sort_direction: sort_direction, per_page: per_page }) 
end 

Однако в Rails 4 это проще сделать с сильными параметрами, например: params.require(:user).permit(:search,..) т.д.

Теперь, ваш контроллер Индексный метод может выглядеть следующим образом:

def index 
    if params[:search].present? 
    @user = User.find_by_client_code(params[:search]) 
    redirect_to edit_user_path(@user) 
    else 
    @users = User.fetch_with_brand(user_params) 
    end 
end 

Или вы можете реорганизовать его дальше, если вы, как правило, чтобы перенаправить пользователя на страницу редактирования в нескольких местах:

before_filter :redirect_to_edit, only: [:index, :some_other_method_name] 

def index 
    @users = User.fetch_with_brand(user_params) 
end 

def redirect_to_edit 
    if params[:search].present? 
    @user = User.find_by_client_code(params[:search]) 
    redirect_to edit_user_path(@user) 
    end 
end 

У вас есть тощий контроллер теперь.

+0

Ничего себе, спасибо за очень подробный ответ. Намного лучше! –