2

Я хочу иметь какой-то единственный список, который инициализируется в отдельном модуле, затем может быть включен в контроллер и изменен на уровне класса контроллера и доступен на контроллере уровень. Я думал, что переменные класса будут работать здесь, но что-то странное происходит, кажется, что они не инициализируются в моем конечном классе.переменные класса и включение модуля, в частности в ActionController

Более конкретно:

У меня есть много контроллеров всех, включая некоторые функциональные возможности по умолчанию, в модуле.

class BlahController < ApplicationController 
    include DefaultFunctionality 
end 

class FooController < ApplicationController 
    include DefaultFunctionality 
end 

module DefaultFunctionality 
    def show 
    render 'shared/show' 
    end 
    def model 
    controller_name 
    end 
end 

, например. Это не настоящий код, но это самое большое взаимодействие, которое оно имеет в настоящий момент.

Я хотел бы расширить это с помощью некоторых других функций (сортируемый интерфейс для списков), так [примечание: я хотел бы иметь возможность менять функциональность списка сортировки по классам ]:

module DefaultFunctionality 
module Sortable 
    def sort_params 
    params.slice(:order, :sort_direction).reverse_merge(default_sort_params) 
    end 
    def default_sort_params 
    @@sorts.first 
    end 
    def set_sorts(sorts = []) #sorts = [{:order => "most_recent", :sort_direction => :desc},...] 
    @@sorts = sorts 
    end 
end 
include Sortable 
set_sorts([{:order => :alphabetical, :sort_direction => :asc}] #never run? 
end 

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

class FooController < ApplicationController 
    include DefaultFunctionality #calls the default set_sorts 
    set_sorts([{:order => :most_recent, :sort_direction => :asc}]) 
end 

А также сделать хорошие ссылки в представлениях, как показано ниже, за исключением того, что я получаю сообщение об ошибке.

___/blah/1 => shared/show.html.erb__ 
<%= link_to("upside down", polymorphic_path(model, sort_params) %><%#BOOOM uninitialized class variable @@sorts for BlahController %> 

я фигура class_var плохой вызов, но я не могу думать о том, что еще я мог бы использовать. (экземпляр класса var?)

ответ

0

Я закончил с использованием переменной экземпляра уровня класса и включен() без autoincluded подмодулей, перед тем заметив, что @tadman ответили.

Кончилось выглядеть так:

class BlahController < ApplicationController 
    include DefaultControllerFunctionality 
    include DefaultControllerFunctionality::Sortable 
end 

class FooController < ApplicationController 
    include DefaultControllerFunctionality 
    include DefaultControllerFunctionality::Sortable 
    sorts=([{:order => :most_recent, :sort_direction => :desc}]) 
end 

в контроллерах, и в/Lib

Lib/default_controller_functionality.rb

module DefaultFunctionality 
    def show 
    render 'shared/show' 
    end 
    def model 
    controller_name 
    end 
end 

Библиотека/default_controller_functionality/сортировкой .rb

module DefaultControllerFunctionality 
    module Sortable 
    def self.included(base) 
     base.helper_method :sort_params 
     base.class_eval <<-END 
      @sorts=[] 
      class << self; attr_accessor :sorts end 
     END 
     #this line^makes it so that the module 
     #doesn't work when included in any other 
     #module than the class you want @sorts to end up in. 
     #So don't include(Sortable) in DefaultControllerFunctionality and expect .sorts to work in FooController. 

     base.sorts= [{:order => :alphabetical, :sort_direction => :asc}] 
    end 
    def sort_params 
     params.slice(:order, :sort_direction).reverse_merge(default_sort_params) 
    end 
    def default_sort_params 
     self.class.sorts.first 
    end 
    end 
end 
2

Классы экземпляров экземпляров - это путь, безусловно. Редко вам действительно нужно использовать переменную класса.

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

Что вам нужно это:

module DefaultFunctionality 
    def sort_params 
    params.slice(:order, :sort_direction).reverse_merge(default_sort_params) 
    end 

    def default_sort_params 
    @sorts.first 
    end 

    def sorts=(sorts = nil) 
    @sorts = sorts || [{:order => "most_recent", :sort_direction => :desc}] 
    end 

    def self.included(base_class) 
    self.sorts = ([{:order => :alphabetical, :sort_direction => :asc}] 
    end 
end 

, как вы ловите класс в том числе модуля является определение Module.included соответственно. В этом случае set_sorts вызывается каждый раз, когда этот модуль включен, и он находится в контексте вызывающего класса.

Я изменил это немного, чтобы включить некоторые конкретные изменения стиля:

  • Заявляя по умолчанию внутри метода, а не в декларации. Избегает создания нечитабельно длинных строк или наличия однострочных, иначе сложных структур данных.
  • Использование переменных экземпляра класса, которые будут выполнять задание в этом случае.
  • Использование Ruby, стиль метод вар = мутатор вместо set_var()
+0

Обратите внимание, что я хотел, чтобы @sorts был уровнем класса, а не уровнем экземпляра. Ниже приведен ответ, который я использовал. Причина, по которой я оставил любые вызовы self.included() в моем вопросе - экземпляры и переменные класса становятся действительно грязными при включении подмодулей. Поэтому я даю вам повышение, поскольку вы переместили методы в DefaultFunctionality, эффективно удалив проблему подмодуля, которая вызывает невыразимые головные боли. –

+0

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

+0

В моем исходном коде я делал отдельные объекты SortOrder, поэтому с make_sorts! метод для преобразования между массивами [order, dir, name] и SortOrder.new (order, dir, name) был полезен. Очевидно, здесь это не так. Я изменил свой ответ, включив стиль self.sorts; это лучше всего подходит для примера. –

0

Вы должны добавить метод included для модуля для этой работы.

module DefaultFunctionality 

def self.included(base) 
    base.include(Sortable) 
    set_sorts([{:order => :alphabetical, :sort_direction => :asc}] #never run? 
end 

module Sortable 
    # other methods 

    def set_sorts(sorts = [{:order => "most_recent", :sort_direction => :desc}]) 
    @@sorts = sorts 
    end 
end 
end