How do I extract one parameter from multiple request parameters using Rails? - ruby-on-rails

If I want to get out one parameter from request parameters below, how do I do so?
{"utf8"=>"✓", "authenticity_token"=>"***", "users_unsubscribe_mail_magazine_form"=>{"email"=>"tea#tea.com", "dm"=>"1"}, "commit"=>"Send Mail", "controller"=>"users/unsubscribe_mail_magazines", "action"=>"create"}
I want to get "users_unsubscribe_mail_magazine_form"=>{"dm"=>"1"}, and pass the parameter to another page.
When I type into the live shell
params[:users_unsubscribe_mail_magazine_form][:dm]
I get an error message
"!! #<NameError: undefined local variable or method `params' for #UnsubscribeMailMagazineMailer:0x00007f14c86c5848>"
Thank you.
PS:
I am using form_for "f.submit" to send the parameters.
PPS:
This is how I call my mailer.
def create
#unsubscribe_form = Users::UnsubscribeMailMagazineForm.new mail_magazine_unsubscribe_params
#dm = #unsubscribe_form.dm
if #unsubscribe_form.valid?
user = User.find_by(email: #unsubscribe_form.email)
UnsubscribeMailMagazineMailer.unsubscribe(user).deliver_now unless user.nil?
redirect_to action: :create_complete
else
render action: :new
end
end

The params are only available in the controller. When you want to use the parameters or single values from them in a mailer then you have to pass that value to the mailer in the arguments.
Something like this should work:
# in the controller
UnsubscribeMailMagazineMailer.unsubscribe(
user, params[:users_unsubscribe_mail_magazine_form][:dm]
).deliver_now if user
# in your mailer
def unsubscribe(user, dm)
# have the `user` and the `dm` value available in local variables
end

Related

Accessing more than default parameters (to, from, subject, reply_to) for rails mail interceptor

I have a method within a mailer called notification_mailer.rb:
def reminder_email
#community = #reminder.community
subject = "random subject text"
mail(from: address_for(support), reply_to: address_for(support), to: to_address, subject: subject)
end
I am trying to use a mail interceptor check_mail_settings.rb:
class CheckMailSettings
def self.delivering_email(mail)
if #community.status = "mute"
mail.perform_deliveries = false
end
end
end
ActionMailer::Base.register_interceptor(CheckMailSettings)
But this interceptor does not actually have access to the #community variable. I have tried passing it in the mail call in notification_mailer.rb like so
mail(community: #community, from: address_for(support).....)
and accessing it within the interceptor check_mail_settings.rb like this
mail.community
but that does not work either.
Is there any way I can get access to this #community variable within the interceptor check_mail_settings.rb or will I need to do any conditionals involving #community within the notification_mailer.rb beforehand?
while i don't think that what you are doing there really makes sense, it is possible.
in the interceptor you get an instance of Mail::Message. it has access to whatever you pass into the mail call.
so in the example you provided it would be
mail[:community].value

Rails testing controller private method with params

I have a private method in a controller
private
def body_builder
review_queue = ReviewQueueApplication.where(id: params[:review_queue_id]).first
...
...
end
I would like to test just the body_builder method, it is a method buidling the payload for an rest client api call. It needs access to the params however.
describe ReviewQueueApplicationsController, type: :controller do
describe "when calling the post_review action" do
it "should have the correct payload setup" do
#review_queue_application = ReviewQueueApplication.create!(application_id: 1)
params = ActionController::Parameters.new({ review_queue_id: #review_queue_application.id })
expect(controller.send(:body_builder)).to eq(nil)
end
end
end
If I run the above it will send the body_builder method but then it will break because the params have not been set up correctly as they would be in a call to the action.
I could always create a conditional parameter for the body_builder method so that it either takes an argument or it will use the params like this def body_builder(review_queue_id = params[:review_queue_id]) and then in the test controller.send(:body_builder, params), but I feel that changing the code to make the test pass is wrong it should just test it as it is.
How can I get params into the controller before I send the private method to it?
I think you should be able to replace
params = ActionController::Parameters.new({ review_queue_id: #review_queue_application.id })
with
controller.params = ActionController::Parameters.new({ review_queue_id: #review_queue_application.id })
and you should be good. The params is just an attribute of the controller (the actual attribute is #_params but there are methods for accessing that ivar. Try putting controller.inspect in a view).

Error passing object to method using send() in Ruby

I'm having a problem using send() to call a method while passing said method an object. I receive an undefined method ``employee_feedback(#<WorkItem:0x000000057cc7c0>)' for WorkItemMailer:Class error.
This is in my work_item.rb model:
def send_work_item_mail
forms_needing_mail = ["employee", "install", "repair"]
if forms_needing_mail.include?(self.form)
WorkItemMailer.send("#{self.form}_feedback(#{self})").deliver_now
end
end
Which is being called as:
#work_item.send_work_item_mail
in my work_items_controller.rb
And the following is the method in my mailer:
def employee_feedback(work_item)
#work_item = work_item
#employee = User.find_by(id: #work_item.employee)
#manager = User.find_by(id: #employee.manager)
mail to: #manager.email, subject: "Employee feedback for #{#employee.name}"
end
Am I using send incorrectly, or is there something else at play here?
try this
WorkItemMailer.send("#{self.form}_feedback".to_sym, self).deliver_now
Calling send on an object is identical as calling a method directly. The difference is that you pass the method name as an argument to send.
Subsequent arguments to send, (after the method name) are passed as parameters in the method
So this:
WorkItemMailer.employee_feedback(self)
Should be called as:
WorkItemMailer.send(:employee_feedback, self)
In your case:
WorkItemMailer.send("#{self.form}_feedback", self).deliver_now

How do you test the params hash in a Rails test?

The following generates an error: "undefined local variable or method `params'"
assert_equal params[:recipient_id], users(:one).id
How do you test the params hash?
Also, how do you test assert_redirect when there are params present? The params are appended to the URL, so testing for model_path or similar fails.
Working with built in test class in Rails 3.
http://guides.rubyonrails.org/testing.html#functional-tests-for-your-controllers gives some of this information.
In this case, params is attached to the #request or #response object (depending on what HTTP method you are testing), so you can refer to it as #request.params[:recipient_id].
For redirect:
assert_redirected_to post_path(assigns(:post)) will assert that you are redirected to the proper path for a given model. The assigns method should have the instance variables you are setting inside of the controller to pass to the view

Is it possible to use the 'request' method in a model?

I am using Ruby on Rails 3 and I am tring to do some like this in my model file
if request.headers["CONTENT_LENGTH"]
...
end
but I get this error:
NameError (undefined local variable or method `request' for #<User:0x00...>):
So, is it possible to use the 'request' method in a model? If so, how?
No, because the request is only available in controllers and view code. From a design point of view you're ill advised to use the request within model code, but let's say you want to do something with the request on a particular instance of your User, just create a method for it:
class User
...
def has_a_request?(request)
raise ArgumentError if(request.blank? || !request.respond_to(:headers))
if(request.headers["CONTENT_LENGTH"] # Does it really have CONTENT_LENGTH btw?
puts "#{self.username} got a request with content length"
return true
else
puts "#{self.username} didn't get a request with content length"
return false
end
end
And then elsewhere in your application:
User.has_a_request?(request)
Is not good app design to use the request object in the method, but if you do absolutely need it you can do :
class User
def a_method request
end
end
class UserController
def index
User.find(params[:user]).a_method request
end
end
Extract relevant data from the request object in your controller, then pass them on to the model -- either by setting attributes on an instance of it or by passing them as parameters to a method call.

Resources