ruby-on-rails - Rails : How do I save an object to a model after calling Model. 新的?

标签 ruby-on-rails ruby

我有一个用户模型和一个消息模型。用户有_多条消息且消息属于_用户。

在 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 强制执行这一点。
  • ModuleNameClassName 是 CamelCase(也是一种常量)。
  • variable_nameattribute_namesnake_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/

相关文章:

ruby-on-rails - Wicked PDF - 将 Font Awesome 图标显示为方框

ruby-on-rails - ruby - 如何加密文本

ruby - 单元测试中应该父类(super class)不匹配

ios - Calabash - 如何比较标签中给定 ID 的文本?

ruby - 在 Mechanize 中,我如何确定 post_connect_hook 的响应类型

php - 网页抓取 JAVASCRIPT 内容的语言

ruby-on-rails - RSpec - 加载时发生错误 - 你的意思是?

ruby-on-rails - Rails before_filter 用于 Controller 中的特定操作

css - Rails 不再编译和提供我的 application.scss 文件

ruby-on-rails - 运行 "rails new"时出现语法错误