Rails에서 메타 프로그래밍(블랙 매직)이라 불리는 send 방법을 활용해봤어요
개시하다
내가 이 기사를 쓰려는 목적은 센스 방법을 활용하지 않은 인상을 가진 사람에게 Rails에서 이렇게 사용하는 장면이 있다는 것을 소개하기 위해서다.
먼저send방법을 사용하는 것이 가장 좋은지 아닌지...웃다 웃다
원 프로그래밍은?
우선 원 프로그램 설계의 의미를 간단하게 소개하다.
Rails 자습서에서 이렇게 설명했습니다.
한마디로 원 프로그래밍은'프로그래밍으로 프로그래밍'이다.메타 프로그램 설계는 루비가 가지고 있는 매우 강력한 기능이다. 라일스의 언뜻 보면 마법 같은 기능('흑마술'이라고도 부른다)은 대부분 루비의 메타 프로그램 설계를 통해 이루어진다.
프로그램으로 프로그램을 만듭니까?이 설명도 살짝만 읽어도 잘 모르겠네요, 웃음.
Rails 튜토리얼에서 실제로는 send 방법을 이용하여 메타 프로그램을 만들었는데 그걸 보면 더 인상적일 수 있어요.
※ 이후 실제 사례로 설명
send 방법이 뭐예요?
루비에게 센드라는 방법이 있어.
간단한 예로 어떻게 사용하는지 설명하다.
예를 들어 upcase 문자열을 대문자로 출력하는 방법을 예로 들자.
string = "ruby" #=> "ruby"
string.upcase #=> "RUBY"
string.send(:upcase) #=> "RUBY"
string.send("upcase") #=> "RUBY"
이렇게 send 방법의 매개 변수를 호출하고자 하는 방법 이름의 기호나 문자열을 전달하면 일반적으로 방법의 호출이 발생한다.그럼 다음에 파라미터가 있는 방법을 사용하고 싶을 때 어떻게 해야 하나요? split 방법의 예를 들어보세요.
Rails 튜토리얼에서는 여기까지 설명하지 않았지만 의외로 간단했다.
split 방법은 문자열 등을 매개 변수에 건네주고 나누어 배열하는 것입니다.
string = "aaaaaxbbbbbxccccc" #=> "aaaaaxbbbbbxccccc"
string.split("x") #=> ["aaaaa", "bbbbb", "ccccc"]
string.send(:split, "x") #=> ["aaaaa", "bbbbb", "ccccc"]
string.send("split", "x") #=> ["aaaaa", "bbbbb", "ccccc"]
매개 변수를 방법에 전달하려면send 방법의 두 번째 매개 변수 다음에 전달합니다.Rails send 사용 방법
그럼 본론으로 들어가겠습니다.
Rails에서 EC 사이트를 제작할 때 3개의 모델(Artist, Label,Genre)의 데이터를 한눈에 볼 수 있는view는 기본적으로 같기 때문에 나는 그것을 국부화했다.
먼저 간단한 모형을 놓고 어떤 배치인지 보자.(상당히 지저분하니 신경 쓰지 마시오 웃음)
이동
응, 이것은 단지 표시된 데이터일 뿐이야.이걸 국부화하지 않고 뭘 해요?그래서 국부화를 진행했다.
컨트롤러
app/controllers/artists_controller.rb
# 中略
def index
@artists = Artist.page(params[:page])
@artist = Artist.new
end
# 中略
app/controllers/genres_controller.rb# 中略
def index
@genres = Genre.page(params[:page])
@genre = Genre.new
end
# 中略
app/controllers/labels_controller.rb# 中略
def index
@labels = Label.page(params[:page])
@label = Label.new
end
# 中略
뷰
app/views/artists/index.html.erb
<h2>アーティスト一覧</h2>
<%= render 'layouts/object_list', objects: @artists, object: @artist %>
app/views/genres/index.html.erb<h2>ジャンル一覧</h2>
<%= render 'layouts/object_list', objects: @genres, object: @genre %>
app/views/labels/index.html.erb<h2>レーベル一覧</h2>
<%= render 'layouts/object_list', objects: @labels, object: @label %>
app/views/layouts/_object_list.html.erb<div class="row">
<div class="col-sm-5">
<%= render 'layouts/error', object: object %>
<%= form_with model: object, local: true do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.submit "登録" %>
<% end %>
</div>
<div class="col-sm-7">
<div class="index-wrapper">
<% object_name = object.class.to_s.downcase # それぞれのオブジェクトのクラス名を変数に代入 %>
<% objects.each do |data| %>
<% edit_path = self.send("edit_#{object_name}_path", data) ### ここで使用!!### %>
<% destroy_path = self.send("#{object_name}_path", data) ### ここで使用!!### %>
<%= data.name %>
<%= link_to "編集", edit_path %>
<%= link_to "削除", destroy_path, method: :delete, data: { "confirm" => "本当に削除しますか?" } %>
<% end %>
</div>
<%= paginate objects, class: "pagination" %>
</div>
</div>
각자index.html.erb
로 작성한 부분 템플릿의 호출은 문제없습니다.(모르시는 분들은 구글로 보내주세요)_object_list.html.erb
의 코드로 이번 주제의send 방법과 관련된 코드만 설명합니다.해설
먼저 각 대상의 클래스 이름 (모든 소문자) 을 변수에 대입합니다.
나중에 왜 그런지 알게 될 거야.
<% object_name = object.class.to_s.downcase # それぞれのオブジェクトのクラス名を変数に代入 %>
하나하나 설명하면.class
- 호출된 대상의 클래스를 가져옵니다..to_s
- 문자열로 변환.downcase
- 문자열을 소문자로 변환그래서 정리를 해볼게요.
# 渡ってきた元のインスタンス変数 → object_nameに入る文字列
@artist → "artist"
@genre → "genre"
@label → "label"
.다음은 주제의send 방법의 코드입니다.
<% edit_path = self.send("edit_#{object_name}_path", data) ### ここで使用!!### %>
<% destroy_path = self.send("#{object_name}_path", data) ### ここで使用!!### %>
여기서 하고 싶은 것은 edit_path
,destroy_path
각각 each 방법에 따라 추출한 대상 + 국부 호출을 통해 전달된 대상의 종류(artist나genre 또는 label) 동적 생성 경로를 대입하는 것이다.즉, 동적 결정 호출 방법이다.이것은 루비의 메타 프로그램이다.
send 방법의 집행 결과는 다음과 같다.
# artist
edit_path = edit_artist_path(data)
destroy_path = artist_path(data)
# genre
edit_path = edit_genre_path(data)
destroy_path = genre_path(data)
# label
edit_path = edit_label_path(data)
destroy_path = label_path(data)
여기 있다, 응?self.
가 뭐예요?그나저나 레일스~_path
가 방법인가요?방법은 ***.メソッド
의 느낌으로 어떤 대상에게 호출되는 것이 아닌가?그렇게 생각할지도 몰라요.특히 다른 언어(JavaScript, PHP 등)를 처음 배우는 사람은 함수 아닌가?그렇게 생각할 수도 있어, 이게 방법이야!!
아니면 루비에 함수가 없거나.
이 말을 하면 길어지니까 조금 생략하겠지만 루비 전부 대상
~_path
도 모종의 대상인 방법입니다.그리고 자기 방법을 쓸 때.~_path
의 느낌으로 쓰다.그러나 이것은 생략self.メソッド
할 수 있고 방법명만 사용하면 호출할 수 있다.즉
self.
는 평소 생략~_path
하고 실제로self.
도 불러낼 수 있다는 것이다.그럼 send 방법을 사용할 때도 생략
self.~_path
할 수 있습니까?그렇다니까.위에서 소개한 코드는 좀 더 짧게 할 수 있다.
<% edit_path = send("edit_#{object_name}_path", data) ### ここで使用!!### %>
<% destroy_path = send("#{object_name}_path", data) ### ここで使用!!### %>
이번에는 설명하기 편하게 처음엔 가산self.
상태였는데 짧게 쓰면 과를 완성한 것이다.총결산
실제로send방법을 사용하지 않아도 더욱 간단하게 진행할 수 있다.
prefix
self.
를 사용하지 않고 상대 경로를 직접 쓰면 상대 경로에 변수를 넣는 것이 그리 어렵지 않겠죠.하지만 난 그저 흑마술이라는 방법을 사용하고 싶을 뿐이야.웃다 웃다
여러분도 이루기 어려운 게임 감각을 선택해 보세요. 재미있을 거예요.
Reference
이 문제에 관하여(Rails에서 메타 프로그래밍(블랙 매직)이라 불리는 send 방법을 활용해봤어요), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/Yuki_Nakagami/items/21319c10e833cd0efc12텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)