Rails 4 - 无法使用' has_one'来创建新的嵌套模型,从而无需保存模型关联

时间:2015-10-24 00:28:40

标签: ruby-on-rails rails-activerecord polymorphic-associations

我有一个Visibility模型,它有一些布尔属性和其他定义其他模型可以看到的东西。可见性是多态的,因为我希望它属于User和Activity模型。可见性:

class Visibility < ActiveRecord::Base  
  belongs_to :viewable, :polymorphic => true
end

用户(已编辑为包含整体):

class User < ActiveRecord::Base
  # Relations
  #has_many :posts
  has_one :fb_connection
  has_many :activities
  has_many :participations
  has_many :activities, :through => :participations
  has_one :visibility, as: :viewable, dependent: :destroy
  accepts_nested_attributes_for :visibility

  has_many :friendships
  has_many :friends, :through => :friendships
  has_many :sent_friend_invites, :through => :friendships
  has_many :received_friend_invites, :through => :friendships

  devise :database_authenticatable, :registerable,
  :recoverable, :rememberable, :trackable, :validatable, :confirmable

  # Callback to set a user's default visibility for their activities
  before_save :default_values

  # paperclip helper method
  has_attached_file :profile_pic, styles: {
    thumb: '100x100>',
    square: '200x200#',
    medium: '300x300>'
  }, default_url: "https://dl.dropboxusercontent.com/u/743320/q_silhouette.gif"


  # Pagination
  paginates_per 100

  # Validations
  # :email
  validates :first_name, presence: true
  validates :last_name, presence: true
  validates_format_of :email, with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i

  # Paperclip validation
  validates_attachment :profile_pic, :size => { :in => 0..10.megabytes }, :content_type => { :content_type => /^image\/(jpeg|png|gif|tiff)$/}

  def self.paged(page_number)
    order(admin: :desc, email: :asc).page page_number
  end

  def self.search_and_order(search, page_number)
    if search
      where("email LIKE ?", "%#{search.downcase}%").order(
      admin: :desc, email: :asc
      ).page page_number
    else
      order(admin: :desc, email: :asc).page page_number
    end
  end

  def self.last_signups(count)
    order(created_at: :desc).limit(count).select("id","email","created_at")
  end

  def self.last_signins(count)
    order(last_sign_in_at:
    :desc).limit(count).select("id","email","last_sign_in_at")
  end

  def self.users_count
    where("admin = ? AND locked = ?",false,false).count
  end

  def get_display_name
    if display_name =~ /./  # Just check that the display name is not ""
      #puts "display name: " + display_name
      return display_name
    else
      #puts "name: " +  [first_name, last_name].join(" ")
      return [first_name, last_name].join(" ")
    end
  end

  def get_profile_pic_thumb
    return profile_pic(:thumb)
  end

  def measurement_labels
    return I18n.t('user_label_use_metric_true') if use_metric      
  end

  private

  def default_values
    viewable ||= Visibility.create(default_viewable_params)  
  end

  def default_viewable_params
    {:public => true, :app_friends => true, :facebook_friends => true, :strava_friends => true, :viewable => self }
  end
end

活动(相关部分):

class Activity < ActiveRecord::Base
    ...  
    has_one :visibility, as: :viewable, dependent: :destroy
    ...
end

我无法让我的生活得以实现。每当我保存用户模型时 - 即使未修改可见性模型 - 它也会为用户创建一个新的可见性模型。例如,在控制台中:

user = User.find(5)
user.foo = false
user.save

我得到了这个输出:

  

(0.4ms)BEGIN SQL(1.0ms)INSERT INTO&#34; visibilities&#34; (&#34;公共&#34 ;,   &#34; app_friends&#34;,&#34; facebook_friends&#34;,&#34; viewable_id&#34;,&#34; viewable_type&#34;,   &#34; created_at&#34;,&#34; updated_at&#34;)VALUES($ 1,$ 2,$ 3,$ 4,$ 5,$ 6,$ 7)   返回&#34; id&#34; [[&#34; public&#34;,&#34; t&#34;],[&#34; app_friends&#34;,&#34; t&#34;],   [&#34; facebook_friends&#34;,&#34; t&#34;],[&#34; viewable_id&#34;,5],[&#34; viewable_type&#34;,   &#34; User&#34;],[&#34; created_at&#34;,&#34; 2015-10-23 23:06:57.431922&#34;],[&#34; updated_at&#34;,   &#34; 2015-10-23 23:06:57.431922&#34;]](21.3ms)COMMIT =&gt;真

当然,尝试通过用户更新可见性模型失败了。在更新时,还会创建一个新的。以下是使用simple_form_for:

的适用user_controller方法和视图
#user_controller
def preferences
    @user = current_user
    if !@user.visibility
      @user.visibility = Visibility.new
    end   
end

def update_preferences
    user = current_user
    user.update!(user_pref_params)
    flash[:notice] = I18n.t('user_flash_update_success')
    redirect_to profile_path(user)    
end

private 

def user_pref_params
    params.require(:user).permit(:use_metric, visibility_attributes: [:id, :public, :app_friends, :facebook_friends])
