Jak korzystać z rails 4
Domyślny generator projektów Rails 4 tworzy teraz katalog "concerns" w obszarze controllers and models. Znalazłem kilka wyjaśnień dotyczących korzystania z routingu, ale nic o kontrolerach czy modelach.
Jestem całkiem pewien, że ma to związek z obecnym "trendem DCI" w społeczności i chciałbym spróbować.
Pytanie brzmi, jak mam korzystać z tej funkcji, czy jest jakaś konwencja, jak zdefiniować hierarchię nazw / klas w rozkaz, aby to zadziałało? Jak mogę uwzględnić problem w modelu lub kontrolerze?
6 answers
Więc odkryłem to sam. Jest to właściwie dość prosta, ale potężna koncepcja. Ma to związek z ponownym użyciem kodu, jak w poniższym przykładzie. Zasadniczo chodzi o to, aby wyodrębnić wspólne i / lub specyficzne dla kontekstu fragmenty kodu w celu oczyszczenia modeli i uniknięcia ich zbyt grubego i niechlujnego.
Jako przykład podam jeden dobrze znany wzór, wzór taggable:
# app/models/product.rb
class Product
include Taggable
...
end
# app/models/concerns/taggable.rb
# notice that the file name has to match the module name
# (applying Rails conventions for autoloading)
module Taggable
extend ActiveSupport::Concern
included do
has_many :taggings, as: :taggable
has_many :tags, through: :taggings
class_attribute :tag_limit
end
def tags_string
tags.map(&:name).join(', ')
end
def tags_string=(tag_string)
tag_names = tag_string.to_s.split(', ')
tag_names.each do |tag_name|
tags.build(name: tag_name)
end
end
# methods defined here are going to extend the class, not the instance of it
module ClassMethods
def tag_limit(value)
self.tag_limit_value = value
end
end
end
Więc po próbce produktu, można dodać Taggable do dowolnej klasy chcesz i podzielić się jego funkcjonalność.
To jest dość dobrze wyjaśnione przez DHH :
W Rails 4 zaprosimy programistów do korzystania z domyślne app / models/concerns I app / controllers / concerns katalogi które są automatycznie częścią ścieżki ładowania. Wraz z ActiveSupport:: Concern wrapper, wystarczy wsparcie, aby to lekki mechanizm faktoringowy połysk.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-17 06:34:58
Czytałem o używaniu model concerns do skórowania tłustych modeli, a także suszenia kodów modeli. Oto Wyjaśnienie z przykładami:
1) wysychanie kodów modeli
Rozważmy Model artykułu, Model zdarzenia i model komentarza. Artykuł lub wydarzenie ma wiele komentarzy. Komentarz należy do artykułu lub Wydarzenia.
Tradycyjnie modele mogą wyglądać tak:
Skomentuj Model:
class Comment < ActiveRecord::Base
belongs_to :commentable, polymorphic: true
end
Artykuł Model:
class Article < ActiveRecord::Base
has_many :comments, as: :commentable
def find_first_comment
comments.first(created_at DESC)
end
def self.least_commented
#return the article with least number of comments
end
end
Model Zdarzeń
class Event < ActiveRecord::Base
has_many :comments, as: :commentable
def find_first_comment
comments.first(created_at DESC)
end
def self.least_commented
#returns the event with least number of comments
end
end
Jak możemy zauważyć, istnieje znacząca część kodu wspólna zarówno dla zdarzenia, jak i artykułu. Wykorzystując obawy możemy wyodrębnić ten wspólny kod w osobnym module Komentowalnym.
Do tego utwórz komentarz.plik rb w app / models / concerns.
module Commentable
extend ActiveSupport::Concern
included do
has_many :comments, as: :commentable
end
# for the given article/event returns the first comment
def find_first_comment
comments.first(created_at DESC)
end
module ClassMethods
def least_commented
#returns the article/event which has the least number of comments
end
end
end
A teraz twoje modele wyglądają tak:
Skomentuj Model:
class Comment < ActiveRecord::Base
belongs_to :commentable, polymorphic: true
end
Model Artykułu:
class Article < ActiveRecord::Base
include Commentable
end
Model Zdarzenia:
class Event < ActiveRecord::Base
include Commentable
end
[[17]} 2) tłuszcz niszczący skórę Modelki.
Rozważmy model zdarzeń. Wydarzenie ma wielu uczestników i komentarzy.
Zazwyczaj model zdarzeń może wyglądać tak
class Event < ActiveRecord::Base
has_many :comments
has_many :attenders
def find_first_comment
# for the given article/event returns the first comment
end
def find_comments_with_word(word)
# for the given event returns an array of comments which contain the given word
end
def self.least_commented
# finds the event which has the least number of comments
end
def self.most_attended
# returns the event with most number of attendes
end
def has_attendee(attendee_id)
# returns true if the event has the mentioned attendee
end
end
Modele z wieloma skojarzeniami i poza tym mają tendencję do gromadzenia coraz większej ilości kodu i stają się niewykonalne. Obawy zapewniają sposób na skórowanie modułów tłuszczowych, dzięki czemu są bardziej modularne i łatwe do zrozumienia.
Powyższy model można zrefakturować za pomocą obaw jak poniżej:
Utwórz plik attendable.rb
i commentable.rb
W app / models/concerns / event folder
Rb
module Attendable
extend ActiveSupport::Concern
included do
has_many :attenders
end
def has_attender(attender_id)
# returns true if the event has the mentioned attendee
end
module ClassMethods
def most_attended
# returns the event with most number of attendes
end
end
end
Komentować.rb
module Commentable
extend ActiveSupport::Concern
included do
has_many :comments
end
def find_first_comment
# for the given article/event returns the first comment
end
def find_comments_with_word(word)
# for the given event returns an array of comments which contain the given word
end
module ClassMethods
def least_commented
# finds the event which has the least number of comments
end
end
end
A teraz używając obaw, twój model zdarzeń redukuje się do
class Event < ActiveRecord::Base
include Commentable
include Attendable
end
* podczas korzystania z obawy zaleca się, aby przejść do grupowania opartego na "domenie", a nie grupowania "technicznego". Grupowanie oparte na domenie jest takie jak "Komentowalne", "Photoable", "Attendable". Grupa Techniczna oznacza "ValidationMethods", "FinderMethods" itp
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-13 04:37:44
Warto wspomnieć, że używanie obaw przez wielu jest uważane za zły pomysł.
Niektóre powody:
- Za kulisami dzieje się jakaś czarna magia - troska to metoda patching
include
, istnieje cały system obsługi zależności - zbyt wiele złożoności jak na coś, co jest trywialnym, starym, dobrym wzorcem Ruby mixin.
Twoje zajęcia są nie mniej suche. Jeśli wrzucisz 50 publicznych metod w różne moduły i dołącz je, twoja klasa nadal ma 50 publicznych metod, po prostu ukrywasz ten zapach kodu, jakby wkładasz śmieci do szuflad.
- baza kodowa jest trudniejsza do nawigacji z tymi wszystkimi problemami wokół. Jesteś pewien, że wszyscy członkowie Twojego zespołu rozumieją to, co powinno zastąpić troskę?
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-15 03:44:33
Ten post pomógł mi zrozumieć obawy.
# app/models/trader.rb
class Trader
include Shared::Schedule
end
# app/models/concerns/shared/schedule.rb
module Shared::Schedule
extend ActiveSupport::Concern
...
end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-10 08:32:48
Wydawało mi się, że większość przykładów pokazuje moc module
, a nie jak ActiveSupport::Concern
dodaje wartość module
.
Przykład 1: więcej czytelnych modułów.
Więc bez obaw, jak będzie typowy module
.
module M
def self.included(base)
base.extend ClassMethods
base.class_eval do
scope :disabled, -> { where(disabled: true) }
end
end
def instance_method
...
end
module ClassMethods
...
end
end
Po refaktoryzacji z ActiveSupport::Concern
.
require 'active_support/concern'
module M
extend ActiveSupport::Concern
included do
scope :disabled, -> { where(disabled: true) }
end
class_methods do
...
end
def instance_method
...
end
end
Widzisz, że metody instancji, metody klas i dołączony Blok są mniej brudne. Obawy wstrzykną je odpowiednio dla Ciebie. To jedna z zalet używania ActiveSupport::Concern
.
Przykład 2: obsługa zależności modułów z gracją.
module Foo
def self.included(base)
base.class_eval do
def self.method_injected_by_foo_to_host_klass
...
end
end
end
end
module Bar
def self.included(base)
base.method_injected_by_foo_to_host_klass
end
end
class Host
include Foo # We need to include this dependency for Bar
include Bar # Bar is the module that Host really needs
end
W tym przykładzie Bar
jest moduł, który Host
naprawdę potrzebuje. Ale ponieważ Bar
ma zależność od Foo
Klasa Host
musi include Foo
(ale czekaj dlaczego Host
chce wiedzieć o Foo
? Czy można tego uniknąć?).
Więc Bar
dodaje zależności wszędzie tam, gdzie się uda. I kolejność włączenia również ma tu znaczenie. to dodaje wiele złożoności / zależności do ogromnego kodu baza.
Po refaktoryzacji z ActiveSupport::Concern
require 'active_support/concern'
module Foo
extend ActiveSupport::Concern
included do
def self.method_injected_by_foo_to_host_klass
...
end
end
end
module Bar
extend ActiveSupport::Concern
include Foo
included do
self.method_injected_by_foo_to_host_klass
end
end
class Host
include Bar # It works, now Bar takes care of its dependencies
end
Teraz wygląda prosto.
Jeśli myślisz, dlaczego nie możemy dodać Foo
zależności w samym module Bar
? To nie zadziała, ponieważ {[22] } muszą być wstrzykiwane w klasę, która zawiera Bar
, a nie w samym module Bar
.
Źródło: Rails ActiveSupport:: Concern
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-03-28 23:09:45
W trosce tworzy plik nazwa_pliku.rb
Na przykład chcę w mojej aplikacji, gdzie atrybut create_by exist update tam wartość o 1 i 0 dla updated_by
module TestConcern
extend ActiveSupport::Concern
def checkattributes
if self.has_attribute?(:created_by)
self.update_attributes(created_by: 1)
end
if self.has_attribute?(:updated_by)
self.update_attributes(updated_by: 0)
end
end
end
Jeśli chcesz przekazać argumenty w akcji
included do
before_action only: [:create] do
blaablaa(options)
end
end
Następnie dołącz w swoim modelu tak:
class Role < ActiveRecord::Base
include TestConcern
end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-08-12 14:33:39