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?

Author: Arslan Ali, 2013-01-26

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.

 625
Author: yagooar,
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

 382
Author: Aaditi Jain,
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ł.

  1. like this guy
  2. a ten

Niektóre powody:

  1. 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.
  2. 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.
  3. baza kodowa jest trudniejsza do nawigacji z tymi wszystkimi problemami wokół.
  4. Jesteś pewien, że wszyscy członkowie Twojego zespołu rozumieją to, co powinno zastąpić troskę?
Obawy to łatwy sposób, by strzelić sobie w nogę, bądź ostrożny z nimi.
 98
Author: Dr.Strangelove,
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
 56
Author: aminhotob,
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

 49
Author: Siva,
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
 7
Author: Sajjad Murtaza,
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