Ruby-on-rails Rails - 添加不在模型中的属性并更新模型属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9376744/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 02:52:16  来源:igfitidea点击:

Rails - Add attributes not in model and update model attribute

ruby-on-railsaccessor

提问by alex.bour

I have 3 fields in my form witch are not in my database: opening_type, opening_hours, opening_minutes. I want to update the main attribute "opening" (in database) with these 3 fields.

我的表单中有 3 个字段不在我的数据库中:opening_type、opening_hours、opening_minutes。我想用这 3 个字段更新主要属性“opening”(在数据库中)。

I tried lot of things that doesn't work.

我尝试了很多不起作用的东西。

Actually I have:

其实我有:

  attr_accessor :opening_type, :opening_hours, :opening_minutes

  def opening_type=(opening_type)
  end
  def opening_type
    opening_type = opening.split("-")[0] if !opening.blank?
  end

  def opening_hours=(opening_hours)
  end
  def opening_hours
    opening_hours = opening.split("-")[1] if !opening.blank?
  end  

  def opening_minutes=(opening_minutes)
  end
  def opening_minutes
    opening_minutes = opening.split("-")[2] if !opening.blank?    
  end

I tried adding something like:

我尝试添加如下内容:

  def opening=(opening)
    logger.info "WRITE"

    if !opening_type.blank? and !opening_hours.blank? and opening_minutes.blank?
      opening = ""
      opening << opening_type if !opening_type.blank?
      opening << "-" 
      opening << opening_hours if !opening_hours.blank?
      opening << "-" 
      opening << opening_minutes if !opening_minutes.blank?
    end
    write_attribute(:opening, opening)
  end

  def opening
    read_attribute(:opening)
  end

But, the accessors methods are not called and I think opening_type, opening_hours, opening_minutes were empty too if the accessors were called...

但是,访问器方法没有被调用,我认为如果访问器被调用,opening_type、opening_hours、opening_minutes 也是空的......

I think I don't need a before_save callback and should do this rewriting the accessors.

我想我不需要 before_save 回调,应该重写访问器。

Notes: - Rails 3.0.5, - opening_type, :opening_hours, :opening_minutes could be empty

注意: - Rails 3.0.5,-opening_type,:opening_hours,:opening_minutes 可以为空

EDIT: I updated my code

编辑:我更新了我的代码

回答by Gareth

Note that attr_reader, attr_writerand attr_accessorare just macros for defining your own methods.

请注意attr_readerattr_writerattr_accessor只是用于定义您自己的方法的宏。

# attr_reader(:foo) is the same as:
def foo
  @foo
end

# attr_writer(:foo) is the same as:
def foo=(new_value)
  @foo = new_value
end

# attr_accessor(:foo) is the same as:
attr_reader(:foo)
attr_writer(:foo)

At the moment, your setter methods aren't doing anything special, so if you just switch to attr_accessoryour code will become cleaner.

目前,你的 setter 方法没有做任何特别的事情,所以如果你只是切换到attr_accessor你的代码会变得更干净。

Your other issue is that your opening=method is never being called, and this makes sense because there's nowhere in your code calling it. What you really want is for your opening to be set after all of the individual parts have been set. Now there's no trivial way to do this, but Rails does have a before_validationcallback where you can put code that runs after values have been set but before the validation runs:

您的另一个问题是您的opening=方法永远不会被调用,这是有道理的,因为您的代码中没有任何地方可以调用它。您真正想要的是在设置所有单个部分后设置您的开口。现在没有简单的方法可以做到这一点,但是 Rails 确实有一个before_validation回调,您可以在其中放置在设置值之后但在验证运行之前运行的代码:

class Shop < ActiveRecord::Base

  attr_accessor :opening_type, :opening_hours, :opening_minutes

  before_validation :set_opening

  private
  def set_opening
    return unless opening_type && opening_hours && opening_minutes
    self.opening = opening_type + "-" + opening_hours + "-" + opening_minutes
  end
end

回答by davidb

instead of

代替

attr_reader :opening_type, :opening_hours, :opening_minutes

you need

你需要

attr_accessor :opening_type, :opening_hours, :opening_minutes
attr_reader :opening_type, :opening_hours, :opening_minutes

hf...

高频...

// Are :opening_type, :opening_hours, :opening_minutes real fields? If yes then you just need this?

// :opening_type, :opening_hours, :opening_minutes 是真实字段吗?如果是,那么你只需要这个?

attr_accessor :opening attr_reader :opening

attr_accessor :打开 attr_reader :打开