12

I have a callback of a model that needs to create a dependent object based on another field entered in the form. But params is undefined in the callback method. Is there another way to access it? What's the proper way to pass a callback method parameters from a form?

class User < ActiveRecord::Base
  attr_accessible :name
  has_many :enrollments

  after_create :create_enrollment_log
  private
  def create_enrollment_log
    enrollments.create!(status: 'signed up', started: params[:sign_up_date])
  end
end
at.
  • 50,922
  • 104
  • 292
  • 461

2 Answers2

8

params are not accessible in models, even if you pass them as a parameter then it would be consider as bad practice and might also be dangerous.

What you can do is to create virtual attribute and use it in your model.

class User < ActiveRecord::Base
 attr_accessible :name, :sign_up_date
 has_many :enrollments

 after_create :create_enrollment_log
 private
 def create_enrollment_log
   enrollments.create!(status: 'signed up', started: sign_up_date)
 end
end

Where sign_up_date is your virtual attribute

Muhamamd Awais
  • 2,385
  • 14
  • 25
  • This wouldn't conflict with the database? – at. Nov 28 '12 at 19:45
  • not at all unless you have an attribute of same name in database i would suggest you to have look at this rails cast http://railscasts.com/episodes/167-more-on-virtual-attributes – Muhamamd Awais Nov 28 '12 at 19:51
  • 1
    I get the following error: `undefined method `sign_up_date' for #` when trying to assign it. Which does seem odd as without querying the database, it looks just like the `name` field which I have no problem assigning. Does Rails query the database upon `.new` or from a `date_select` form helper? – at. Nov 28 '12 at 19:57
2

params will not be available inside the models.

One possible way to do this would be to define a virtual attribute in the user model and use that in the callback

class User < ActiveRecord::Base
 attr_accessible :name,:sign_up_date
 has_many :enrollments

 after_create :create_enrollment_log
 private
 def create_enrollment_log
   enrollments.create!(status: 'signed up', started: sign_up_date)
 end
end

you will have to make sure that the name of the field in the form is user[:sign_up_date]

kp2222
  • 94
  • 4
  • wouldn't this try to save it to the database as well, where the sign_up_date user field doesn't exist? – at. Nov 28 '12 at 19:44
  • nope, unless there is a matching column in the users table it can not save it to the database – kp2222 Nov 28 '12 at 19:46
  • I get `undefined method `sign_up_date' for #` when using `date_select` in my form. Or I get `undefined method `sign_up_date=' for #` if I try to do a simple assignment to it in my controller. – at. Nov 28 '12 at 19:58
  • A virtual attribute shoud be 'attr_accessor' but not attr_accessible! These two things are totally different! – K M Rakibul Islam Aug 16 '14 at 02:39