Я работаю над обновлением устаревшего приложения до рельсов 4, и я получаю необъяснимое (по крайней мере, мне) ForbiddenAttributesError
.
У меня есть белый список параметров, прежде чем использовать их для создания нового экземпляра Station
, но по какой-то причине я все еще получаю
ForbiddenAttributesError
. Есть ли способ получить дополнительную информацию о том, какой атрибут вызывает ошибку?
** ИЗМЕНИТЬ. Я использую Devise и CanCan. Если я удалю load_and_authorize_resource
, ошибки исчезнут (и авторизация тоже!). Я пробовал решения на https://github.com/ryanb/cancan/issues/835 безрезультатно.
rspec spec/контроллеры/station_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