[英]ForbiddenAttributesError in Rails 4
我正在努力將遺留應用程序升級到rails 4,我得到了一個無法解釋的(至少對我而言) ForbiddenAttributesError
。
在使用它們創建一個新的Station
實例之前,我已將列表列入白名單但由於某種原因我仍然得到ForbiddenAttributesError
。 有沒有辦法獲得有關哪個屬性導致錯誤的更多信息?
**編輯。 我正在使用Devise和CanCan。 如果我刪除load_and_authorize_resource
,錯誤就會消失(以及授權!)。 我在https://github.com/ryanb/cancan/issues/835上嘗試過這些解決方案但沒有用。
rspec spec / controllers / stations_controller_spec.rb
1) StationsController POST 'create' invalid should not create a new record
Failure/Error: post :create, :station => { :name => 'foo' }
ActiveModel::ForbiddenAttributesError:
ActiveModel::ForbiddenAttributesError
# ./spec/controllers/stations_controller_spec.rb:67:in `block (5 levels) in <top (required)>'
# ./spec/controllers/stations_controller_spec.rb:66:in `block (4 levels) in <top (required)>'
2) StationsController POST 'create' valid should create a new record
Failure/Error: before { post :create, :station => FactoryGirl.attributes_for(:station, :hw_id => rand(1000)) }
ActiveModel::ForbiddenAttributesError:
ActiveModel::ForbiddenAttributesError
# ./spec/controllers/stations_controller_spec.rb:73:in `block (4 levels) in <top (required)>'
3) StationsController POST 'create' valid
Failure/Error: before { post :create, :station => FactoryGirl.attributes_for(:station, :hw_id => rand(1000)) }
ActiveModel::ForbiddenAttributesError:
ActiveModel::ForbiddenAttributesError
# ./spec/controllers/stations_controller_spec.rb:73:in `block (4 levels) in <top (required)>'
schema.rb
create_table "stations", :force => true do |t|
t.string "name"
t.string "hw_id"
t.float "lat"
t.float "lon"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "timezone"
t.float "balance"
t.integer "user_id"
t.boolean "down"
end
station_controller.rb
...
# POST /stations
# POST /stations.xml
def create
@station = Station.new(station_params)
@station.set_timezone!
logger.debug("@station " + @station.inspect)
respond_to do |format|
if @station.save
format.html { redirect_to(@station, :notice => 'Station was successfully created.') }
format.xml { render :xml => @station, :status => :created, :location => @station }
format.yaml { render :status => :ok, :nothing => true }
else
# create users list if the station cannot be created
@users = User.all_users_select(current_user)
format.html { render :action => "new" }
format.xml { render :xml => @station.errors, :status => :unprocessable_entity }
format.yaml { render :status => :unprocessable_entity, :nothing => true }
end
end
end
...
# whitelists params for mass assignment
def station_params
params.require(:station).permit(
:user_id, :name, :hw_id, :measures, :lat, :lon, :authenticity_token, :commit
)
end
station_controller_spec.rb
describe "POST 'create'" do
describe "invalid" do
it "should not create a new record" do
expect do
post :create, :station => { :name => 'foo' }
end.to_not change(Station, :count)
end
end
describe "valid" do
before { post :create, :station => FactoryGirl.attributes_for(:station, :hw_id => rand(1000)) }
it "should create a new record" do
expect do
post :create, :station => FactoryGirl.attributes_for(:station, :hw_id => rand(1000))
end.to change(Station, :count)
end
subject { response }
it { should redirect_to station_path(assigns(:station)) }
end
end
工廠/ station.rb
FactoryGirl.define do
factory :station do
name "Test Staton"
hw_id Time.now.to_s
lat 63.401839
lon 13.072183
end
factory :invalid_station, class: Station do
name nil
end
end
車型/ station.rb
#include Geokit::Geocoders
class Station < ActiveRecord::Base
#acts_as_mappable :default_units => :kms,
# :lat_column_name => :lat,
# :lng_column_name => :lon
belongs_to :user
has_many :measures, :dependent => :destroy
has_one :current_measure, :class_name => "Measure"
# arduino client has not memory enough to post the station name so it cannot be required!
validates :hw_id, :presence => true # must have a hw_id
validates :hw_id, :uniqueness => true # and the hw_id must be unique
# Geocoder gem attribute mapping
geocoded_by :name, :latitude => :lat, :longitude => :lon
def owned_by?(owner)
user==owner
end
def calibrate_speed(speed)
speed/250
end
def self.send_low_balance_alerts
stations = Station.find(:all)
stations.each do |station|
logger.info "Checking station #{station.name}"
logger.info "Last measure at #{station.current_measure.created_at}"
if station.balance/100 < 15 && !station.down
if !station.user.nil?
logger.info "Send reminder to owner #{station.user}"
UserMailer.notify_about_low_balance(station.user, station).deliver
end
end
end
end
def self.send_down_alerts
stations = Station.find(:all)
stations.each do |station|
logger.info "Checking station #{station.name}"
logger.info "Last measure at #{station.current_measure.created_at}"
if station.current_measure.created_at < 15.minutes.ago && !station.down
station.down = true
station.save
if !station.user.nil?
logger.info "Send reminder to owner #{station.user}"
UserMailer.notify_about_station_down(station.user, station).deliver
end
end
end
end
def self.get_timezone(lat, lon)
timezone = Timezone::Zone.new :latlon => [lat, lon]
timezone.active_support_time_zone
end
def set_timezone!
if (!self.lat.nil? && !self.lon.nil?)
self.timezone = Station.get_timezone(self.lat, self.lon)
end
end
end
這完全是一個問題,CanCan與Rails 4不兼容,與我的Station
模型或控制器無關。
我的解決方法是skip_load_resource
用於create
操作。
before_filter :authenticate_user!, :except => [:show, :index]
load_and_authorize_resource :except => [:show, :index]
skip_load_resource :only => [:create]
砰! 一切都變綠了。
UPDATE。 查看CanCanCan它是現在死亡康康的延續,並具有Rails 4強大的參數支持等功能。
一個電台屬於一個用戶嗎? 我認為你不應該為user_id提供強大的參數。 user_id應該通過模型的設置方式自動生成。 所以你強大的params代碼應該是:
def station_params
params.require(:station).permit(
:name, :hw_id, :measures, :lat, :lon, :authenticity_token, :commit #user_id taken out
)
end
另外,你的意思是讓hw_id成為一個字符串嗎? 通常當某事說id是一個整數。 此外,如果hw是與站具有某種類型關系的模型,則它也不應該在強參數中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.