Może bardziej zaawansowani szybko połapali się jak wykorzystywać strong_parameters ale nieźle się nagłowiłem zanim doszedłem jak zapisywać parametry tablicowe pochodzące z formularzy więc ku pamięci i dla mniej zaawansowanych (takich jak ja )
Cały kod w uproszczeniu, tylko tyle by przedstawić problem.
Mam trzy modele
[code=ruby]class Library < ActiveRecord::Base
has_many :articles_libraries, dependent: :delete_all
has_many :articles, through: :articles_libraries
end
class Article < ActiveRecord::Base
has_many :articles_libraries, dependent: :delete_all
has_many :libraries, through: :articles_libraries
end
class ArticlesLibrary < ActiveRecord::Base
belongs_to :article
belongs_to :library
end[/code]
I formularz wprowadzania danych dla artykułu:
[code=ruby]<%= form_for(@article) do |f| %>
<% if @article.errors.any? %>
<%= t(“activerecord.errors.template.header”, count: @article.errors.count) %>
<%= t “activerecord.errors.template.body” %>
<ul>
<% @article.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br/>
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :library_ids %><br/>
<%= f.select :library_ids, Library.all.map{|l| [l.name,l.id]}, {}, {multiple: true} %>
</div>
<div class="field">
<%= f.label :content %><br/>
<%= f.text_area :content %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>[/code]
W wcześniejszych wersjach RoR wystarczyło w modelu Article dopisać jedną linię:
[code=ruby]class Article < ActiveRecord::Base
has_many :articles_libraries, dependent: :delete_all
has_many :libraries, through: :articles_libraries
attr_accessible :title, :content, :library_ids
end[/code]
Strong_parameters przenosi tą funkcjonalność do kontrolera czyli nie dodajemy attr_accessilble w modelu natomiast w kontrolerze mamy (metoda article_params ma pełnić funkcję analogiczną do attr_accessible):
[code=ruby]class ArticlesController < ApplicationController
(…)
def create
@article = current_user.articles.build(article_params)
(…)
end
def update
respond_to do |format|
if @article.update(article_params)
format.html { redirect_to @article, notice: t(‘articles.flash.update’) }
else
format.html { render action: ‘edit’ }
end
end
end
(…)
private
# Never trust parameters from the scary internet, only allow the white list through.
def article_params
params.require(:article).permit(:title, :content, :library_ids )
end
end[/code]
Niestety to nie działa . Możemy sobie w formularzu zmieniać biblioteki, do których ma należeć artykuł a efektów nie widać.
Przyczyną jest to, że strong_parameters obsługuje jedynie dane skalarne a params[:article][:library_ids] jest tablicą. Trzeba zmienić zmienić metodę article_params
class ArticlesController < ApplicationController
(...)
private
# Never trust parameters from the scary internet, only allow the white list through.
def article_params
params.require(:article).permit(:title, :content, library_ids: [] )
end
end
Powodzenia w przechodzeniu na Rails 4.