I am using the cucumber step definitons provided by factory girl and I can not get something to work here.
First of all, here are the involved factories:
Factory.define :user do |u|
u.name {|n| "User#{n}" }
u.first_name {|n| "FirstName#{n}"}
u.last_name {|n| "LastName#{n}"}
u.password 'please'
u.password_confirmation 'please'
end
Factory.define :lecture do |l|
l.name {|n| "Lecture#{n}"}
l.abbreviation {|n| "lec#{n}"}
l.association :admin, factory: :user
end
Here is the step I am trying to execute:
And the following Lecture exists:
| Name | Abbreviation |
| Informatik A - Algorithmen und Datenstrukturen | ainf |
I am getting this error message and have absolutely NO idea where it comes from:
User(#42819220) expected, got User(#43753000) (ActiveRecord::AssociationTypeMismatch)
features/lectures/ui.feature:11:in `And the following Lecture exists:'
And here are my model definitions:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :rememberable, :trackable
# Setup accessible (or protected) attributes for your model
attr_accessible :name, :password, :password_confirmation, :remember_me, :first_name, :last_name
validates_uniqueness_of :name
has_many :administrated_lectures, class_name: "Lecture", foreign_key: "admin_id", dependent: :nullify
end
class Lecture < ActiveRecord::Base
validates_uniqueness_of :name
validates_uniqueness_of :abbreviation
scope :ordered, order("name")
belongs_to :admin, class_name: "User"
end
I am using this with spork btw.
Kind regards,
Nils
This is most likely because of Spork.
The error is because at some point the User constant is being reloaded, but FactoryGirl is still referencing the old constant. This is because you can unload constants like this:
Object.remove_const :User
See the line in this class:
https://github.com/thoughtbot/factory_girl/blob/master/lib/factory_girl/factory.rb#L27
You can see where this error occurs by breakpointing or just inspecting somewhere around these 2 places:
https://github.com/carlhuda/bundler/blob/1-0-stable/lib/bundler/runtime.rb#L68
https://github.com/rails/rails/blob/master/activesupport/lib/active_support/dependencies.rb#L519 (this class is the main place where you'll debug the problem)
My guess is that something is reloading ActiveRecord classes, but not reloading FactoryGirl. One way around this might be to reset the FactoryGirl definitions:
Spork.each_run do
# this isn't the correct api, something like this though.
FactoryGirl.definition_file_paths = [File.join(Rails.root, 'spec', 'factories')]
FactoryGirl.find_definitions
end
Hope that helps, Lance.
Oh, damn. Got it. I set cache_classes to false somewhere in the past because proper class reloading did not work for some reason. Just made it true again, and now it works. :/
Related
I was trying to follow the railscasts tutorial that explains how to handle mass-assignment errors and attr_accessible for admins, but since that was a little outdated, I'm trying to follow what's in the rails API dock for 3.2.6 here.
All I want to do is allow the admin user the ability to access the "winning" attribute for the Proposal Model on the Update action.
Here's my Proposal Model showing the current attr_accessible.
class Proposal < ActiveRecord::Base
attr_accessible :email, :email_confirmation, :link, :name, :references, :short_description
belongs_to :idea
Here's my code for the Proposal Controller's Update action.
class ProposalsController < ApplicationController
include ActiveModel::MassAssignmentSecurity
attr_accessible :email, :email_confirmation, :link, :name, :references, :short_description
attr_accessible :email, :email_confirmation, :link, :name, :references, :short_description, :winning, :as => :admin
def update
#idea = Idea.find(params[:idea_id])
#proposal = #idea.proposals.find(params[:id])
if #proposal.update_attributes(proposal_params)
redirect_to idea_proposals_url(#idea)
else
render 'edit'
end
end
protected
def proposal_params
role = current_user.admin ? :admin : :default
sanitize_for_mass_assignment(params[:proposal], role)
end
Check out this Railscast. I had a similar issue with an Admin field Boolean and didn't want any user to circumvent the security by sending a curl post. If the user is an admin then it gave them the ability to access the field, otherwise Mass Assignment would protect the field from being modified.
http://railscasts.com/episodes/237-dynamic-attr-accessible?view=asciicast
I know all the security reasons behind why mass-assigning is bad, what I cant figure out is why my app is trying to do a mass assign.
I am just trying to create a new record of my Section model and I am getting the "Can't mass-assign protected attributes" error. Below are the possible involved models. Can someone please explain to me how this is a mass-assigning? I am new to rails, so I could be missing something very simple.
class Section < ActiveRecord::Base
belongs_to :project
belongs_to :type, :foreign_key => 'type_id', :class_name => 'SectionType'
attr_accessor :order
end
class SectionType < ActiveRecord::Base
attr_accessible :name, :template
end
class Project < ActiveRecord::Base
has_many :sections
attr_accessible :description, :name, :short, :status, :subtitle, :version
def to_param
return name.gsub(/\s+/, '%20')
end
end
Any help would be greatly appreciated, I am new to rails and know this is probably a simple problem, but I have been trying to find an answer and can not.
If you're attempting to create a new Section object and that's failing, that'd be because you don't have any attributes listed as accessible inside that model. You will need to do that, using a similar call to attr_accessible as the one you have in your Project model already.
I have a method that works locally on my machine but it fails in Heroku. Heroku logs say:
NoMethodError (undefined method `events' for nil:NilClass)
I have used heroku console for an equivalent of this method and it works so there is data that supports it. The method is:
def index
#events = current_user.school.events
end
I am using Devise which I believe gives me the current_user method. The equivalent, a = User.first.school.events yields the true instance value with data. The User.first yields correct data.
Here are my models:
class School < ActiveRecord::Base
#validates_presence_of :name
has_many :events, :dependent => :destroy
has_many :users, :dependent => :destroy
belongs_to :user
belongs_to :event
def self.fetch_for_name(_name)
school = self.new(:name => _name)
end
end
class User < ActiveRecord::Base
belongs_to :school
rolify
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :name, :email, :password, :password_confirmation, :remember_me
end
class Event < ActiveRecord::Base
belongs_to :school
end
It would be like me if I overlooked some simple, basic thing but if I can do this correctly in Heroku console, why would this method break. Another unrelated page works correctly on Heroku.
current_user is the user that is logged in. It doesn't necessarily mean User.first. This should be the same locally as on Heroku. If you're having trouble figuring out what user is logged in you can add this to your application controller
before_filter :debug
def debug
Rails.logger.info("Current User is: #{current_user.inspect}")
end
And then view the output with $ heroku logs --tail It should show you the current value of the current_user. At the end of the day what #thesis said is correct, you have a user that does not have a school associated with it.
I have 3 models: Users, Customers, Issues. Below is the code for these models
Customer model:
class Customer < ActiveRecord::Base
belongs_to :se
belongs_to :user
has_many :issues
end
Issues model:
class Issue < ActiveRecord::Base
belongs_to :customer
end
Users model:
class User < ActiveRecord::Base
has_many :ses
has_many :customers
has_many :issues, :through => :customers
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :email, :password, :password_confirmation, :remember_me, :first_name, :last_name, :cell_ph, :area
end
I would like to display only the issues that belong to a particular user. I am having problems making this work. Can someone suggest how I might create an index method that would accomplish this?
Here is my index method where I'm trying to use devise's current_user method to identify the user who's logged in to the view:
def index
#issues = Issue.where(:user == :current_user)
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #issues }
end
end
You can't do what you're doing because an Issue doesn't have a user.
According to Rails guides (second example on http://guides.rubyonrails.org/association_basics.html#the-has_many-through-association session), you can nest the has_many using a has_many :through.
So you should be able to do this:
current_user.issues
In addition to Rodrigo's answer, you have some bad syntax on this line:
#issues = Issue.where(:user == :current_user)
That's never going to return any results because :user == :current_user is performing a comparison of two distinct Ruby Symbol objects. That always returns false, so your statement essentially equates to Issue.where(false).
This is closer to what you need:
#issues = Issue.where(:user => current_user)
This still doesn't fix the problem you have (Issue does not have many Users), but at least the meaning is correct.
I have been getting all kinds of conflicting information regarding this basic question, and the answer is pretty crucial to my current problems. So, very simply, in Rails 3, is it allowed or not allowed to use accepts_nested_attributes_for with a belongs_to relationship?
class User < ActiveRecord::Base
belongs_to :organization
accepts_nested_attributes_for :organization
end
class Organization < ActiveRecord::Base
has_many :users
end
In a view:
= form_for #user do |f|
f.label :name, "Name"
f.input :name
= f.fields_for :organization do |o|
o.label :city, "City"
o.input :city
f.submit "Submit"
Nested attributes appear to work fine for a belongs_to association as of Rails 4. It might have been changed in an earlier version of Rails, but I tested in 4.0.4 and it definitely works as expected.
The doc epochwolf cited states in the first line "Nested attributes allow you to save attributes on associated records through the parent." (my emphasis).
You might be interested in this other SO question which is along the same lines as this one. It describes two possible solutions: 1) moving the accepts_nested_attributes to the other side of the relationship (in this case, Organization), or 2) using the build method to build the Organization in the User before rendering the form.
I also found a gist that describes a potential solution for using accepts_nested_attributes with a belongs_to relationship if you're willing to deal with a little extra code. This uses the build method as well.
For belongs_to association in Rails 3.2, nested model needs the following two steps:
(1) Add new attr_accessible to your child-model (User model).
accepts_nested_attributes_for :organization
attr_accessible :organization_attributes
(2) Add #user.build_organization to your child-controller (User controller) in order to create column organization.
def new
#user = User.new
#user.build_organization
end
For Ruby on Rails 5.2.1
class User < ActiveRecord::Base
belongs_to :organization
accepts_nested_attributes_for :organization
end
class Organization < ActiveRecord::Base
has_many :users
end
Just got to your controller, suppose to be "users_controller.rb":
Class UsersController < ApplicationController
def new
#user = User.new
#user.build_organization
end
end
And the view just as Nick did:
= form_for #user do |f|
f.label :name, "Name"
f.input :name
= f.fields_for :organization do |o|
o.label :city, "City"
o.input :city
f.submit "Submit"
At end we see that #user3551164 have already solved, but now (Ruby on Rails 5.2.1) we don't need the attr_accessible :organization_attributes