end
<!-- preferences form -->
<%= simple_form_for @user, :url => update_preferences_path do |f| %>            
    <%= f.simple_fields_for :visibility do |v| %>
        <%= v.input :public, label: t('user_preferences_label_public'), as: :select, required: false %>
        <%= v.input :app_friends, label: t('user_preferences_label_app_friends'), as: :select, required: false %>
        <%= v.input :facebook_friends, label: t('user_preferences_label_facebook_friends'), as: :select, required: false %>     
    <% end %>
    <!-- Preference for system of measurement -->
    <%= f.input :use_metric, as: :select, collection: [[t('user_preferences_use_metric_true'), true], [t('user_preferences_use_metric_false'), false]], label: t('user_preferences_label_use_metric'),  include_blank: false %> 

    <!-- Submit button -->
    <%= f.button :submit, :label => "Save", :class => "btn btn-primary" %>
<% end %>

这种大规模分配尝试给了我这样的反馈:

  

启动PATCH&#34; / users / updateprefs&#34; 2015-10-23为127.0.0.1   17:02:52 -0700由UsersController处理#update_preferences为   HTML参数:{&#34; utf8&#34; =&gt;&#34;✓&#34;,   &#34; authenticity_token&#34; = GT;&#34; FXj3kWxNDE7tl7InvBvL68UzlvmWR / d3aJ4 / gTg7cCCEGEafJJZO10ud31kU2120SdKF3aNj5gy0FiizURHTeQ ==&#34 ;,   &#34;使用者&#34; =&GT; {&#34; visibility_attributes&#34; =&GT; {&#34;公共&#34; =&GT;&#34;假&#34 ;,   &#34; app_friends&#34; =&gt;&#34; false&#34;,&#34; facebook_friends&#34; =&gt;&#34; false&#34;,&#34; id&#34; =&gt; ;&#34; 64&#34;},   &#34; use_metric&#34; =&gt;&#34; true&#34;},&#34;提交&#34; =&gt;&#34;更新用户&#34;}用户负载(0.4ms)   SELECT&#34;用户&#34;。* FROM&#34;用户&#34;用户&#34;。&#34; id&#34; = $ 1 ORDER BY   #&34;用户&#34;&#34; ID&#34; ASC LIMIT 1 [[&#34; id&#34;,55]](0.3ms)BEGIN可见性   加载(0.8ms)SELECT&#34; visibilities&#34;。* FROM&#34; visibilities&#34;哪里   &#34;能见度&#34;&#34; viewable_id&#34; = $ 1 AND&#34; visibilities&#34;。&#34; viewable_type&#34; =   $ 2 LIMIT 1 [[&#34; viewable_id&#34;,55],[&#34; viewable_type&#34;,&#34; User&#34;]] SQL   (0.6ms)INSERT INTO&#34; visibilities&#34; (&#34; public&#34;,&#34; app_friends&#34;,   &#34; facebook_friends&#34;,&#34; viewable_id&#34;,&#34; viewable_type&#34;,&#34; created_at&#34;,   &#34; updated_at&#34;)价值($ 1,$ 2,$ 3,$ 4,$ 5,$ 6,$ 7)返回&#34; id&#34;   [[&#34; public&#34;,&#34; t&#34;],[&#34; app_friends&#34;,&#34; t&#34;],[&#34; facebook_friends&#34; ,&#34; t&#34;],   [&#34; viewable_id&#34;,55],[&#34; viewable_type&#34;,&#34;用户&#34;],[&#34; created_at&#34;,   &#34; 2015-10-24 00:02:52.244397&#34;],[&#34; updated_at&#34;,&#34; 2015-10-24   00:02:52.244397&#34;]] SQL(0.5ms)UPDATE&#34;用户&#34; SET&#34; use_metric&#34; =   $ 1,&#34; updated_at&#34; = $ 2 WHERE&#34;用户&#34;。&#34; id&#34; = $ 3 [[&#34; use_metric&#34;,&#34; t&#34;],   [&#34; updated_at&#34;,&#34; 2015-10-24 00:02:52.247304&#34;],[&#34; id&#34;,55]] SQL   (0.5ms)UPDATE&#34; visibilities&#34; SET&#34; app_friends&#34; = $ 1,&#34; updated_at&#34; =   $ 2 WHERE&#34; visibilities&#34;。&#34; id&#34; = $ 3 [[&#34; app_friends&#34;,&#34; f&#34;],   [&#34; updated_at&#34;,&#34; 2015-10-24 00:02:52.250120&#34;],[&#34; id&#34;,64]](13.3ms)   COMMIT

正如您所看到的,Rails正在创建新的可见性并更新现有的可见性!我可以通过一些非常丑陋的代码来解决这个问题,但我会感谢任何有助于保持控制器操作干净的帮助。

1 个答案:

答案 0 :(得分:2)

SOCK_SEQPACKET模型中,使用User方法,您可以创建新的可见性并将其分配给default_values。但是,这是作用域使得它只对方法可用,而不是作为整体的类(因此与方法变量进行比较)。

此外,viewable仅在viewable模型中正确使用关联。在Visibility模型中,您必须将其引用为User

需要做的是使用visibility来将比较和赋值应用于实例变量。

self