为什么我的虚拟属性不起作用?

时间:2014-03-23 22:00:40

标签: ruby-on-rails virtual-attribute

我正在使用Rails 3.2.17尝试访问模型中的两个虚拟属性(expiration_amount& expiration_format)但我尝试过的任何内容都无法访问它们

其他所有内容似乎都正确更新,但在我的日志中,虚拟属性总是空白。

编辑我按照建议将:expiration_amount :expiration_format添加到attr_accessible,但它仍然无效。他们都是空白。我注意到的一件事是记录器调用是在它击中数据库后发生的。 before_update不是正确的过滤器吗?

编辑2 Devise是否可以阻止访问虚拟属性?

编辑3 我刚决定从控制器(它正在工作)开始,虽然我仍然很好奇为什么我无法访问这些虚拟属性该模型。

工作控制器操作(更新方法)

@user.set_expiration(params[:expiration_amount].to_i, params[:expiration_format])

工作模式方法

def set_expiration(amount, format)
  if defined?(amount) && defined?(format)
    case format
    when "hours" 
      self.expiration = amount.hours.from_now
    when "days"
      self.expiration = amount.days.from_now
    when "weeks"
      self.expiration = amount.weeks.from_now
    else
      self.expiration = amount.hours.from_now
    end
  end
end

---原始代码---

User.rb

class User < ActiveRecord::Base
  attr_accessible               :email, 
                                :password, 
                                :password_confirmation, 
                                :remember_me,
                                :first_name, 
                                :last_name, 
                                :company, 
                                :phone, 
                                :expiration,
                                :expiration_amount, 
                                :expiration_format

  attr_accessor                 :expiration_amount, 
                                :expiration_format

  before_update                 :set_expiration

  def set_expiration
    logger.debug "DEBUG - expiration_amount: #{expiration_amount}"
    logger.debug "DEBUG - expiration_format: #{expiration_format}"

    if expiration_amount && expiration_format
      case expiration_format
      when "hours" 
        self.expiration = expiration_amount.hours.from_now
      when "days"
        self.expiration = expiration_amount.days.from_now
      when "weeks"
        self.expiration = expiration_amount.weeks.from_now
      else
        self.expiration = expiration_amount.hours.from_now
      end
    end
  end
end

形式

= form_for(resource, :as => resource_name, :url => admins_user_update_path(resource), :html => { :method => :put }) do |f| 
  = devise_error_messages! 

  %fieldset{id: "edit-user-account"}
    %legend
      Set User Access

    .field.required
      %label
        "Allow access for "
      = select_tag "expiration_amount", options_for_select(expiration_amount, 3)
      = select_tag "expiration_format", options_for_select(expiration_format, "days")
      %span.instructions
        From Now

    .field
      = f.submit "Grant Access"

日志

  Parameters: {"utf8"=>"✓", "authenticity_token"=>"xxx=", "expiration_amount"=>"3", "expiration_format"=>"days", "commit"=>"Grant Access", "id"=>"5"}
User Load (0.6ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1  [["id", "5"]]
Admin Load (0.4ms)  SELECT "admins".* FROM "admins" WHERE "admins"."id" = 1 LIMIT 1
 (0.3ms)  BEGIN
DEBUG - expiration_amount: 
DEBUG - expiration_format: 
(0.3ms)  COMMIT
Redirected to http://localhost:8080/admins/users

3 个答案:

答案 0 :(得分:0)

Rails 3: 也可以将它们放在attr_accessible中。

Rails 4: 确保你允许它们。

答案 1 :(得分:0)

我建议使用rails form helper创建表单:

.field.required
= form_for @user do |f|
  = f.label :expiration, "Allow access for "
  = f.select "expiration_amount", options_for_select(expiration_amount, 3)
  = f.select "expiration_format", options_for_select(expiration_format, "days")
  %span.instructions
   From Now

然后在你的控制器中:

@user = User.find(params[:id])
@user.update_attributes(params[:user])

答案 2 :(得分:0)

我终于弄明白了问题是什么!因为我在select_tags使用了叮咬,所以没有正确命名它们,所以:

= select_tag "expiration_amount", options_for_select(expiration_amount, 3)
= select_tag "expiration_format", options_for_select(expiration_format, "days")

呈现为:

<select id="expiration_amount" name="expiration_amount">
<select id="expiration_format" name="expiration_format">

但他们需要让模特选择它们是:

= f.select :expiration_amount, options_for_select(expiration_amount, 3)
= f.select :expiration_format, options_for_select(expiration_format, "days")

<select id="user_expiration_amount" name="user[expiration_amount]">
<select id="user_expiration_format" name="user[expiration_format]">

之后我能够在模型中完成所有操作而不是控制器。

模型方法

before_update :set_expiration

def set_expiration
  logger.debug "DEBUG @ User - expiration_amount: #{expiration_amount}"
  logger.debug "DEBUG @ User - expiration_format: #{expiration_format}"

  if defined?(expiration_amount) && defined?(expiration_format)
    amount = expiration_amount.to_i

    case expiration_format
    when "hours" 
      self.expiration = amount.hours.from_now
    when "days"
      self.expiration = amount.days.from_now
    when "weeks"
      self.expiration = amount.weeks.from_now
    else
      self.expiration = 0.hours.from_now
    end
  end
end