Помимо особенностей того, как ведут себя объекты статического метода , есть определенная красота, с которой вы можете столкнуться с ними, когда дело доходит до организации кода на уровне модуля.
# garden.py
def trim(a):
pass
def strip(a):
pass
def bunch(a, b):
pass
def _foo(foo):
pass
class powertools(object):
"""
Provides much regarded gardening power tools.
"""
@staticmethod
def answer_to_the_ultimate_question_of_life_the_universe_and_everything():
return 42
@staticmethod
def random():
return 13
@staticmethod
def promise():
return True
def _bar(baz, quux):
pass
class _Dice(object):
pass
class _6d(_Dice):
pass
class _12d(_Dice):
pass
class _Smarter:
pass
class _MagicalPonies:
pass
class _Samurai:
pass
class Foo(_6d, _Samurai):
pass
class Bar(_12d, _Smarter, _MagicalPonies):
pass
...
# tests.py
import unittest
import garden
class GardenTests(unittest.TestCase):
pass
class PowertoolsTests(unittest.TestCase):
pass
class FooTests(unittest.TestCase):
pass
class BarTests(unittest.TestCase):
pass
...
# interactive.py
from garden import trim, bunch, Foo
f = trim(Foo())
bunch(f, Foo())
...
# my_garden.py
import garden
from garden import powertools
class _Cowboy(garden._Samurai):
def hit():
return powertools.promise() and powertools.random() or 0
class Foo(_Cowboy, garden.Foo):
pass
Теперь он становится немного интуитивным и самодокументирование, в контексте которого предполагается, что некоторые компоненты предназначены для использования, и идеально подходит для обозначения различных тестовых примеров, а также для простого подхода к тому, как тестовые модули сопоставляются с фактическими модулями, которые тестируются для пуристов.
Я часто считаю целесообразным применить этот подход к организации кода утилиты проекта. Довольно часто люди сразу бросаются и создают пакет utils
и в итоге получают 9 модулей, из которых 120 LOC, а остальные - два десятка LOC в лучшем случае. Я предпочитаю начать с этого и преобразовать его в пакет и создать модули только для тех зверей, которые их действительно заслуживают:
# utils.py
class socket(object):
@staticmethod
def check_if_port_available(port):
pass
@staticmethod
def get_free_port(port)
pass
class image(object):
@staticmethod
def to_rgb(image):
pass
@staticmethod
def to_cmyk(image):
pass
14 Области применения
[...]
Определить простая область, мы используем метод области действия внутри класса, передавая запрос, который мы хотели бы выполнить, когда вызывается эта область:class Article < ApplicationRecord scope :published, -> { where(published: true) } end
Это точно так же, как определение метода класса, и то, что вы используете, является вопросом личных предпочтений:
blockquote>class Article < ApplicationRecord def self.published where(published: true) end end
Так что
scope
в основном просто причудливый способ создания метода класса, который должен иметь определенное поведение (т.е. возвращать отношение ) и любой метод метода класса, который возвращает отношение, является областью действия.scope
раньше было чем-то особенным, но теперь они просто методы класса, и все методы класса копируются в отношения для поддержки цепочки.Нет способа узнать, является ли метод
Model.m
«реальной» областью действия, которая будет возвращать отношение или некоторый метод случайного класса, не выполняя его и не проверяя, что он возвращает, или вручную проверяя его исходный код. Методscopes
, к которому вы стремитесь, исчез и никогда не вернется.Вы можете попытаться занести в черный список каждый метод класса, который, как вы знаете, плох; так кроется ложь и безумие.
Единственный разумный вариант - вносить в белый список каждый классовый метод, который, как вы знаете, хорош и является тем, что вы хотите, чтобы пользователи могли вызывать. Затем вы должны отфильтровать массив
scopes
в контроллере и внутриAssignableLearningObjectives::Collector
. Я бы проверил в обоих местах, потому что у вас могут быть разные критерии для того, что разрешено, в зависимости от того, какая информация доступна и по какому пути вы проходите через код; Я полагаю, немного меньше СУХОГО, но эффективность и надежность не дружат.Вы можете применить белый список областей видимости в конструкторе
AssignableLearningObjectives::Collector
или вavailable_objectives
.
Если вы хотите что-то более красивое, чем:
scopes.each{ |scope| objectives = objectives.send(scope) } objectives
, тогда вы можете использовать
inject
:def available_objectives objectives = assignable_objectives.... scopes.inject(objectives) { |objectives, scope| objectives.send(scope) } end