সেভ কলব্যাকের পরে কারাগুলিতে কোন বৈশিষ্ট্যগুলি পরিবর্তন করা হয়েছিল তা নির্ধারণ করুন?


153

আমি যদি মডেলটির প্রকাশিত বৈশিষ্ট্যটি মিথ্যা থেকে সত্যে পরিবর্তিত করা হয় তবেই একটি বিজ্ঞপ্তি প্রেরণের জন্য আমি আমার মডেল পর্যবেক্ষকের একটি আফটার_সেভ কলব্যাক সেট করছি । যেহেতু পরিবর্তিত হিসাবে পদ্ধতি ? মডেলটি সংরক্ষণের আগে কেবল কার্যকর, আমি বর্তমানে (এবং ব্যর্থ) যেভাবে চেষ্টা করার চেষ্টা করছি তা নিম্নরূপ:

def before_save(blog)
  @og_published = blog.published?
end

def after_save(blog)
  if @og_published == false and blog.published? == true
    Notification.send(...)
  end
end

মডেল পর্যবেক্ষক কলব্যাকগুলি ব্যবহার করে (যাতে আমার নিয়ামক কোডটি কলুষিত না করা হয়) ব্যবহার করার পক্ষে কারও কাছে কি এই হ্যান্ডেল করার সর্বোত্তম উপায় হিসাবে কোনও পরামর্শ আছে?

উত্তর:


182

রেলগুলি 5.1+

ব্যবহার saved_change_to_published?:

class SomeModel < ActiveRecord::Base
  after_update :send_notification_after_change

  def send_notification_after_change
    Notification.send(…) if (saved_change_to_published? && self.published == true)
  end

end

বা আপনি যদি পছন্দ করেন, saved_change_to_attribute?(:published) ,।

রেলগুলি 3-5

সতর্কতা

এই পদ্ধতিটি 5.3 কিলের মাধ্যমে কাজ করে (তবে 5.1-এ হ্রাস পেয়েছে এবং 5.2-এ পরিবর্তিত পরিবর্তন রয়েছে)। আপনি এই টান অনুরোধ পরিবর্তন সম্পর্কে পড়তে পারেন ।

আপনার after_updateফিল্টারটিতে মডেলটিতে আপনি অ্যাকসেসর ব্যবহার করতে পারেন _changed?। উদাহরণস্বরূপ:

class SomeModel < ActiveRecord::Base
  after_update :send_notification_after_change

  def send_notification_after_change
    Notification.send(...) if (self.published_changed? && self.published == true)
  end

end

এটা ঠিক কাজ করে।


আমি উপরে যা বলেছি তা ভুলে যান - এটি রেল ২.০.৫ এ কাজ করে না। সুতরাং রেলস 3-এ একটি দরকারী সংযোজন
স্টিফেনার

4
আমার মনে হয় আফটার আপডেটের পরে এখন অবনতি হয়? যাইহোক, আমি এটি পরে-পরে সংরক্ষণের হুকটিতে চেষ্টা করেছি এবং দেখে মনে হচ্ছে এটি ঠিক আছে। (পরিবর্তনগুলি () হ্যাশ এখনও কোনও আফটার_সেভের মধ্যে এখনও দৃশ্যমানভাবে পুনরায় সেট করা হয়নি) apparent
টাইলার রিক

3
আমাকে এই লাইনটি মডেল.আরবি ফাইলে অন্তর্ভুক্ত করতে হয়েছিল। অ্যাক্টিভোডেল :: ডার্টি
কোডারভিশাল 7'16

13
রেলের পরবর্তী সংস্করণগুলিতে আপনি after_updateকলের সাথে শর্ত যুক্ত করতে পারেন :after_update :send_notification_after_change, if: -> { published_changed? }
কোয়েন।

11
রেল 5.2 তে কিছু এপিআই পরিবর্তন হবে changes কলব্যাক চলাকালীন আপনাকে করতে saved_change_to_published?বা saved_change_to_publishedপরিবর্তনটি আনতে হবে
alopez02

183

যারা কেবল after_saveকলব্যাকের মাধ্যমে করা পরিবর্তনগুলি জানতে চান তাদের জন্য :

