Cant mass-assign protected attributes issue - ruby-on-rails-3

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.

Related

Uniqueness validation with a has_many relationship

My model structure is as follows:
class Client < ActiveRecord::Base
has_many :charts
end
class Chart < ActiveRecord::Base
belongs_to :client
has_many :chart_data
end
class ChartDatum < ActiveRecord::Base
belongs_to :chart
end
ChartDatum has an attribute called 'name' which needs to be unique for each client.
I tried using "validates_uniqueness_of :name, :scope => [:chart_id]" but this helped me getting a unique key for a particular chart but not for all charts for a particular client. I am looking for something like "validates_uniqueness_of :name, :scope => [:client_id]" but obviously with the current structure it will not work out.
Could someone please help me?
Since you need unique name for chart_data for each client, you can try writing a custom validation for name something like this :
class ChartDatum < ActiveRecord::Base
belongs_to :chart
validates :name, :uniqueness => true, unless => :unique_for_client?
def unique_for_client?
client = self.chart.client
client.charts.chart_data.pluck(:name).include?(self.name)
end
end

rails spree has_many through association

'm trying to tweek Spree to my needs and I've hit a bump. I'll try to explain as best as I can without pasting too much code, 'cause Spree has quite a lot of it...
For starters. I've extended OptionType like this
Spree::OptionType.class_eval do
PRODUCT_TYPES = SuperMap.new( [:default, 0],
[:vehicle_bonnet, 1],
[:vehicle_images, 2])
super_mapped_attr :product_type, PRODUCT_TYPES
attr_accessible :product_type
end
I want to check in the show view of the ProductsController what sort of product_type I'm dealing with, like this:
<% if #product.option_types.product_type_key == :vehicle_bonnet %>
...
<% end %>
and I get undefined method ``product_type_key'. This method should be available thanks to SuperMap.
Now, the Product and OptionType has a bit strange association (for me at least).
module Spree
class Product < ActiveRecord::Base
has_many :product_option_types, :dependent => :destroy
has_many :option_types, :through => :product_option_types
end
end
so far seems to be ok.
module Spree
class ProductOptionType < ActiveRecord::Base
belongs_to :product
belongs_to :option_type
acts_as_list :scope => :product
end
end
and now comes the weird part:
module Spree
class OptionType < ActiveRecord::Base
has_many :option_values, :order => :position, :dependent => :destroy
has_many :product_option_types, :dependent => :destroy
has_and_belongs_to_many :prototypes, :join_table => 'spree_option_types_prototypes'
attr_accessible :name, :presentation, :option_values_attributes
validates :name, :presentation, :presence => true
default_scope :order => "#{self.table_name}.position"
accepts_nested_attributes_for :option_values, :reject_if => lambda { |ov| ov[:name].blank? || ov[:presentation].blank? }, :allow_destroy => true
end
end
this is actually the whole OptionType model. What suprises me it doesn't have has_many :products, through: :product_option_types. I've tried to add this line to my extension, but didn't help. I've tried few other thing of course, but it just made such a mess I went back to this version, since I think it shows best what I'm trying to achieve. What am I missing?
EDIT (solved, I should hope so...):
Turned out that in the Product model there was an alias alias :options :product_option_types, which was (imho) in the wrong place, because somewhere in the middle of a quite a long model (I should think it should have been somewhere closer to the has_many, but that's just me).
Further more, the options turned out to be an array, no that shocking come to think of it. So, what I did is extended the product model, added a method, where I'm checking the product_type_key, like so:
def type_of_product?(type)
options.each do |opts|
if opts.option_type.product_type_key == type
return true
end
end
false
end
Not the prettiest method, but it works as I expect it to...

Can't mass-assign protected attributes with has_many association and create

This is EXTREMELY bizarre. I'm upgrading a Rails 2.3.12 app and running into this same problem over and over again. I'm stumped and nothing else out there seems to touch on it.
I have two models:
class User < ActiveRecord::Base
has_many :logs, :class_name => 'UserLog'
end
and
class UserLog < ActiveRecord::Base
attr_accessor :site_id, :controller, :action, :url, :session
belongs_to :user
validates_presence_of :user
end
then in another controller I'm doing this:
def log_user_activity
#current_user.logs.create(:site_id => #site.id, :controller => params[:controller],
:action => params[:action], :url => request.path,
:session => request.session_options[:id]) if #current_user
end
as you can see, it's pretty straightforward but when I call log_user_activity I'm getting this:
Can't mass-assign protected attributes: site_id, controller, action, url, session
HOWEVER, if I change all my creates or builds to this:
def log_user_activity
log = #current_user.logs.new
log.site_id = #site.id
log.controller = params[:controller]
log.action = params[:action]
log.url = request.path
log.session = request.session_options[:id]
log.save
end
then it works fine!?
Has anyone seen this? Any clues?
In class UserLog, add the following:
attr_accessible :site_id, :controller, :action, :url, :session
The reason you have to use attr_accessible is most likely because you are utilizing a plugin that is relying on this being present for a model. It has happened to all of us and is a royal pita)
Once attr_accessible is designated for a class, then any attribute that is not specified as 'accessible' will not be allowed to be updated.

trouble saving to intersect table following railscast

I'm trying to create nested attributes as outlined in this railscast http://railscasts.com/episodes/167-more-on-virtual-attributes?view=asciicast
In my example, I am trying to associate an activity to an image, so I have a structure of activity -> activity_image -> image.
When I save my activity, rails creates the activity and the image, but I'm not getting the intersecting table of activity_image being saved. Of course, I never actually tell rails to save this, but neither does the railscast I'm following.
Is there some way this is supposed to be defined in the models? What have I got wrong?
class Activity > ActiveRecord::Base
attr_accessible :title, :description, :activity_image_url
belongs_to :user
has_many :activity_images
has_many :image_urls, :through => :activity_images
#validates_presence_of :title, :description, :url
attr_accessor :activity_image_url
after_save :assign_image
private
def assign_image
if #activity_image_url
self.activity_image_url = ImageUrl.find_or_create_by_url(#activity_image_url)
end
end
end

WARNING: Can't mass-assign protected attributes

I get this error "WARNING: Can't mass-assign protected attributes: races_attributes"
, when following this http://railscasts.com/episodes/196-nested-model-form-part-1 on rails 3.
Where Races are a component of Events. This is my models/race.rb:
class Race < ActiveRecord::Base
belongs_to :event
attr_accessible :name, :unit
end
This is my models/event.rb:
class Event < ActiveRecord::Base
has_many :races, :dependent => :destroy
accepts_nested_attributes_for :races
attr_accessible :name, :date, :description, :location_name, :address_one, :address_two, :city, :state, :zip, :active, :races_attributes
end
Any Ideas?
Shorter than using attr_accessible, safer than using whitelist_attributes: attr_protected
Just indicate the protected attributes, and Rails will infer that all others can be mass-assigned:
class MyClass < ActiveRecord::Base
attr_protected :id
end
(I always have way more attributes that I want mass-assigned than the ones I want protected.)
attr_accessible specifies that you can not mass-assign attributes, using save method, for example. So, if you change an attribute that is not defined with attr_accessible, you will get a warning because it will not actually be saved in the database.