neanderslob
neanderslob

Reputation: 2703

Using an array to define strong params

I have a form that I'm creating with an ENORMOUS list of questions. Rather than hard-code all these out in html.

I'm planning on storing them in a table called questions and populating a questionnaire view by looping through the table with a script that pulls both the text of the question from one column, and its corresponding parameter from another.

The answers will be stored in a Questionnaire model and table. This seems relatively straight-forward, except when dealing with strong params.

So I have the model Question, and table questions. Which contains the columns the_questions and the_parameters.

The questions contained in that table correspond to fields for the model Questionnaire. I would like to query the database to get an array of the parameters and then drop them into the strong params in the questionnaire controller.

So rather than:

def questionnaire_params
  params.require(:questionnaire).permit(:an, :enormous, :list, :of, :params.....)
end

I'd like to do something like:

def questionnaire_params
  @my_params=Questions.the_parameters
  params.require(:questionnaire).permit(@my_params)
end

Is there any way to do this? Am I way out in left field with this idea? Any guidance or admonishment would be appreciated.

Upvotes: 1

Views: 440

Answers (6)

Yen-Ju
Yen-Ju

Reputation: 477

ActionController::Parameters takes an array:

$ bin/rails c
> params = ActionController::Parameters.new(user: {name: 'John', age: 22})
=> {"user"=>{"name"=>"John", "age"=>22}} 
> permitted = params.require(:user).permit(:name, :age)
=> {"name"=>"John", "age"=>22} 
> permitted = params.require(:user).permit([:name, :age])
=> {"name"=>"John", "age"=>22} 
> permitted = params.require(:user).permit(*[:name, :age])
=> {"name"=>"John", "age"=>22} 
> permitted = params.require(:user).permit('name', 'age')
=> {"name"=>"John", "age"=>22}

Therefore, you can just pass your @my_params as an array into permit.

Upvotes: 0

max
max

Reputation: 102388

You don't need an enormous list of different parameters to do something as simple as a questionnaire. You're just doing it wrong. And you don't want to stuff a params whitelist in the DB. It would be slow and cause some real headaches when it comes to software versioning.

A fairly standard design for a questionnaire would be something like this:

<%= form_for(:questions, controller: 'questions', action: 'create') do |form| %>
    <% @questions.each do |question| %> 
        <fieldset>
        <%= fields_for(question) do |qf| %>
          <legend><%= question.title %></legend>
          <%= qf.collection_check_boxes :answer_ids, question.answers, :id, :text %>
        <% end %>
        </fieldset>
    <% end %>
<% end %> 

The params:

params.require(:questions).allow(question: [:answer_ids])

Upvotes: 0

margo
margo

Reputation: 2927

You may want to reconsider how you are modelling you application. Usually when you need to manipulate strong params, it is an indication of a code smell.

How are questions and answers and questionnaires related? As an alternative, consider this modelling:

  • a questionnaire has_many answers and has_many questions through answers
  • an answer belongs_to a question and belongs_to a questionnaire
  • a question has_many answers

You can get to the question through the answer. Your strong params for questionnaire would then be

params.require(:questionnaire).permit(
  answers_attributes: [:id, :question_id, :text]
)

Upvotes: 2

Andrey Deineko
Andrey Deineko

Reputation: 52377

I would like to query the database to get an array of the parameters and then drop them into the strong params in the questionnaire controller.

This would mean, you'll permit all and each attribute to be massassigned.

To do so you just need to use permit! method, which will whitelist every model's attribute:

params.require(:questionnaire).permit! # I don't want to even start discussing downsides of whitelisting all attributes

If you though have some attributes, you don't want to allow to be mass assigned and still want to use array, you can define

def questionnaire_params
  @all_attributes = Model.column_names.map(&:to_sym)
  @not_permitted = [:id, :some_other_attribute]
  params.require(:questionnaire).permit(@all_attributes - @not_permitted)
end

Upvotes: 3

Vrushali Pawar
Vrushali Pawar

Reputation: 3803

params.require(:questionnaire).permit(Questionaire.column_names.map(&:to_sym))

Check if this works for you.

Upvotes: 1

sethi
sethi

Reputation: 1889

I tried something like (Not sure if i got your question right though)

params.require(:parent).permit(ModelName.column_names)

But then you are defeating the purpose of strong params.

Try

params.require(:parent).permit(Parent.column_names - blacklist_array )

as in

params.require(:parent).permit(Parent.column_names - [:tax_num , :age])

Upvotes: 1

Related Questions