5.1 এবং তার বেশি রেল

model.saved_changes

রেল <5.1

model.previous_changes

আরও দেখুন: http://api.rubyonrails.org/class/ActiveModel/Dirty.html# মেমোডিক- আই- স্পিরিপ_ভেন্চ


2
এটি পুরোপুরি কার্যকর হয় যখন আপনি মডেল কলব্যাকগুলি ব্যবহার করতে চান না এবং আরও কার্যকারিতা চালিয়ে যাওয়ার আগে ঘটতে বৈধ সংরক্ষণের প্রয়োজন হয়।
ডেভ রবার্টসন

এটি নিখুঁত! এই পোস্ট করার জন্য আপনাকে ধন্যবাদ।
জুনিক্স

অসাধারণ! এর জন্য ধন্যবাদ.
ড্যানিয়েল লোগান

4
কেবল স্পষ্ট করে বলার জন্য: আমার পরীক্ষাগুলিতে (রেল 4), আপনি যদি after_saveকলব্যাক ব্যবহার করেন , self.changed?হয় trueএবং self.attribute_name_changed?হয় trueতবে তবে self.previous_changesএকটি খালি হ্যাশ ফেরত দেয়।
Sandre89

9
এটি কারা 5.1 + এ অবচয় করা হয়েছে। ব্যবহারের saved_changesমধ্যে after_saveপরিবর্তে callbacks
rico_mac

71

এটি পরে যে কারও কাছে দেখার পরে, বর্তমানে এটি গুগলে শীর্ষে রয়েছে: এটি উল্লেখ করার মতো যে, এই আচরণটি রেল 5.2-এ পরিবর্তিত হবে এবং অ্যাক্টিভমডেল হিসাবে :: নষ্ট কিছুটা পরিবর্তন হয়েছে ।

আমি কি পরিবর্তন করব?

আপনি যদি কল attribute_changed?- after_*ব্যাকগুলিতে পদ্ধতি ব্যবহার করেন তবে আপনি একটি সতর্কতা দেখতে পাবেন:

প্রসারণ সতর্কতা: attribute_changed?কলব্যাকের পরের অভ্যন্তরের আচরণটি রেলের পরবর্তী সংস্করণে পরিবর্তিত হবে। নতুন রিটার্ন মান saveপ্রত্যাবর্তনের পরে পদ্ধতিটি কল করার আচরণকে প্রতিফলিত করবে (যেমন এখন এটি কী দেয় তার বিপরীতে)। বর্তমান আচরণ বজায় রাখতে saved_change_to_attribute?পরিবর্তে ব্যবহার করুন। (/_প্যাটএইচএলএক্স / অ্যাপ্লিকেশন / মডেলস / ইউজার.আরবি 15 তে কিছু_ক্যালব্যাক থেকে কল করা)

যেমনটি উল্লেখ করা হয়েছে, আপনি সহজেই ফাংশনটি প্রতিস্থাপনের মাধ্যমে এটি ঠিক করতে পারেন saved_change_to_attribute?। উদাহরণস্বরূপ, name_changed?হয়ে যায়saved_change_to_name?

তেমনিভাবে, আপনি যদি পূর্বের attribute_changeমানগুলি পেতে ব্যবহার করেন তবে এটিও পরিবর্তিত হয় এবং নিম্নলিখিতটি ছুঁড়ে দেয়:

প্রসারণ সতর্কতা: attribute_changeকলব্যাকের পরের অভ্যন্তরের আচরণটি রেলের পরবর্তী সংস্করণে পরিবর্তিত হবে। নতুন রিটার্ন মান saveপ্রত্যাবর্তনের পরে পদ্ধতিটি কল করার আচরণকে প্রতিফলিত করবে (যেমন এখন এটি কী দেয় তার বিপরীতে)। বর্তমান আচরণ বজায় রাখতে saved_change_to_attributeপরিবর্তে ব্যবহার করুন। (/_প্যাটএইচএলএক্স / অ্যাপ্লিকেশন / মডেলস / ইউজার.আরবি:20 তে কিছু_ক্যালব্যাক থেকে কল করা হয়েছে)

