【问题标题】:Ruby on Rails - Linking a user and product controller together, is not workingRuby on Rails - 将用户和产品控制器链接在一起,不起作用
【发布时间】:2018-12-11 23:37:29
【问题描述】:

更新 2

到目前为止,我所做的是 rails generate migration add_user_reference_to_products

然后我做了

类 AddUserReferenceToProducts

但我正在获取 PG::DuplicateColumn: ERROR: 关系“request_items”的列“user_id”已经存在。

当我在视图中引用它(作为@products.user_id)时,它是空白的。我尝试过创建一个新产品,但它不起作用。我应该做什么,因为我现在做不到,为了我现在的生活,弄清楚现在该做什么。

更新

我想做类似@products.users.username 的操作(如果有其他方法,请告诉我)为他们创建的产品显示用户的用户名。

目前,我没有修改如下所述的代码,但如果需要更多信息,请告诉我。另外,如果您能够提供分步流程,我将不胜感激。

克莱德提供的答案对我不起作用(未定义的方法“用户名”)。

问题:尽管已经在模型中定义了这种关系,但我如何才能将用户控制器与产品控制器链接? (一个用户可以创建多个产品,一个产品属于一个用户)

我有一个网站,用户可以在其中创建产品。现在,这些用户也有一个个人资料页面。我想知道是否可以拥有它,所以当用户创建产品并单击产品本身时,它会显示哪个用户创建了它,当我单击用户名时,它会指向他们的个人资料页面。

目前,唯一不工作的是用户名没有出现在他们创建的产品上,路线和其他一切都在工作。

对于用户,相关代码:

class UsersController < ApplicationController
  def index
    @users = User.all
  end

  def show
    @users = User.find(params[:id])
  end
end

架构

  create_table "users", force: :cascade do |t|
    t.string   "email"
    t.string   "username"
    t.string   "encrypted_password"
    t.string   "description"
    t.string   "address"
    t.string   "phone_number"
 end

对于产品:

class ProductsController < ApplicationController
  def index
    @products = Product.all
  end

  def new
    @products = Product.new
  end

  def create
      params[:products][:user_id] = current_user.id
      @products = products.new(products_params)
  end

  def edit
    @products = Product.find(params[:id])
  end

  def update
    @products = Products.find(params[:id])
    @products.update_attributes!(products_params)
    flash[:notice] = "#{@products.name} has been succesfully updated."
    redirect_to show_my_products_path
  end

  def destroy
    @products = Product.find(params[:id])
    @products.destroy
    flash[:notice] = "Your product '#{@products.name}' has been deleted."
    redirect_to show_my_products_path
  end

  def show
    @products = Product.find(params[:id])
  end

end

架构

  create_table "products", force: :cascade do |t|
    t.string   "name",                default: "", null: false
    t.string   "description"
    t.string   "quantity"
    t.datetime "created_at",                       null: false
    t.datetime "updated_at",                       null: false
    t.integer  "user_id"
  end

对于展示产品页面,它本质上是显示产品信息。我想添加的一件事是这一行:

<%= link_to "#{user.username}",  users_show_path_url(user), class: 'link_to'   %>

如果您单击用户创建的产品页面上的此链接,它将定向到他们的个人资料页面。但是,在产品的 show.html.erb 页面中,我确实收到了错误:

