#كيف تنشئ رسائل محفوظة باستخدام Rails
سنتحدّث في هذه الحلقة عن قوالب الرسائل (message templates) في تطبيقات إطار العمل "ريلز"، وهي من الميزات التي أضافها موقع Github مؤخرًا، حيث أن معظم المشاريع في Github تستخدم ردودا مكررة أو شائعة في المجتمع الخاص بها، وعليه فهي تحتاج إلى كتابتها في كل مرّة. ولذلك قام موقع Github بإضافة "حفظ تعليق" والذي سيصبح جاهزًا في المستقبل بدون الحاجة إلى كتابته يدويًا، مما يوفّر الوقت على المطوّر والتركيز على ما يشغله والتسهيل من مهمّة إدارة المشروع.
سنبدأ مثالنا مع تطبيق "ريلز" مجهّز بنظام تعليقات، وما سنقوم به هو إضافة زر يسمح لنا بحفظ "الرد" وذلك لاستخدامه لاحقًا ومتى ما نشاء.
سنبدأ بإنشاء model ربما بالاسم "الردود المحفوظة" أو يمكننا تسميته "الرسائل المحفوظة" (saved_messages) وله عنوان title
و body
، أما العنوان فسيكون لغرض عرضه في القائمة المنسدلة بدلًا من عرض كامل نص الرسالة المحفوظة والذي قد يكون طويل وبعدّة فقرات.
class CreateSavedMessages < ActiveRecord::Migration[5.0]
def change
create_table :saved_messages do |t|
t.string :title
t.text :body
t.timestamps
end
end
end
سنبدأ بإضافة رابط إلى "إضافة رسالة محفوظة":
<%= link_to “Add a saved message”, new_saved_message_path %>
ومن ثم سنستخدم الدالة select_tag
التي يوفرها إطار العمل Rails وذلك لإنشاء قائمة اختيار منسدلة:
الجدير بالذكر أنه من الممكن جدًا الاستعلام عن هذه الرسائل المحفوظة على مستوى طبقة العرض (view) من دون الاستعانة بمُتحكّم (controller).
بالتوجّه إلى التوثيق الخاص بالدالة select_tag
سيكون من الواضح لنا ما هي المعطيات (arguments) اللازمة لتمريرها لهذه الدالة.
#select_tag(name, option_tag = nil, options = {})
<%= select_tag “saved_messages”, options_for_select(SavedMessage.all.map{ |sm| [sm.title, sm.id, data: {body: sm.body}] }) %>
أما الدالة options_for_select
تتطلب مصفوفة كمُعطى لها وهذا ما قمنا به، حيث قمنا بتمرير مصفوفة تحتوي على عنوان الرسالة المحفوظة والمعرف الخاص بها ونص الرسالة.
يجب أيضًا إضافة خيار افتراضي وذلك كأوّل اختيار ويمكن ذلك عن طريق الخيار prompt
وذلك كما في التالي:
<%= select_tag “saved_messages”, options_for_select(SavedMessage.all.map{ |sm| [sm.title, sm.id, data: {body: sm.body}] }), prompt: “اختر رسالة محفوظة” %>
أما الآن علينا استخدام جافا سكريبت وذلك لعرض متن الرسالة المحفوظة داخل صندوق الرد وذلك بعد اختيارها من القائمة المنسدلة.
سنستخدم CoffeScript في كتابة جافا سكريبت واستخدام الخاصيّة data-behavior وذلك في إنشاء صنف (class) وذلك لتغليف النموذج (form). ويعود السبب في اختيار هذه الأسلوب لما يقدّمه من سهولة ومرونة في التعامل مع صفحة الويب. ففي حال اعتمادنا على أصناف CSS أو ids سنواجه بعض المشاكل مع عناصر الصفحة. فعلى فرض كان لدينا أكثر من صندوق إدخال وأردنا إدراج إحدى الرسائل المحفوظة فإما أن تندرج هذه الرسالة في جميع صناديق الإدخال أو سيتمّ إدراج أحد الرسائل دون الأخرى، بمعنى آخر سيكون هناك تعارض بين الرسائل.
أما مع الصنف ومع الاستعانة بالخاصيّة (attribute) data-behavior
سيكون من السهل حصر الأمور في نطاق محدد –في النموذج في هذه الحالة-والتعامل معها بدون أن تتداخل الأمور مع بعضها البعض وذلك باستخدام صنف محدد لهذا الغرض. سنقوم أوّلًا بإضافة الخواص اللازمة إلى النموذج (form):
#app/views/comment/_form.html.erb
<%= form_for(comment, html: {data: {behavior: "has-saved-messages"}}) do |f| %>
<% if comment.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(comment.errors.count, "error") %> prohibited this comment from being saved:</h2>
<ul>
<% comment.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<%= link_to "Add a saved message", new_saved_message_path %>
<%= select_tag "saved_messages", options_for_select(SavedMessage.all.map{ |sm| [sm.title, sm.id, data: {body: sm.body}] }), prompt: "Select a saved message", data: {behavior: "saved-message-select"} %>
<div class="field">
<%= f.label :body %>
<%= f.text_area :body, data: {behavior: "comment-body"}%>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
أما ملفّ الجافا سكريبت الموافق سيكون على الشكل التالي:
#app/assets/javascript/saved_messages.coffee
class HasSavedMessage
constructor (elem) ->
@element = $(elem)
@setCallbacks()
setCallbacks: ->
@element.find(“[data-behaviar=’saved-message-select’]”).on “change”, @handleChange
handleChange: (e) =>
saved_message_text = @element.find(“[data-behavior=’saved-message-select’]).find(“:select”).data(“body”)
comment_body = @element.find(“[data-behavior=’comment-body’]”)
comment_body.append(“#{saved_message_text}\n”)
jQuery ->
$.map $(“[data-behavior=’has-saved-messages’]”), (elem) ->
new HasSavedMessage(elem)
في الكود السابق قمنا بتشييد الصنف أوّلا باستخدام الدالة constructor
أما الدالة setCallbacks
ستبحث على الخاصّيّة data-behavior
ذات القيمة saved-message-select
وعند حدث التغيير ”change”
ستطبق الخاصّيّة handleChange
والتي سنستخرج من خلالها نص الرسالة المختارة من القائمة المنسدلة وإدراجها ضمن صندوق الحوار (text input)
كما قمنا بإضافة \n
وذلك لكيلا يتمّ خلط الرسائل المختارة مع بعضها في حال اختيار أكثر من رسالة محفوظة لإدراجها في نفس صندوق الحوار.
إلى هنا نكون قد وصلنا إلى نهاية الحلقة إن كنت مهتم أكثر بهذا الموضوع يمكنك ترك تعليق وسأحاول الكتابة عنه في الحلقات القادمة.