আবার, যেমন এটি উল্লেখ করা হয়েছে, পদ্ধতিটি নাম পরিবর্তন করে saved_change_to_attributeযার সাথে ফিরে আসে ["old", "new"]। বা ব্যবহার করুন saved_changes, যা সমস্ত পরিবর্তনগুলি ফিরিয়ে দেয় এবং এগুলি হিসাবে ব্যবহার করা যেতে পারে saved_changes['attribute']


2
নোট করুন এই সহায়ক প্রতিক্রিয়ার মধ্যে attribute_wasপদ্ধতির অবমূল্যায়নের জন্য কাজের ক্ষেত্রও রয়েছে : saved_change_to_attributeপরিবর্তে ব্যবহার করুন।
জো এটজবার্গার

47

আপনি যদি এর before_saveপরিবর্তে after_saveএটি করতে পারেন তবে আপনি এটি ব্যবহার করতে সক্ষম হবেন:

self.changed

এটি এই রেকর্ডে সমস্ত পরিবর্তিত কলামের একটি অ্যারে প্রদান করে।

আপনি এটি ব্যবহার করতে পারেন:

self.changes

যা কলামগুলির একটি হ্যাশ প্রদান করে যা পরিবর্তিত হয়েছিল এবং ফলাফলগুলির আগে এবং পরে অ্যারে হিসাবে


8
এগুলি ব্যতীত after_কলব্যাকে কাজ করে না , যা আসলে প্রশ্নটি ছিল। নীচে jacek-głodek এর উত্তরটি সঠিক।
জাজ

এটি সাফ করার জন্য উত্তরটি আপডেট করুন এটি কেবল প্রযোজ্যbefore_save
মাহেমফ

1
এটি কোন রেলের সংস্করণ? 4 রেলগুলিতে, কলব্যাকগুলি self.changedব্যবহার করা যেতে পারে after_save
Sandre89

দুর্দান্ত কাজ! আরও লক্ষণীয়, ফলাফলটি self.changedএকটি স্ট্রিংগুলির অ্যারে! (প্রতীক নয়!)["attr_name", "other_attr_name"]
লুক্স

8

"নির্বাচিত" উত্তরটি আমার পক্ষে কার্যকর হয়নি। আমি কাউচরেস্ট :: মডেল (অ্যাক্টিভ মডেলের উপর ভিত্তি করে) এর সাথে রেল ৩.১ ব্যবহার করছি। হুকের _changed?পরিবর্তিত বৈশিষ্ট্যের জন্য পদ্ধতিগুলি কেবল after_updateহুকের মধ্যে ফিরে আসে না before_update। আমি (নতুন?) around_updateহুক ব্যবহার করে এটি কাজ করতে সক্ষম হয়েছি :

class SomeModel < ActiveRecord::Base
  around_update :send_notification_after_change

  def send_notification_after_change
    should_send_it = self.published_changed? && self.published == true

    yield

    Notification.send(...) if should_send_it
  end

end

1
নির্বাচিত উত্তরটি আমার পক্ষেও কার্যকর হয়নি, তবে এটি কাজ করে। ধন্যবাদ! আমি অ্যাক্টিভেকর্ড 3.2.16 ব্যবহার করছি।
বেন লি

5

আপনি এর after_updateমতো একটি শর্ত যুক্ত করতে পারেন:

class SomeModel < ActiveRecord::Base
  after_update :send_notification, if: :published_changed?

  ...
end

send_notificationপদ্ধতিতে নিজেই কোনও শর্ত যুক্ত করার দরকার নেই ।


-17

আপনি কেবল এমন একজন অ্যাকসেসর যুক্ত করুন যিনি আপনার পরিবর্তনগুলি সংজ্ঞায়িত করেন

class Post < AR::Base
  attr_reader :what_changed

  before_filter :what_changed?

  def what_changed?
    @what_changed = changes || []
  end

  after_filter :action_on_changes

  def action_on_changes
    @what_changed.each do |change|
      p change
    end
  end
end

এটি খুব খারাপ অভ্যাস, এমনকি এটি বিবেচনা করবেন না।
নুনো সিলভা
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.