简体   繁体   中英

How can I access params (or utilize a workaround) in my rails model?

I'm trying to refactor some code out of my rails controller to my model, and I've discovered a gap in my understanding of how rails works. I'm attempted to make the 2 methods available to the Raffle class, and I'm struggling to understand how to do so. When I hit this code, the error "undefined local variable or method `params' for #Raffle:0x00007f88c9af8940" is returned.

How can I work around params not being available to the model? Apologies if this is a beginner question- I am definitely a beginner.

#app/models/raffle.rb

class Raffle < ApplicationRecord
    has_many :tickets
    has_many :users, through: :tickets

    def bid_tickets(tier)
        params[:raffle][:"tier"].to_i #error returned here
    end
    
    def bid_total
        (bid_tickets(gold) * 3) + (bid_tickets(silver) * 2) + bid_tickets(bronze)
    end
#app/views/edit.html.erb

<%= form_for(@raffle) do |f| %>
  <%=f.label :ticket, "Gold" %>: <br>
  <%= image_tag "gold.jpg", class: "small_ticket" %><br>
  <%=f.number_field :gold%><br>
  <%=f.label :ticket, "Silver" %>:<br>
  <%= image_tag "silver.jpg", class: "small_ticket" %><br>
  <%=f.number_field :silver %><br>
  <%=f.label :ticket, "Bronze" %>:<br>
  <%= image_tag "bronze.jpg", class: "small_ticket" %><br>
  <%=f.number_field :bronze %> <br><br>
  <%= f.submit "Use Tickets" %>
<% end %><br>
#app/controllers/raffles_controller.rb

def update
      if @raffle.enough_slots? + @raffle.current_bids > @raffle.number_of_ticket_slots
              if enough_tickets? 
          redirect_to edit_raffle_path, notice: "You do not have enough tickets."
        else
        redirect_to edit_raffle_path, notice: "There aren't enough spots left in this raffle to handle your entry! Please use less tickets."
        end
      else @raffle.update_tickets(current_user)
        if @raffle.slots_filled?
          @raffle.select_winner
        end
       redirect_to edit_raffle_path(@raffle)
      end
    end
returned parameters:

{"_method"=>"patch",
 "authenticity_token"=>"xyz",
 "raffle"=>{"gold"=>"1", "silver"=>"", "bronze"=>""},
 "commit"=>"Use Tickets",
 "id"=>"1"}

EDIT:

#app/controllers/raffles_controller.rb (StrongParameters)
class RafflesController < ApplicationController
 private 

    def raffle_params
      params.require(:raffle).permit(:product_name, :product_description, 
      :product_image, :number_of_ticket_slots, :filter)
    end
end

params is made available to you in the Controller (by Rails) because it's a "web request thing". It's a good practice not to pass it deeper into your system, as it contains external "untrusted" input. That's why it's not automatically available in Models.

For example:

# controller
def update
  safe_value = validate_value(params[:unsafe_value]) # extract and validate

  # no "web request things" passed in
  result = MyFeature.do_stuff(@current_user, safe_value)  # pass it to other parts of system

  # then convert the result back into a "web request thing", e.g:
  # return render json: as_json(result)     # return result as json
  # return redirect_to endpoint_for(result) # redirect based on result
                                            # etc
end

It's good practice to pre-process the params (extracting the values out, validating them, etc) before passing that data to other parts of your system as arguments, like your models.

This will keep the rest of your system agnostic of "web request things", keeping them purpose-focused and well-organized.

For one, StrongParameters is a built-in rails feature that helps with this.

Another suggestion would be put a binding.pry or byebug (after making sure it's installed and updated via bundle) in code where params are utilized and then run your code. After it's triggered type params and you will see the breakdown.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM