I'm building a daily deal app to learn RoR.
My question is about attr_accessible
and how to test a model where attributes are protected against mass-assignment.
I have 3 Models in my app:
Basically Deals belongs_to Admin_users and I want only admin users sot be able to publish Deals.
The problem I have is that if I am not wrong, I needed to put all attributes attr_accessible
so that I can create a form and save a Deal and then, to protect attributes (especially admin_user_id) I added with_role
as: :admin
to protect them and make only accessible to an admin (I used this as inspiration: http://ejholmes.github.io/2012/04/22/handling-mass-assignment-with-active-admin.html )
My problem is that RSpec tests that were working before putting as: :admin
, are now failing and the error message I get is:
ActiveModel::MassAssignmentSecurity::Error:
Can't mass-assign protected attributes: url_path, country, title, description, twitter_msg, image_url, prelaunch_date, deal_launch_date, deal_end_date, featured, admin_user_id
I think RSpec does not get I am an admin so I have the right to mass assign theses attributes.
How can I solve this?
Here are my files for reference:
deal_spec.rb
class Deal < ActiveRecord::Base
belongs_to :admin_user, :foreign_key => 'admin_user_id'
attr_accessible :url_path,
:country,
:title,
:description,
:twitter_msg,
:image_url,
:prelaunch_date,
:deal_launch_date,
:deal_end_date,
:featured,
:admin_user_id,
:as => :admin_user
validates :title,
presence: true,
length: { maximum: 200 }
My active admin set up: on initializers/active_admin.rb
ActiveAdmin.setup do |config|
config.site_title = "My App"
config.logout_link_path = :destroy_admin_user_session_path
config.batch_actions = true
# got it on http://ejholmes.github.io/2012/04/22/handling-mass-assignment-with-active-admin.html
module ActiveAdmin
class BaseController
with_role :admin_user
end
end
end
The factory for admin_users:
FactoryGirl.define do
factory :admin_user do
sequence(:email) { |n| "person_#{n}@example.com"}
password "admin_pass"
password_confirmation "admin_pass"
end
end
And the TEST that is actually failing: it's an example on the title lenght test:
require 'spec_helper'
require 'date'
describe Deal do
let(:admin_user) { FactoryGirl.create(:admin_user) }
before(:each) do
@attr = {
url_path: "lorem ipsum",
country: "France",
title: "lorem ipsum",
description: "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum",
twitter_msg: "http://www.example.com",
image_url: "http://www.example2.com",
prelaunch_date: 2.days.from_now.change(hour: 10),
deal_launch_date: 3.days.from_now.change(hour: 10),
deal_end_date: 15.days.from_now.change(hour: 10),
featured: true,
admin_user_id: 1
}
describe "tests TITLES" do
it { should validate_presence_of(:title) }
it "should reject title that is too long" do
long = "a" * 211
hash = @attr.merge(:title => long)
Deal.new(hash).should have(1).error_on(:title)
end
end
I feel I haven't told my deal_rspec.rb test file that :admin_user is really an admin! I don't know how to do it and even if I am protecting well my Deal model attributes against mass assignment. Does anybody know how I can make these tests pass again?
The problem here is that the :as => :admin flag is not referring to an active_record model, it's just an a arbitrary symbol your defining. Using it means you need to pass as: :admin in the create call like this
Deal.create(params[:deal], as: :admin)
So your actual problem is probably with your factory, since it doesn't know to pass the flag when it makes your object. Try something like this
factory :deal do
my_attr "abc"
initialize_with do
create(attributes, as: :admin)
end
end
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.