undefined method `username' for nil:NilClass

Couldn't find User with 'id'= .... 

我想,我不太确定如何链接创建他们产品的用户并在该特定产品上显示他们的用户名。我试过添加:

@users = User.all
@users = User.find(params[:id])

致展会产品负责人。

另外,这是模型:

class User < ActiveRecord::Base
  has_many :products
end

class Product < ActiveRecord::Base
  belongs_to :user
end

我故意省略了一些代码并选择了最相关的代码,但如果您需要更多代码,请告诉我。

我想要的是当有人点击该产品时,他们可以看到是哪个用户创建了它,并看到他们的用户名,因此点击该用户名即可转到用户个人资料。产品和用户之间的唯一链接是产品表中的“user_id”。因此,当创建产品时,user_id 与该项目相关联。

【问题讨论】:

    标签: ruby-on-rails


    【解决方案1】:

    首先,我将创建设计用户

    rails generate devise User
    

    然后我会创建一个任务

    rails g scaffold Task name:string description:text user:references
    

    那我修改任务控制器

    class TasksController < ApplicationController
      before_action :set_task, only: [:show, :edit, :update, :destroy]
      before_action :authenticate_user!, except: [ :show, :index]
      # GET /tasks
      # GET /tasks.json
      def index
        @tasks = Task.all
      end
    
      # GET /tasks/1
      # GET /tasks/1.json
      def show
      end
    
      # GET /tasks/new
      def new
        @task = current_user.tasks.new
      end
    
      # GET /tasks/1/edit
      def edit
      end
    
      # POST /tasks
      # POST /tasks.json
      def create
        @task = current_user.tasks.new(task_params)
    
        respond_to do |format|
          if @task.save
            format.html { redirect_to @task, notice: 'Task was successfully created.' }
            format.json { render :show, status: :created, location: @task }
          else
            format.html { render :new }
            format.json { render json: @task.errors, status: :unprocessable_entity }
          end
        end
      end
    
      # PATCH/PUT /tasks/1
      # PATCH/PUT /tasks/1.json
      def update
        respond_to do |format|
          if @task.update(task_params)
            format.html { redirect_to @task, notice: 'Task was successfully updated.' }
            format.json { render :show, status: :ok, location: @task }
          else
            format.html { render :edit }
            format.json { render json: @task.errors, status: :unprocessable_entity }
          end
        end
      end
    
      # DELETE /tasks/1
      # DELETE /tasks/1.json
      def destroy
        @task.destroy
        respond_to do |format|
          format.html { redirect_to tasks_url, notice: 'Task was successfully destroyed.' }
          format.json { head :no_content }
        end
      end
    
      private
        # Use callbacks to share common setup or constraints between actions.
        def set_task
          @task = Task.find(params[:id])
        end
    
        # Never trust parameters from the scary internet, only allow the white list through.
        def task_params
          params.require(:task).permit(:name, :description, :user_id)
        end
    end
    

    然后我将在User 表中添加新列。

    rails generate migration add_username_to_users username:string
    

    然后我将运行迁移命令

    rake db:migrate
    

    然后我将在注册表单中添加用户名字段#/views/devise/registerations/new.html.erb

    <div class="field">
      <%= f.label :username %><br />
      <%= f.text_field :username, autofocus: true, autocomplete: "username" %>
    </div>
    

    然后我将允许设计控制器中的用户名

    class ApplicationController < ActionController::Base
      before_action :configure_permitted_parameters, if: :devise_controller?
    
      protected
    
      def configure_permitted_parameters
        devise_parameter_sanitizer.permit(:sign_up, keys: [:username])
      end
    end
    

    然后我将在#user.rb 中添加用户名验证

      validates :username, uniqueness: true, presence: true
    

    然后我会在用户模型中添加引用

    has_many :tasks
    

    现在您可以在任务中显示您的用户名 随处可见

    <%= task.user.username %>
    

    这是工作示例 Association link sample for username display

    【讨论】:

      【解决方案2】:

      为了使用变量user,您需要分配它,我看不到在展示产品操作中这是在哪里完成的。

      尝试通过产品访问用户:

      <%= link_to "#{@products.user.username}",  users_show_path_url(@products.user), class: 'link_to' %>
      

      您还需要确保您正在查看的产品确实有用户,否则会导致相同类型的错误。

      【讨论】:

      • 嗨猫,谢谢。我现在刚刚完成了你的方法,我得到了 nil:NilClass 的未定义方法“用户名”。根据您所说,我是否也应该在产品控制器中定义用户?
      • 你分配给@products的产品有用户吗?您可以通过查看@products.user 的结果轻松检查。解决方案是通过验证来强制关系,或者在呈现链接之前检查用户是否存在。
      【解决方案3】:

      试试:

         <%= link_to user_path(@product.user), title: @product.user.username do %>
           <%= @product.user.username %>
         <% end %>
      

      【讨论】:

        【解决方案4】:

        我不确定您在 Products 控制器中的创建功能是否按预期工作。

        首先,当调用 Product.new 时,Product 需要一个大写的 P。 https://apidock.com/rails/v3.2.13/ActiveRecord/Base/new/class

        其次,我认为您没有正确关联用户。

        第三,你需要将新实例保存到数据库中。

        根据您的 product_params,您可能可以执行以下操作:

        def create
          attributes = product_params.merge(user_id: current_user.id)
          @product = Product.new(attributes)
        
          if @product.save
            redirect_to show_my_products_path, notice: 'Product was successfully created.'
          else
            render :new
          end
        end
        

        在这种情况下,由于您没有通过参数传递 user_id,因此您的 product_params 中不需要允许 user_id。

        那么在正确的视图中你应该可以调用

        <%= link_to @product.user.username, users_show_path_url(user), class: 'link_to' %> |
        

        我还看到您在其他应该是单数的方法中调用 Products.find。 (可能是一个单独的问题) https://api.rubyonrails.org/classes/ActiveRecord/FinderMethods.html#method-i-find

        如果在索引中只有一个实例方法,那么最好将实例方法称为单数,这样它们都将是@product 而不是@products,但这纯粹是为了便于阅读。


        一般建议 - 最好尽可能多地构建您的应用程序,rails 会为您处理很多工作。

        例如,我从头开始跑

        rails g scaffold user username
        
        rails g scaffold products name user:references
        
        rails db:migrate
        

        我没有所有属性,因为这只是一个示例,但这为我生成了使一切按预期工作所需的所有代码(我的模型中的 has_many 除外)。这是一件非常有用的事情:)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多