rails accepts_nested_attributes_for and validations... Rails 2.3.11 - ruby-on-rails

I have two models
class Group < AR
has_many :permissions
accepts_nested_attributes_for :permissions, :allow_destroy => true
end
class Permission < AR
validates_uniqueness_of :action, :scope => [:role]
end
I can't seem to get the unique constraint on permissions to work when creating a new group, only on update. Here's a sample output. Does anyone know the best way to get validation to work on nested attributes and unique constraints?
sample output
> g = Group.create(:permissions_attributes => [{:role => 'admin', :action => 'one'}])
> # Now add the same permissions, should not be valid
> g.permissions_attributes = [{:role => 'admin', :action => 'one'}]
> g.valid? # => false
That is expected. However if I create the Group with the same permissions_attributes twice, it doesn't invalidate:
> g = Group.new(:permissions_attributes => [{:role => 'admin', :action => 'one'}, {:role => 'admin', :action => 'one'}]
> g.valid? # => true BUT THIS SHOULD BE FALSE!!
> g.save # => true Oh Nos!!!

class Group < AR
has_many :permissions
accepts_nested_attributes_for :permissions, :allow_destroy => true
validates_associated :permissions
end

Related

Unknown key find_options during database migration

I'm trying to update an old Redmine plugin but when I try to do the migration I get this error. Could someone give me some pointers how to address the problem?
I tried to replace find_options with scope but I'm not exactly sure how do to it.
rake aborted!
ArgumentError: Unknown key: :find_options. Valid keys are: :type, :permission, :timestamp, :author_key, :scope
/home/developer/projects/redmine/redmine-3.3.1/lib/plugins/acts_as_activity_provider/lib/acts_as_activity_provider.rb:32:in `acts_as_activity_provider'
Migration file:
require File.join(File.dirname(__FILE__), '../../app/models', 'hudson_build')
class UpdateBuilding < ActiveRecord::Migration
def self.up
HudsonBuild.update_all "building = 'true'", "building = 't'"
HudsonBuild.update_all "building = 'false'", "building = 'f'"
end
def self.down
HudsonBuild.update_all "building = 't'", "building = 'true'"
HudsonBuild.update_all "building = 'f'", "building = 'false'"
end
end
part of my hudson_build.rb model that's causing the problem:
require 'hudson_api_error'
require 'hudson_exceptions'
require 'rexml_helper'
include RexmlHelper
class HudsonBuild < ActiveRecord::Base
unloadable
has_many :changesets, :class_name => 'HudsonBuildChangeset', :dependent => :destroy
has_one :test_result, :class_name => 'HudsonBuildTestResult', :dependent => :destroy
has_many :artifacts, :class_name => 'HudsonBuildArtifact', :dependent => :destroy
belongs_to :job, :class_name => 'HudsonJob', :foreign_key => 'hudson_job_id'
belongs_to :author, :class_name => 'User', :foreign_key => 'caused_by'
validates_presence_of :hudson_job_id, :number
validates_uniqueness_of :number, :scope => :hudson_job_id
acts_as_event :title => Proc.new {|o|
retval = "#{l(:label_build)} #{o.job.name} #{o.number}: #{o.result}" unless o.building?
retval = "#{l(:label_build)} #{o.job.name} #{o.number}: #{l(:notice_building)}" if o.building?
retval
},
:description => Proc.new{|o|
items = []
items << o.test_result.description_for_activity if o.test_result != nil
items << HudsonBuildChangeset.description_for_activity(o.changesets) if o.changesets.length > 0
items.join("; ")
},
:datetime => :finished_at
acts_as_activity_provider :type => 'hudson',
:timestamp => "#{HudsonBuild.table_name}.finished_at",
:author_key => "#{HudsonBuild.table_name}.caused_by",
:find_options => {:include => {:job => :project}},
:permission => :view_hudson
include HudsonHelper
extend RexmlHelper
I don't know this plugin but i found this commit
Please try changing in HudsonBuild class this line:
:find_options => {:include => {:job => :project}},
to
:scope => includes(:project),
Here is an example.

Rails association : update association parameter (make admin/remove admin)

So I have a User model, and a Group model which has several users thanks to the GroupUserAssociation model. Here's how my relationships are defined:
class Group < ActiveRecord::Base
has_many :group_users, :class_name => 'GroupUserAssociation', :foreign_key => :group_id
has_many :group_admins, :class_name => 'GroupUserAssociation', :foreign_key => :group_id, :conditions => ['level = 1']
has_many :group_not_admins, :class_name => 'GroupUserAssociation', :foreign_key => :group_id, :conditions => ['level = 0']
has_many :users, :through => :group_users, :source => :user
has_many :admins, :through => :group_admins, :source => :user
has_many :not_admins, :through => :group_not_admins, :source => :user
end
If I want to add/remove users to group, there is an elegant way to write it (elegant because it doesn't involves the GroupUserAssociation object):
Group.first.users << User.first # Adds to group
Group.first.users.delete(User.first) # Removed from group
But if I do
Group.first.admins << User.first
Group.first.admins.delete(User.first)
it also deletes the association (hence has the same effect as the first lines).
Is there an elegant way (without handling the GroupUserAssociation object to promote/demote admin (= to update GroupUserAssociation.level from 1 to 0) ?
I could do
Group.first.users.delete(User.first) # Removed from group
Group.first.admins << User.first
But that would mean 2 times commiting to DB which is not really good...
I read there are some nice things for this in Rails 4, but unfortunately I'm using Rails 3.2...
Thanks
We do this using this code:
#config/routes.rb
resources :entries do
post :category
delete ":category_id", to: :category, as: "remove_category"
end
#Categories
def category
entry = #entry = Entry.find(params[:entry_id])
category = #category = Category.find(params[:category_id])
#Actions
entry.categories << category if request.post? && !entry.categories.include?(category)
entry.categories.delete(category) if request.delete?
#Return
respond_to do |format|
format.html { redirect_to collection_path }
format.js
end
end

after_save error in ruby on rails

I have two models linked to each other and I am trying to do an after_save, create in the model and code is as follows.
class CustomerBill < ActiveRecord::Base
after_save :updating_and_creating_ledger_items
has_many :customer_ledgers, :dependent => :destroy
def updating_and_creating_ledger_items
CustomerLedger.create(:date => self.date, :customer_id => self.customer_id, :user_id => self.user_id)
end
end
customer ledger model
class CustomerLedger < ActiveRecord::Base
belongs_to :customer_bill, :foreign_key => "customer_bill_id"
end
Now the problem is the program executes perfectly but the value are not been put in the database. If I check Customer ledger it is still empty.
The values are not getting stored. what seems to be the problem? Guidance towards this matter will be helpful.
Thanks in advance. :)
Add
validates_associated :customer_ledgers
In customer_bill.rb
Try
ledger = customer_ledgers.build(:date => self.date, :customer_id => self.customer_id, :user_id => self.user_id)
ledger.save
EDITED for to avoid Validations, use
ledger = customer_ledgers.build(:date => self.date, :customer_id => self.customer_id, :user_id => self.user_id)
ledger.save(:validate => false)
The CustomerLedger may be failing a validation check. Replace:
def updating_and_creating_ledger_items
CustomerLedger.create(:date => self.date, :customer_id => self.customer_id, :user_id => self.user_id)
end
with:
def updating_and_creating_ledger_items
ledger = customer_ledgers.build(:date => self.date, :customer_id => self.customer_id, :user_id => self.user_id)
ledger.save(:validate => false)
end
You're not setting the customer_bill_id in the create, change create to build as so:
customer_ledger.build(:date => self.date, :customer_id => self.customer_id, :user_id => self.user_id)

Rails has_many build method as a polymorphic resource

class OrganizationModuleAttachment < ActiveRecord::Base
belongs_to :attachable, :polymorphic => true
end
class Document < ActiveRecord::Base
has_many :organization_module_attachments, :as => :attachable, :dependent => :destroy
def organization_module_attachment_ids=(values)
(values || []).each_with_index do |organization_module_id, index|
organization_module_attachments.build(:organization_module_id => organization_module_id, :attachable_type => "Document", :position => index + 1)
end
end
end
form.html.haml:
= f.select :organization_module_attachment_ids, options_for_select((#organization_modules || []).collect { |a| [a.name, a.id] }, (#document.organization_modules || []).collect { |a| a.id }), {}, { :class => "multiselect", :multiple => true }
So in the document class I am trying to build organization_module_attachments. I get an error in the creation of the organization module attachment when I submit the form. I think rails is assuming the foreign key on an attachment is :document_id, when in fact it is polymorphic and is therefore :attachable_id. If I explicitly set the :attachable_id in the build method it works fine.
I've tried a number of things and searched around for a few days with no luck. Does anyone know how to do this?

Rails XML :include

Here are my models:
class User < ActiveRecord::Base
...
belongs_to :picture, :foreign_key => 'picture_id',
:class_name => 'UploadedFile',
:dependent => :destroy
has_many :enrolled_groups, :through => :interests
...
end
class Group < ActiveRecord::Base
has_many :enrolled_users, :through => :interests,
:source => :user
end
I want to get an XML feed for my Groups with the enrolled users and their picture information.
The following line works fine (just with the enrolled users):
render :xml => #group.to_xml(:include => [:enrolled_users] )
How can I also include the picture info in the feed? I tried a bunch of things but can't figure it out... any idea?
If doing .to_xml(:include => [:enrolled_users, :picture]) doesn't work, then the hacky way would be to add (in User class):
def attributes
super.merge(:picture => picture)
end
You should be able to access nested resources by something like this:
render :xml => #group.to_xml(:include => [{:enrolled_users => :picture}])
I couldn't get it to work with the other proposed solutions. The way I ended up doing it was as follow:
In the controller:
render :xml => #group.to_xml(:include => {:enrolled_users => {:methods => :picture_url}})
In the model:
def picture_url
HOST+picture.public_filename(:avatar)
end

Resources