如何设置 "global" 可以在 Rails 中的控制器和模型中访问的变量
How can I set "global" variables that can be accessed in controllers and models in Rails
我有一个 table 设置了条目。我想在我的模型和控制器中将这些条目作为变量访问,而无需每次都查询数据库来设置这些变量。
我可以通过为我的模型和控制器创建副本 "concerns" 来让它工作。我还可以在我的 ApplicationController 中设置全局变量。或者我可以在我需要它们的每个地方初始化它们。设置和访问可在控制器和模型中访问的全局变量的正确 rails 方法是什么?
class ItemType
has_many :items
end
class Item
belongs_to :item_type
belongs_to :foo
end
class Foo
has_many :items
def build_item
bar_item_type = ItemType.find_by(:name => "bar")
self.items.build(
:foo_id => self.id,
:item_type_id => bar_item_type.id
)
end
end
class ItemsController
def update
bar_item_type = ItemType.find_by(:name => "bar")
@item.update(:item_type_id => bar_item_type.id)
end
end
在示例中,您可以看到我在 Foo 模型和 ItemsController 中都声明了 bar_item_type
变量。我想通过能够为我的 rails 项目创建和访问该变量一次而不是必须在所有地方进行相同的数据库调用来干燥我的代码库。
我反对这样的 hard-coded 或 DB state-dependent 代码。如果您必须这样做,这里是我所知道的方法之一:
# models
class ItemType < ActiveRecord::Base
has_many :items
# caches the value after first call
def self.with_bar
@@with_bar ||= transaction { find_or_create_by(name: "bar") }
end
def self.with_bar_id
with_bar.id
end
end
class Item < ActiveRecord::Base
belongs_to :item_type
belongs_to :foo
scope :with_bar_types, -> { where(item_type_id: ItemType.with_bar_id) }
end
class Foo < ActiveRecord::Base
has_many :items
# automatically sets the foo_id, no need to mention explicitly
# the chained with_bar_types automatically sets the item_type_id to ItemType.with_bar_id
def build_item
self.items.with_bar_types.new
end
end
# Controller
class ItemsController
def update
@item.update(item_type_id: ItemType.with_bar_id)
end
end
如果您必须使用常量,有几种方法可以做到。但是您必须考虑到您正在实例化一个 ActiveRecord 模型对象,它依赖于数据库中存在的数据。不推荐这样做,因为您现在拥有依赖于数据库中存在的数据的模型和控制器逻辑。如果您已经播种了数据库并且它不会改变,这可能没问题。
class ItemType
BAR_TYPE ||= where(:name => "bar").limit(1).first
has_many :items
end
现在,无论何时你需要这个对象,你都可以这样称呼它:
bar_item_type = ItemType::BAR_TYPE
我有一个 table 设置了条目。我想在我的模型和控制器中将这些条目作为变量访问,而无需每次都查询数据库来设置这些变量。
我可以通过为我的模型和控制器创建副本 "concerns" 来让它工作。我还可以在我的 ApplicationController 中设置全局变量。或者我可以在我需要它们的每个地方初始化它们。设置和访问可在控制器和模型中访问的全局变量的正确 rails 方法是什么?
class ItemType
has_many :items
end
class Item
belongs_to :item_type
belongs_to :foo
end
class Foo
has_many :items
def build_item
bar_item_type = ItemType.find_by(:name => "bar")
self.items.build(
:foo_id => self.id,
:item_type_id => bar_item_type.id
)
end
end
class ItemsController
def update
bar_item_type = ItemType.find_by(:name => "bar")
@item.update(:item_type_id => bar_item_type.id)
end
end
在示例中,您可以看到我在 Foo 模型和 ItemsController 中都声明了 bar_item_type
变量。我想通过能够为我的 rails 项目创建和访问该变量一次而不是必须在所有地方进行相同的数据库调用来干燥我的代码库。
我反对这样的 hard-coded 或 DB state-dependent 代码。如果您必须这样做,这里是我所知道的方法之一:
# models
class ItemType < ActiveRecord::Base
has_many :items
# caches the value after first call
def self.with_bar
@@with_bar ||= transaction { find_or_create_by(name: "bar") }
end
def self.with_bar_id
with_bar.id
end
end
class Item < ActiveRecord::Base
belongs_to :item_type
belongs_to :foo
scope :with_bar_types, -> { where(item_type_id: ItemType.with_bar_id) }
end
class Foo < ActiveRecord::Base
has_many :items
# automatically sets the foo_id, no need to mention explicitly
# the chained with_bar_types automatically sets the item_type_id to ItemType.with_bar_id
def build_item
self.items.with_bar_types.new
end
end
# Controller
class ItemsController
def update
@item.update(item_type_id: ItemType.with_bar_id)
end
end
如果您必须使用常量,有几种方法可以做到。但是您必须考虑到您正在实例化一个 ActiveRecord 模型对象,它依赖于数据库中存在的数据。不推荐这样做,因为您现在拥有依赖于数据库中存在的数据的模型和控制器逻辑。如果您已经播种了数据库并且它不会改变,这可能没问题。
class ItemType
BAR_TYPE ||= where(:name => "bar").limit(1).first
has_many :items
end
现在,无论何时你需要这个对象,你都可以这样称呼它:
bar_item_type = ItemType::BAR_TYPE