rails如何将params传递给new来创建块

时间:2017-11-09 00:29:28

标签: ruby-on-rails ruby parameters ruby-on-rails-5

我正在处理一个我想传递的项目:repairshop_id params到new_user_review。我这样做是通过使用:

<%= link_to 'Add A Review', new_user_review_path(@user, :repairshop_id => @repairshop.id), class: "btn btn-danger btn-xs", style: "border: #e20049" %>

每次审核都是针对用户的,但要么是在他的维修店或他的所有列表中。

在用于评论的控制器中,我之前的操作应该设置@parent,这是维修店或列表,具体取决于我从哪里调用新评论(显示列表页面或显示维修店页面)。

点击新的评论按钮后,网址会显示:http://localhost:3000/users/2/reviews/new?repairshop_id=3

这意味着我确实可以使用repairshop_id。

但是当我试图在控制器中设置params时,它的评估为nil class。

控制器代码:

class ReviewsController < InheritedResources::Base

    before_action :authenticate_user!, only: [:new, :create, :destroy, :update] 

    before_action :set_parent, only:  [:new, :create] 
    before_action :set_child_and_parent, only:  [:destroy, :update, :update, :edit]


    def new
        @review = Review.new        
    end

    def edit

    end

    def create
        @review = Review.new(review_params)         
        @review.user_id = current_user.id
        @review.owner_id = @owner.id        

        p "My parent is #{@parent}"

        respond_to do |format|
            if @review.save 
                format.html { redirect_to @parent, notice: 'Review was successfully created.' }
                format.json { render :show, status: :created, location:@parent }
            else                
                format.html { render :new }
                format.json { render json: @review.errors, status: :unprocessable_entity }
            end
        end

    end

    def destroy

        @review.destroy
        respond_to do |format|                      
            format.html { redirect_to @parent, notice: 'Review  was successfully destroyed.' }
            format.json { head :no_content }
        end

    end

    def update
        respond_to do |format|
            if @review.update(review_params)
                format.html { redirect_to @parent, notice: 'Review was updated.' }
                format.json { render :show, status: :ok, location: @parent}
            else
                format.html { render :edit }
                format.json { render json: @review.errors, status: :unprocessable_entity }
            end
        end
    end

    private

    def review_params
      params.require(:review).permit(:comment, :rating, :repairshop_id)
    end

    def set_child_and_parent
        @review = Review.find_by_id(params[:id])
        if params[:repairshop_id]
            @parent =  Repairshop.find_by_id(params[:repairshop_id])
        end

        if params[:listing_id]
            @parent = Listing.find_by_id(params[:listing_id])   
        end

        @owner = User.find_by_id(@parent.user_id)
    end

    def set_parent      
        if params[:repairshop_id]
            @parent =  Repairshop.find_by_id(params[:repairshop_id] )
        end

        if params[:listing_id]
            @parent = Listing.find_by_id(params[:listing_id] )  
        end

        @owner = User.find_by_id(params[:user_id])
    end


end

如果我通过直接提供repairshop_id设置父级,一切正常。但不知何故,这个repairshop_id没有被传递给控制器​​set_parent动作。

如何将变量从显示页面传递给全新的控制器操作。

我希望在创建评论后将用户重定向到listing / repairshops显示页面,然后点击评论按钮,然后尝试使用@parent params

更新:我得到的错误是500内部服务器,无法重定向到nil(这里是@parent):

enter image description here

我的评论表单代码:

<%= bootstrap_form_for [@owner, @review] do |f| %>
  <% if @review.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@review.errors.count, "error") %> prohibited this review from being saved:</h2>

      <ul>
      <% @review.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <%= f.select :rating, [1,2,3,4,5], :label => "CHOOSE YOUR RATING (1 is poor, 5 is great)" %>
  <%= f.text_area :comment, :label => "YOUR COMMENTS" %>

  <%= f.submit "SUBMIT", class: "btn btn-danger" %>    

<% end %>

更新后的照片:enter image description here

4 个答案:

答案 0 :(得分:1)

调试提示:

添加byebug

$1 ".log"

然后,运行代码,并在byebug控制台中,尝试def set_parent byebug .. end puts params

<强>提示:

puts params[:review]

答案 1 :(得分:0)

首先在您的repairshop_id操作中设置您希望的 def new @review = Review.new @repairshop_id = params[:repairshop_id] end 类似

的内容
<%= hidden_field_tag :repairshop_id, @repairshop_id %>

