Rails 3.1.2 with mail gem 2.3.0
I'm trying to use ActionMailer with an ActiveModel based form. I've defined my table less model like so:
class StprodApp
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
attr_accessor :email,:name
attr_reader :errors
validates_presence_of :email, :message => "Please enter your email address"
def initialize(attributes = {})
attributes.each do |name, value|
send("#{name}=", value)
end
#errors = ActiveModel::Errors.new(self)
end
def persisted?
false
end
end
So far so good, I can post a form based on stprod_app, and validations work
So now I want to send an email based off this model, so I do this in my create action:
#stprod_app = StprodApp.new(params[:stprod_app])
if #stprod_app.valid?
EmployeeMailer.stprod_app(#stprod_app).deliver
end
I get this error
undefined method `index' for #<StprodApp:0x007f95325a1ad0>
and this stack trace
mail (2.3.0) lib/mail/encodings.rb:117:in `value_decode'
mail (2.3.0) lib/mail/encodings.rb:101:in `decode_encode'
mail (2.3.0) lib/mail/fields/unstructured_field.rb:74:in `do_decode'
mail (2.3.0) lib/mail/fields/unstructured_field.rb:56:in `decoded'
mail (2.3.0) lib/mail/fields/unstructured_field.rb:107:in `wrapped_value'
mail (2.3.0) lib/mail/fields/unstructured_field.rb:70:in `do_encode'
mail (2.3.0) lib/mail/fields/unstructured_field.rb:52:in `encoded'
mail (2.3.0) lib/mail/field.rb:123:in `method_missing'
mail (2.3.0) lib/mail/header.rb:190:in `block in encoded'
mail (2.3.0) lib/mail/header.rb:189:in `each'
mail (2.3.0) lib/mail/header.rb:189:in `encoded'
mail (2.3.0) lib/mail/message.rb:1708:in `encoded'
actionmailer (3.1.2) lib/action_mailer/base.rb:451:in `set_payload_for_mail'
actionmailer (3.1.2) lib/action_mailer/base.rb:431:in `block in deliver_mail'
activesupport (3.1.2) lib/active_support/notifications.rb:53:in `block in
instrument'
activesupport (3.1.2) lib/active_support/notifications/instrumenter.rb:21:in
`instrument'
activesupport (3.1.2) lib/active_support/notifications.rb:53:in `instrument'
actionmailer (3.1.2) lib/action_mailer/base.rb:430:in `deliver_mail'
mail (2.3.0) lib/mail/message.rb:230:in `deliver'
app/controllers/stprod_app_controller.rb:20:in `create'
So I read the docs for the mail gem, and it says this:
---snip---
All objects that can render into an email, have an #encoded method. Encoded will return the object as a complete string ready to send in the mail system, that is, it will include the header field and value and CRLF at the end and wrapped as needed.
All objects that can render into an email, have a :decoded method. Decoded will return the object's "value" only as a string. This means it will not include the header fields (like 'To:' or 'Subject:').
By default, calling #to_s on a container object will call its encoded method, while #to_s on a field object will call it's decoded method. So calling #to_s on a Mail object will return the mail, all encoded ready to send, while calling #to_s on the From field or the body will return the decoded value of the object. The header object of Mail is considered a container. If you are in doubt, call #encoded, or #decoded explicitly, this is safer if you are not sure.
Structured fields that have parameter values that can be encoded (e.g. Content-Type) will provide decoded parameter values when you call the parameter names as methods against the object.
Structured fields that have parameter values that can be encoded (e.g. Content-Type) will provide encoded parameter values when you call the parameter names through the object.parameters[''] method call.
---snip---
It looks like the index error is Rail's last desperate attempt to decode/encode? the email. The only 'index' I found in rails that makes sense is in ActiveSupport::Multibyte::Chars.
It sounds like I have to implement an encode/decode method in my ActiveModel, but I can't figure out how!
Anybody know how to define an ActiveModel that works with ActionMailer?
Solved, left off a crucial detail, and therin lay the problem
I was passing the Stprod_app instance variable to the mail call:
def stprod_app(emp,app)
#app = app
#emp = emp
mail(:to=> #app.antibot,
:from=>#emp.email,
:app=>#app) # <<< DOH!!!!
Sorry!
I had a similar error from this code:
def report( request )
headers['environment'] = RAILS_ENV
headers['identifier'] = request.id
...
end
In this case, it could not encode request.id because it was numeric. Changing it to request.id.to_s solved the problem.
Related
I'm using Flexirest to make a request to an endpoint that returns an array of strings with Content-Type: application\json.
This is the model:
class Neighborhood < BaseModel
get :by_location, "/neighborhoods/by_location"
end
And this is how I make the request:
def get_neighborhood_list
city_to_use = ApplicationHelper.user_location[:city] || Rails.configuration.default_location[:city]
#hoods = Neighborhood.by_location(city: city_to_use)
end
And this is called but it only reaches the super line since it breaks inside there:
def handle_response(response, cached = nil)
result = super(response, cached)
setup_paging_variables result, response
setup_paging_variables result.data, response if result.respond_to? 'data'
result
end
The endpoint returns an array of strings:
[
"Ahwatukee Foothills Village",
"Alhambra",
"Camelback East Village",
"Central City",
]
With this headers
My problem is that Flexirest is treating the strings as json objects instead due to the value on the Content-Type header.
I get this error
TypeError: no implicit conversion of Symbol into Integer
on this line on the if attributes[:_links].
It's getting there because hal_response? is true
Do I need to do something in particular in order for Flexirest to stop behaving like this?
Update
I guess I didn't explained it properly. The error is occurring on the gem side.
Here is the full error:
TypeError - no implicit conversion of Symbol into Integer:
flexirest (1.5.5) lib/flexirest/request.rb:612:in `handle_hal_links_embedded'
flexirest (1.5.5) lib/flexirest/request.rb:553:in `new_object'
flexirest (1.5.5) lib/flexirest/request.rb:704:in `block in generate_new_object'
flexirest (1.5.5) lib/flexirest/request.rb:703:in `generate_new_object'
flexirest (1.5.5) lib/flexirest/request.rb:501:in `handle_response'
config/initializers/01_flexirest.rb:7:in `handle_response'
flexirest (1.5.5) lib/flexirest/request.rb:219:in `block (2 levels) in call'
faraday (0.9.2) lib/faraday/response.rb:57:in `on_complete'
flexirest (1.5.5) lib/flexirest/request.rb:200:in `block in call'
activesupport (4.2.4) lib/active_support/notifications.rb:164:in `block in instrument'
activesupport (4.2.4) lib/active_support/notifications/instrumenter.rb:20:in `instrument'
activesupport (4.2.4) lib/active_support/notifications.rb:164:in `instrument'
flexirest (1.5.5) lib/flexirest/request.rb:156:in `call'
flexirest (1.5.5) lib/flexirest/mapping.rb:46:in `_call'
flexirest (1.5.5) lib/flexirest/mapping.rb:28:in `block in _map_call'
app/controllers/application_controller.rb:93:in `get_neighborhood_list
The if attributes[:_links] line is part of the gem code, and it's here on this line
When it reaches this line the value of attributes is one of the strings inside the response, for instance: attributes = "Ahwatukee Foothills Village". That's why it gives the error.
What I'm trying to figure out if there is a way (maybe something in the configuration) that I can use Flexirest to handle this kind of responses.
This is a old question but thought I'd answer it. you need to add
plain: true
in your model like below.
class Neighborhood < BaseModel
get :by_location, "/neighborhoods/by_location", plain: true
end
It will then return the string array
I'm using Rails 5.0.5 with Devise 4.3.0 for authentication. This app has been running smoothly for months, until I added a 'type'=>'string' attribute to my User model and attempted to create a new user. Submitting the form gives me a 500 internal server error. In this example, the User.type = 'hunter'.
NameError - wrong constant name hunter:
activesupport (5.0.5) lib/active_support/inflector/methods.rb:268:in `const_get'
activesupport (5.0.5) lib/active_support/inflector/methods.rb:268:in `block in constantize'
activesupport (5.0.5) lib/active_support/inflector/methods.rb:266:in `each'
activesupport (5.0.5) lib/active_support/inflector/methods.rb:266:in `inject'
activesupport (5.0.5) lib/active_support/inflector/methods.rb:266:in `constantize'
activesupport (5.0.5) lib/active_support/dependencies.rb:583:in `get'
activesupport (5.0.5) lib/active_support/dependencies.rb:614:in `constantize'
activerecord (5.0.5) lib/active_record/inheritance.rb:177:in `find_sti_class'
activerecord (5.0.5) lib/active_record/inheritance.rb:209:in `subclass_from_attributes'
activerecord (5.0.5) lib/active_record/inheritance.rb:55:in `new'
devise (4.3.0) lib/devise/models/registerable.rb:20:in `new_with_session'
app/models/user.rb:58:in `new_with_session'
user.rb:
def self.new_with_session(params, session)
if session['devise.user_attributes']
new(session['devise.user_attributes']) do |user|
user.attributes = params
user.valid?
end
else
super
end
end
Is Rails think this attribute value is a ClassName?? Can't seem to figure this one out. Any help greatly appreciated.
ActiveRecord uses the type column for Single Table Inheritance (STI) by default and the type value is expected to name a class. Presumably you don't have a hunter class so you get a confusing NameError from deep inside the guts of ActiveRecord.
From the fine manual:
inheritance_column()
Defines the name of the table column which will store the class name on single-table inheritance situations.
The default inheritance column name is type, which means it's a reserved word inside Active Record. To be able to use single-table inheritance with another column name, or to use the column type in your own model for something else, you can set inheritance_column:
self.inheritance_column = 'zoink'
Either rename your type column to something else or tell ActiveRecord to use some other column name for STI:
class User < ApplicationRecord
self.inheritance_column = 'there_is_no_sti_here' # Or whatever you're not using for a column name.
end
Using self.inheritance_column = nil also works.
If you're doing this a lot then you could make it declarative by adding a concern:
module STISuppression
extend ActiveSupport::Concern
included do
self.inheritance_column = nil
end
end
and then say things like:
class SomeModel < ApplicationRecord
include STISuppression
end
Same effect but it makes it clear what you're up to.
I'd like to add a vendor? function to Spree::User.
So I created app/models/spree/user.rb
module Spree
class User < Spree::Base
include Spree::UserMethods
def vendor?
self.role_users.any? { |ru| ru.role.name == 'vendor' }
end
end
end
This works if I start rails console and test:
u = Spree::User.last; u.vendor? # => false
But when I start rails server and visit a page I get this error:
NoMethodError in Spree::Admin::OrdersController#index
undefined method `serialize_from_session' for #
Stack trace
activerecord (4.2.5) lib/active_record/dynamic_matchers.rb:26:in `method_missing'
devise (3.5.4) lib/devise.rb:465:in `block (2 levels) in configure_warden!'
warden (1.2.4) lib/warden/session_serializer.rb:34:in `fetch'
warden (1.2.4) lib/warden/proxy.rb:212:in `user'
warden (1.2.4) lib/warden/proxy.rb:322:in `_perform_authentication'
warden (1.2.4) lib/warden/proxy.rb:104:in `authenticate'
devise (3.5.4) lib/devise/controllers/helpers.rb:124:in `current_spree_user'
solidus_auth_devise (1.3.0) lib/spree/authentication_helpers.rb:11:in `spree_current_user'
solidus/core/lib/spree/core/controller_helpers/auth.rb:67:in `try_spree_current_user'
solidus/core/lib/spree/core/controller_helpers/auth.rb:31:in `current_ability'
cancancan (1.13.1) lib/cancan/controller_additions.rb:338:in `authorize!'
solidus/backend/app/controllers/spree/admin/base_controller.rb:22:in `authorize_admin'
Any idea what I should do to fix this error? According to the stack trace it looks like I'm missing a method somewhere.
Cheers,
Martin
The answer is to open the Spree::User class and add the methods you're missing:
E.g:
config/initializers/spree_user.rb
Spree::User.class_eval do
def vendor?
self.role_users.any? { |ru| ru.role.name == 'vendor' }
end
end
Am using the save option on mongoid on ruby on rails, its throwing me an error
can't convert Fixnum into String
my model file are
product.rb
class Product
include Mongoid::Document
include Mongoid::Timestamps
include Mongoid::Versioning
field :product_role, :type => String
field :status_id, type: Moped::BSON::ObjectId
field :status_name,type: String
end
status.rb
class Status
include Mongoid::Document
field :name, type: String
index :name => 1
end
controller code is
product_id = "523741002a6c6e8d1a000002",
status_name = "Pending Review"
product_detail_status = Product.where(id:product_id).first
status = Status.where(name:status_name).first
puts "##############"
puts product_detail_status.id.to_s
puts status.name.to_s
puts status.id.to_s
puts "##############"
product_detail_status.status_name = status.name.to_s
product_detail_status.status_id = status.id
product_detail_status.save
i can able to view the values in puts, but its not saving by the way its throwing error on
product_detail_status.save as "can't convert Fixnum into String"
Completed 500 Internal Server Error in 657ms
TypeError - can't convert Fixnum into String:
mongoid (3.1.4) lib/mongoid/versioning.rb:53:in `revise'
activesupport (3.2.13) lib/active_support/callbacks.rb:407:in `
activesupport (3.2.13) lib/active_support/callbacks.rb:405:in `__run_callback'
activesupport (3.2.13) lib/active_support/callbacks.rb:385:in `_run_save_callbacks'
activesupport (3.2.13) lib/active_support/callbacks.rb:81:in `run_callbacks'
mongoid (3.1.4) lib/mongoid/callbacks.rb:130:in `run_callbacks'
mongoid (3.1.4) lib/mongoid/persistence/modification.rb:24:in `prepare'
mongoid (3.1.4) lib/mongoid/persistence/operations/update.rb:45:in `persist'
mongoid (3.1.4) lib/mongoid/persistence.rb:145:in `update'
mongoid (3.1.4) lib/mongoid/persistence.rb:82:in `save'
thanks in advance
I'm not sure why you are getting that error, but a better approach may be to use relations instead of manually adding a status_id and status_name to the product model
class Product
include Mongoid::Document
field :product_role, :type => String
has_one :status
end
Then in your controller, assign the Product's status as such
product_detail_status = Product.where(id:product_id).first
status = Status.where(name:status_name).first
product_detail_status.status = status
i found the solution, but am not sure its right way, on product model i remove
include Mongoid::Versioning
by that i can save it on product model by command save.
I keep getting the following error when sending a simple e-mail via ActionMailer in Rails:
NoMethodError: undefined method `encode!' for "Hello":String
This is triggered whenever the following is run:
def hello_world_email()
mail( :from => "me",
:to => "you,
:subject => "Hello World"
)
end
From researching this, it looks like it's caused by the differences between Ruby 1.8.7 and 1.9.*, which has built-in character encoding support.
Is there any way of getting ActionMailer to work with Ruby 1.8.7 and avoid this issue? (I can upgrade Ruby on my machine, but I can't do the same for everyone else working on the project). Given that the whole of Rails 3.0.9 (of which ActionMailer is a part) is meant to work with Ruby 1.8.7, I keep thinking that there must be a way...
Note: My exact version of Ruby is ruby 1.8.7 (2009-06-12 patchlevel 174) [universal-darwin10.0] (pre-installed on OSX).
You may have an issue with using Ruby 1.8 and having a constant Encoding defined by a gem.
For example we found an issue with a class that was including REXML at a global scope.
The line in question in the library was:
value.encode!(charset) if defined?(Encoding) && charset
This is checking for a global constant called Encoding. (Which could be defined in any gem at global scope.) Our problem was actually the include which then made REXML::Encoding available everywhere as Encoding. You could try grepping or acking your codebase for "module Encoding" or "class Encoding".
Hope this helps.
The stack trace below defines the problem.
NoMethodError: undefined method `encode!' for "Generate":String
mail (2.2.19) lib/mail/fields/unstructured_field.rb:169:in `encode'
mail (2.2.19) lib/mail/fields/unstructured_field.rb:138:in `fold'
mail (2.2.19) lib/mail/fields/unstructured_field.rb:108:in `wrapped_value'
mail (2.2.19) lib/mail/fields/unstructured_field.rb:70:in `do_encode'
mail (2.2.19) lib/mail/fields/unstructured_field.rb:52:in `encoded'
mail (2.2.19) lib/mail/field.rb:123:in `send'
mail (2.2.19) lib/mail/field.rb:123:in `method_missing'
mail (2.2.19) lib/mail/header.rb:190:in `encoded'
mail (2.2.19) lib/mail/header.rb:189:in `each'
mail (2.2.19) lib/mail/header.rb:189:in `encoded'
mail (2.2.19) lib/mail/message.rb:1708:in `encoded'
actionmailer (3.0.10) lib/action_mailer/base.rb:445:in `set_payload_for_mail'
actionmailer (3.0.10) lib/action_mailer/base.rb:425:in `deliver_mail'
activesupport (3.0.10) lib/active_support/notifications.rb:52:in `instrument'
activesupport (3.0.10) lib/active_support/notifications/instrumenter.rb:21:in `instrument'
activesupport (3.0.10) lib/active_support/notifications.rb:52:in `instrument'
actionmailer (3.0.10) lib/action_mailer/base.rb:424:in `deliver_mail'
mail (2.2.19) lib/mail/message.rb:230:in `deliver'
I had the same error, when trying to test my devise confirmation emails. Weird thing was, running the test isolated did not throw this exception. Running the whole stack did. After doing a binary search, i found, that one of my specs used REXML to parse some content.
require 'spec_helper'
require 'rexml/document'
include REXML
doc = Document.new(response.body)
I dont't know, why i included REXML, presumably, because i wanted to save the REXML:: in front of Document. But changing the code to this fixed the problem:
require 'spec_helper'
require 'rexml/document'
doc = REXML::Document.new(response.body)
if you happen to use code like this somewhere, this may fix this encode! issue with ruby 1.8.7
I found the issue to be with the mailer gem, changing to 2.2.13 fixed it for me.