简体   繁体   中英

Rails - NoMethodError (undefined method 'permit' for “reps”:string)

So I'm trying to create multiple objects from a single form in Rails 5. This was working perfectly fine in rails 4.2, I'm not exactly sure what is causing the error (I imagine it has something to do with the view).

Another problem I've run into after upgrading to rails 5 is now my form is only submitting the last record. I used this walkthrough for reference: http://vicfriedman.github.io/blog/2015/07/18/create-multiple-objects-from-single-form-in-rails/

This is the input and here are the parameters I'm sending.

Parameters: {"utf8"=>"√", "authenticity_token"=>"3j8A0oNW3sM5VIi11ZEHwpwlAhvY3
vml1kcLHfWdptySKSeJokRmBXObh/HEFBwG4/QC8PdfX7NKbkrGjOfI6Q==", "exercise_id"=>"16
5", "exercise_sets"=>{"reps"=>"1", "weight"=>"1"}, "exerciseName"=>"imsick", "co
mmit"=>"Save changes"}

The Error

NoMethodError (undefined method 'permit' for "reps":string)

ExerciseSetsController:

def create
    if current_trainer
        savedMirror = current_trainer.exercises.find_by_name(params[:exerciseName])

        params['exercise_sets'].each do |set|
            #set[:timeFormat] = savedMirror.exercise_sets[0].timeFormat
            #set[:weightFormat] = savedMirror.exercise_sets[0].weightFormat
            #set[:distanceFormat] = savedMirror.exercise_sets[0].distanceFormat
            ExerciseSet.create(exercise_set_params(set))
        end

        flash[:notice] = "Sets added"
        redirect_to (:back)
    end
end

private 
def exercise_set_params(e_params)
  e_params.permit(:id, :reps, :weight, :weightFormat, :time, :timeFormat, :distance, :distanceFormat, :exercise_id, :_destroy)
end

View:

<%savedMirror = current_trainer.exercises.find_by_name(e.name)%>
<%= form_tag  url_for(controller: "exercise_sets", action: "create") do%>
    <ul class="list-group">
        <% e.sets.times do |i|%>
        <%= fields_for "exercise_sets[]", @exerciseSet do |f| %>
        <li class="list-group-item">
            <label>Set: <%=i+1%></label>
                <%#= f.number_field :user_id, value: e.user_id, style:"visibility:hidden; margin:-15px;"%>
                <%= hidden_field_tag(:exercise_id, e.id) %>

              <div class = "row">
                <% if savedMirror.exercise_sets[0].reps == 1%>
                  <div class="col-sm-3">
                    <%= f.label :reps, "Reps" %><br>
                    <%= f.text_field :reps, class: "form-control"%>
                  </div>
                <%end%>
                <% if savedMirror.exercise_sets[0].weight == 1%>
                  <div class="col-sm-3">
                    <%= f.label :weight, "Weight" %><br>
                      <%= f.text_field :weight, class: "form-control"%>
                  </div>
                <%end%>
                <% if savedMirror.exercise_sets[0].time == 1%>
                  <div class="col-sm-3">
                    <%= f.label :time, "Time" %><br>
                      <%= f.text_field :time, class: "form-control"%>
                  </div>
                <%end%>
                <% if savedMirror.exercise_sets[0].distance == 1%>
                  <div class="col-sm-3">
                    <%= f.label :distance, "Distance" %><br>
                    <%= f.text_field :distance, class: "form-control"%>
                  </div>
                <%end%>
              </div>
        </li>
        <%end%>
        <%end%>
        <br>
        <%= hidden_field_tag(:exerciseName, e.name) %>
        <%=submit_tag%>
    </ul>
    <% end %>
<%end%>

Any help is greatly appreciated, thank you!

You need to add .require(:exercise) (I am assuming your model's name is exercise) to use strong params.

Requiring will enable your app to give error if you don't pass the model. Because the parameters you are whitelisting are defined for that model.

Just replace

def exercise_set_params(e_params)
  e_params.permit(:id, :reps, :weight, :weightFormat, :time, :timeFormat, :distance, :distanceFormat, :exercise_id, :_destroy)
end

with

def exercise_set_params(e_params)
  e_params.require(:exercise).permit(:id, :reps, :weight, :weightFormat, :time, :timeFormat, :distance, :distanceFormat, :exercise_id, :_destroy)
end

Hope it works!

It looks like :reps , and :weight , are passed as nested params like this

"exercise_sets"=>{"reps"=>"1", "weight"=>"1"}

So I would be tempted to try this:

e_params.permit(:id, exercise_sets: [:reps, :weight], :weightFormat, :time, :timeFormat, :distance, :distanceFormat, :exercise_id, :_destroy)

Note the nesting:

exercise_sets: [:reps, :weight]

Maybe that will do it.

Fixed the problem:

I was not passing the values as a hash, instead I was passing them as an array. I fixed it by changing the individual fields to:

<input type="text" name="exercise_sets[][reps]" class="form-control" />

<input type="text" name="exercise_sets[][weight]" class="form-control" />

... and so on.

In my case , i had the same problem send data for ajax with axios in params, the solution was added values in "data" instead "params"

axios({
        method:'patch',
        url:'/clients/'+ item +'/update.json',
        //params:{'client': {'info': info}},
        data:{authenticity_token:token,client:{info: info}},
        responseType:'json'
    })

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