然后在表单中添加<%= bootstrap_form_for [@owner, @review] do |f| %> <% if @review.errors.any? %> <div id="error_explanation"> <h2><%= pluralize(@review.errors.count, "error") %> prohibited this review from being saved:</h2> <ul> <% @review.errors.full_messages.each do |message| %> <li><%= message %></li> <% end %> </ul> </div> <% end %> <%= f.select :rating, [1,2,3,4,5], :label => "CHOOSE YOUR RATING (1 is poor, 5 is great)" %> <%= f.text_area :comment, :label => "YOUR COMMENTS" %> <%= hidden_field_tag :repairshop_id, @repairshop_id %> <%= f.submit "SUBMIT", class: "btn btn-danger" %> <% end %> ,例如

public void run() {
    try {
    LeftClicker mouse = new LeftClicker();
    System.out.println("****Clicker Initated****");
    System.out.println("Randomization: " +randomization );
    System.out.println("Clicks / Second: " +clickCount );
    while (!shouldStop && clickCount > 0)
    {
        Long time = System.nanoTime();
        double[] seconds = Algorithms.genStructure(randomization, clickCount);


        for (int i=0; i<seconds.length;i++)
        {
            new Thread(mouse).start();
        Thread.sleep((long) (seconds[i]));
        }

        System.out.println("Time: " + (System.nanoTime() - time));

}
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

答案 2 :(得分:0)

根据上一个屏幕截图,您的review_params方法错误。

def toto
  '1'
  '2'
end

puts toto => you will get 2

def review_params
  params.require(:review).permit(...)
  params.require(:repairshop_id).permit(..)
end

puts review_params <--- what will you get ?

可能你想了解requirepermit的作用,而不是给你一个纯粹的答案。

实施例

params = { repairshop_id: '1', review: { rating: '1', comment: 'hello world' }}
puts params.require(:repairshop_id) => { repairshop: '1' }
puts params.require(:review).permit(:rating) => { review: { rating: '1' } }
puts params.require(:review).permit(:rating, :comment) => { review: { rating: '1', comment: 'Hello World' } }
puts params.require(:toto) => Would raise an exception, saying toto is missing.

i)在表单中添加隐藏的字段输入

<%= hidden_field_tag :repairshop_id, < YOUR REPAIR SHOP ID > %>

ii)修复review_params方法

def review_params
  params.require(:review).permit(:rating, :comment)
end

iii)在create或者before_action中找到您的维修店:

before_action :find_repairshop

..


def find_repairshop
  @repairshop = Repairshop.find(params[:repairshop_id])
end

答案 3 :(得分:0)

解决了我的问题是使用会话参数。 会话只是在一个请求期间存储数据的地方,您可以在以后的请求中读取该数据。

我决定使用会话哈希来存储我从其调用的资源中的新链接获得的资源ID参数,然后使用会话哈希检索父项在创建评论后重定向到。此外,我不需要使用隐藏字段来工作。

class ReviewsController < InheritedResources::Base

    before_action :authenticate_user!, only: [:new, :create, :destroy, :update]     
    before_action :set_child_and_parent, only:  [:destroy, :update, :edit]

    def new
        @review = Review.new                
        session[:parent_id] = params[:parent_id]
        session[:parent_type] = params[:parent_type]
        @parent = get_parent(params[:parent_type], params[:parent_id])      
        @owner = User.find_by_id(@parent.user_id)       
    end

    def create      
        @review = Review.new(review_params)         
        @review.user_id = current_user.id
        @parent = get_parent(session[:parent_type], session[:parent_id])
        @owner = User.find_by_id(@parent.user_id)       
        @review.owner_id = @owner.id             

        respond_to do |format|
            if @review.save 
                format.html { redirect_to @parent, notice: 'Review was successfully created.' }
                format.json { render :show, status: :created, location:@review }
            else                
                format.html { render :new }
                format.json { render json: @review.errors, status: :unprocessable_entity }
            end
        end
    end


private

    def review_params       
        params.require(:review).permit(:comment, :rating)
    end

    def set_child_and_parent        
        @review = Review.find_by_id(params[:id])        
    end

    def get_parent(parent_type, parent_id)
        if parent_type == "repairshop"
            parent = Repairshop.find_by_id(parent_id.to_i)
        elsif parent_type == "listing"
            parent = Listing.find_by_id(parent_id.to_i)
        else
            parent = root_path
        end

        return parent
    end

end