我有一个用户模型和一个消息模型。用户有_多条消息且消息属于_用户。
在 users_controller 的一种方法中,我从 API 获取电子邮件数据,使用该数据初始化新消息(使用 thisMessage = Message.new(messageId, senderName...))。在 Controller 中,我多次执行此操作,并将这些消息存储在名为 listOfMessages 的数组中。到目前为止,一切顺利,我可以通过执行 listOfMessages[0].sender (发送者是消息模型属性)来使用消息的属性。
但是,当我刷新页面时,这些消息当然不会保存。如果我在每次初始化新消息后尝试使用“thisMessage.save”将消息保存到数据库,则会收到错误“nil:NilClass 的未定义方法 '[]'”。
我也尝试过“thisMessage.save!”,但收到错误“未定义方法“has_key?”对于 nil:NilClass"
那么我该如何保存这些消息呢?
消息模型
class Message < ActiveRecord::Base
belongs_to :user
def initialize(inputId, inputSender, inputSenderRealName, inputRecievedAt, inputSubject, inputContent, inputIsRead, inputIsReplied, inputImportanceLevel)
@emailId = inputId
@sender = inputSender
@senderRealName = inputSenderRealName
@recievedAt = inputRecievedAt
@subject = inputSubject
@content = inputContent
@isRead = inputIsRead
@isReplied = inputIsReplied
@importanceLevel = inputImportanceLevel
end
我正在使用的 users_controller 的方法
def messageList
@user = current_user
if @user.current_message == nil
@user.current_message = 0
else
end
puts "Need Loading " + @user.needsLoading.to_s
@listOfMessages = Array.new
messageIdList = Array.new
--API stuff removed--
body1 = singleMessage['bodies'][0]['content']
senderName = singleMessage['addresses']['from'][0]['email']
senderActualName = singleMessage['addresses']['from'][0]['name']
recieveTime = singleMessage['sent_at']
subjectText = singleMessage['subject']
isRead = singleMessage['flags']['seen']
hasReplied = singleMessage['flags']['answered']
thisMessage = Message.new(messageId, senderName, senderActualName, recieveTime, subjectText, body1, isRead, hasReplied, 0)
@listOfMessages << thisMessage
thisMessage.save
}
puts @user.messages.length
@responseText = response
puts @user.needsLoading.to_s
puts @user.current_message
@user.update_column(:needsLoading, 1)
end
最终目标是能够在其他地方执行“current_user.messages[1].sender”等操作。 谢谢!
最佳答案
1。不要重写 ActiveRecord::Model
上的初始化方法。
ActiveRecord 模型已经采用属性哈希:
User.new(name: 'Max', awesome: true)
如果该属性存在,它将在模型实例上设置。初始化器做了很多工作,你不应该轻易地破坏它。
如果您确实需要在初始化程序中执行某些操作,请确保调用 super
并保持接口(interface)与模型所期望的接口(interface)相同。
def initalize(hash = {}, &block)
super
# do something custom here
end
但在大多数情况下,您可以使用回调或自定义属性 setter 。
2。遵循 ruby 约定。
就此而言,Ruby 和 Rails 具有非常简单且强大的命名约定:
CONSTANTS
全部大写。 Ruby 强制执行这一点。ModuleName
和ClassName
是 CamelCase(也是一种常量)。variable_name
和attribute_name
是snake_case
。 Ruby 并不关心——但社区关心。忽视这一点,你将永远无法与酷 child 坐在一起。
3。 .update
和 .assign_attributes
有几种方法可以更改模型实例,但请务必注意更改内存中的模型实例与将更改提交到数据库之间的区别。
@order = Order.new
# change a single attribute.
@order.total = 999
# Update multiple attributes at once
@order.assign_attributes(
total: 669,
shipping_method: 'FEDEX'
)
# So far we have only updated the instance in memory.
@order.save # Commit the changes to the database
# We can also update the database straight away.
@order.update_attribute(:total, 999) # one attribute at a time
# or with a hash.
@order.update(
total: 669,
shipping_method: 'FEDEX'
)
# Using related objects works the same:
@order.update(
customer: @customer
)
# Note that this will also save the related object to the database.
@order.update(
customer: Customer.new
)
4。使用服务对象通过 API 调用创建模型实例。
这限制了外部 API 和您的应用程序之间的接触点数量。而且它们真的很容易测试。
# Import a message from SomeApi
class MessageImportService
def initialize(client = MyApi)
@client = client
end
# @return [Array]
def call
data = @client.call_some_api_method || []
data.map do |raw_msg|
Message.new(
body1 : raw_msg['bodies'][0]['content'],
sender_name : raw_msg['addresses']['from'][0]['email'],
sender_actual_aame : raw_msg['addresses']['from'][0]['name'],
)
end
end
end
从你的 Controller 你会这样做:
@messages = MessageImportService.new.call
https://blog.engineyard.com/2014/keeping-your-rails-controllers-dry-with-services
关于ruby-on-rails - Rails : How do I save an object to a model after calling Model. 新的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31527332/