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.