【问题标题】:User and Link association difficulties用户和链接关联困难
【发布时间】:2015-12-27 14:36:56
【问题描述】:

我有一个用户和链接 MVC。我在下面列出了它们。基本上,当我创建一个新链接时,我希望它与我的用户相关联,然后在我的显示页面上显示带有报价的用户电子邮件,但是当我进行身份验证时,我继续为用户获得 nil 值,即使我有:

  1. 用户和链接关联
  2. 在我的强参数中允许:user_id
  3. 有一个 before_filter 要求用户在发出新请求时登录
  4. 在我的链接架构中有一个 user_id

如果您查看我的 show.html.erb 和 <%= @link.user.try(:email) %> 行,这应该是发布链接的用户电子邮件的位置,但它们都显示为 nil 值。

我现在有点迷茫,为什么我不能让它工作,任何帮助将不胜感激!

型号:

class User < ActiveRecord::Base
  has_many :links
  acts_as_voter
  devise :database_authenticatable, :registerable,
    :recoverable, :rememberable, :trackable, :validatable
end

class Link < ActiveRecord::Base
  belongs_to :user
  acts_as_votable
  attr_accessor :avatar
  mount_uploader :avatar, AvatarUploader
end

控制器:

class LinksController < ApplicationController
  before_filter :authenticate_user!, except: [:index, :show]

  def index
    @links = Link.all
  end

  def show
    @link = Link.find(params[:id])
  end

  def new
    @link = Link.new
  end

  def edit
  end

  def create
    @link = Link.new(link_params)

    if @link.save
      redirect_to root_path
    else
      render 'new'
    end
  end

  private

  def link_params
    params.require(:link).permit(:title, :url, :avatar, :user_id)
  end
end

show.html.erb:

<p id="notice"><%= notice %></p>

<p>
  <strong>Author:</strong>
  <%= @link.title %>
</p>

<p>
  <strong>Quote:</strong>
  <%= @link.url %>
</p>

<small class="author">Submitted <%= time_ago_in_words(@link.created_at) %> ago by <%= @link.user.try(:email) %></small>

架构:

create_table "links", force: :cascade do |t|
    t.string   "title"
    t.string   "url"
    t.datetime "created_at",                     null: false
    t.datetime "updated_at",                     null: false
    t.integer  "user_id"
    t.integer  "cached_votes_total", default: 0
    t.integer  "cached_votes_score", default: 0
    t.integer  "cached_votes_up",    default: 0
    t.integer  "cached_votes_down",  default: 0
    t.string   "avatar"
  end

 create_table "users", force: :cascade do |t|
    t.string   "email",                  default: "", null: false
    t.string   "encrypted_password",     default: "", null: false
    t.string   "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer  "sign_in_count",          default: 0,  null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.string   "current_sign_in_ip"
    t.string   "last_sign_in_ip"
    t.datetime "created_at",                          null: false
    t.datetime "updated_at",                          null: false
  end

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-4 associations schema


    【解决方案1】:

    听起来好像从未设置过 user_id。碰巧的是,您可能不想通过参数设置它(因为这些可以由用户操作)。

    改为替换

     @link = Link.new(link_params)
    

     @link = current_user.links.build(link_params)
    

    如果链接总是有用户,我也会将user_id 列标记为非空,而不是通过调用try 乱扔我的应用程序(而且我通常更喜欢try!try

    【讨论】:

    • 感谢您的回答,该关联现已正常运行。出于我自己的好奇心,您为什么认为 link_params 没有设置用户?关于您的最后一句话,我应该运行迁移,将我的链接表中的 user_id 更改为 null: false?
    • 因为您的表单很可能没有 user_id 字段(或者它是空白的)。我会写一个迁移来改变 user_id 的空性,但这取决于你(你需要删除任何 user_id 为空的行)
    • 感谢您花时间解释这一点,非常感谢。
    【解决方案2】:

    1.据我了解,逻辑是您只能在登录后创建链接。用户只能为他/她创建链接(只有登录的用户才能成为他创建的链接的所有者)。在这种情况下,您不应在表单中公开 user_id,而应将其添加到 create 操作中:

     def create
        @link = Link.new(link_params)
    
        if @link.save
          current_user.links << @link
          redirect_to root_path
        else
          render 'new'
        end
      end
    

    2.另外,如果你不允许孤立链接(没有用户作为所有者),那么我建议不要使用user.try(:email),而是使用@link.user.email

    1. 如果您通过@link 访问用户对象,那么您可以在显示操作中预加载它以保存一些数据库查询

      def show   
       @link = Link.includes(:user).find(params[:id])  
      end
      

    进行这些更改,然后重试。此外,如果您使用默认设计配置,则用户需要电子邮件,因此 .try(:email) 返回 nil 可能意味着找不到 user 对象,这意味着关联设置不正确(我的版本可能会修复该问题)

    【讨论】:

      猜你喜欢
      • 2011-09-16
      • 1970-01-01
      • 2018-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多