I have the following models:
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :name, :email, :password, :password_confirmation, :remember_me
has_many :rulesets
end
class Ruleset < ActiveRecord::Base
attr_accessible :title, :game_id, :user_id
validates :game_id, presence: true
validates :user_id, presence: true
validates :title, presence: true
belongs_to :user
belongs_to :game
has_many :rules
end
class Rule < ActiveRecord::Base
attr_accessible :description, :ruleset_id
belongs_to :ruleset
validates :description, presence: true
validates :ruleset_id, presence: true
end
I have a controller called PagesController that controls the user dashboard, where I want to display the number of rulesets and number of rules that a user has. this is my controller
class PagesController < ApplicationController
def home
end
def dashboard
#rulesets = current_user.rulesets
end
end
In my dashboard view, I'm attempting to display the rulesets and rules counts as such:
<% if current_user.rulesets.any? %>
<li><%= #rulesets.count %> Ruleset</li>
<li><%= #rulesets.rules.count%> Rules</li>
<% end %>
This returns the right number of rulesets if I just try and count the rulesets. When I try and count the rules, I get this and "undefined method `rules'" error. How am I supposed to access the rules that are in the users' ruleset?
You need to count all of the rulesets and the rules for each ruleset. Use something like:
#rulesets.collect {|r| r.rules.count}.sum
Rules would be associated to a particular ruleset. You should specify the ruleset, by id, and then use the ".rules.count" to count all rules associated with THAT ruleset.
Related
I have the following model in my project
class Attribute < ApplicationRecord
validates :name, presence: true
validates :name, uniqueness: true
has_many :attribute_vals
end
and I am trying to do the following in my view
<div id="attributes_list">
<%= #attributes.each do |attr| %>
<% attr.attribute_vals.each do |val| %>
- <%= val.name %>
<% end %>
<% end %>
</div>
where #attributes is equals to Attribute.all.
But when I load the page, the following error is thrown
You tried to define an association named attribute on the model AttributeVal, but this will conflict with a method attribute already defined by Active Record. Please choose a different association name.
My models
class Attribute < ApplicationRecord
validates :name, presence: true
validates :name, uniqueness: true
has_many :attribute_vals
end
.
class AttributeVal < ApplicationRecord
validates :name, presence: true
validates :name, uniqueness: { scope: :attribute_id }
belongs_to :attribute
end
Is there any way I can access this sub collection?
Because ApplicationRecord already using a method named "attribute". I think you should change your model name. But if you want to use like this, you can do like the below:
has_one :association_name, :foreign_key: "key_name", class_name: "ModelClass"
Probably for your project:
class AttributeVal < ApplicationRecord
belongs_to :new_association_name, foreign_key: "attribute_val_id", class_name: "Attribute"
end
Source:
http://blog.blakesimpson.co.uk/read/59-fixing-the-you-tried-to-define-an-association-named-transaction-ruby-on-rails-error
Hello guys this error is giving me a headache for days and I seriously don't know what's happening. So, I have 2 models: User and Composition. Compositions have a belongs_to :user and the user have has_many :compositions and one controller which is giving an error when I try to get de user id from the composition's owner(user).
Error
undefined method `id' for nil:NilClass
<%= link_to profile_path(compos.user.id), class: 'ui-btn btn-small' do %>
<span class="icon-export"></span>visitar perfil</a>
<% end %>
Composition
class Composition < ApplicationRecord
belongs_to :user
validates :title, presence: true, :length => {maximum: 120}
validates :description, presence: true
has_attached_file :thumbnail
validates_attachment_content_type :thumbnail, content_type: /\Aimage/
validates_attachment_file_name :thumbnail, matches: [/png\Z/, /jpe?g\Z/]
do_not_validate_attachment_file_type :thumbnail
end
User
class User < ApplicationRecord
has_many :compositions
rolify
devise :database_authenticatable, :omniauthable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
mount_uploader :avatar, AvatarUploader
# Validações
validates_integrity_of :avatar
validates_processing_of :avatar
validates_format_of :username, :with => /[\w]+/
validates_length_of :username, :in => (5..32)
validates_uniqueness_of :username
#Previne que o avatar tenha um tamanho maior de 2MB
private
def avatar_size_validation
errors[:avatar] << "should be less than 2MB" if avatar.size > 2.megabytes
end
end
Controller
class StaticPagesController < ApplicationController
before_filter :authenticate_user!
def index
#compositions = Composition.all.order('created_at desc').limit(4)
end
end
You can set if condition to check if compos.user is present.
<% if compos.user %>
But, Seems like it's data inconsistency as I think you are working on development environment
You need to make sure for each composition user_id must exist.
class Composition < ApplicationRecord
belongs_to :user
validates :user, presence: true
end
This way you will never have compos with user_id = nil
I'm trying to dynamically build a collection where each array contains a value from two separate tables.
The Models:
#/models/user.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable, :confirmable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :user_id, :email, :password, :password_confirmation, :remember_me,
:first_name, :last_name, :permanent_address, :permanent_city,
:permanent_state, :permanent_zip, :home_phone, :mobile_phone, :role,
:tenant_attributes, :rents_attributes
validates :email, :presence => true, :uniqueness => true
validates :first_name, :presence => true
validates :last_name, :presence => true
validates :permanent_address, :presence => true
validates :permanent_city, :presence => true
validates :permanent_zip, :presence => true
validates :first_name, :presence => true
validates :home_phone, :presence => true
has_one :app
has_one :tenant, :foreign_key => :users_id
has_many :rents
has_many :maints
accepts_nested_attributes_for :tenant
accepts_nested_attributes_for :rents, allow_destroy: true
end
#/models/tenant.rb
class Tenant < ActiveRecord::Base
belongs_to :users
belongs_to :units
attr_accessible :lease_begin, :lease_end, :rent_share, :users_id, :units_id
has_many :maints
end
The Helper Method (so far):
#/helpers/users_helper.rb
def tenants
tenants = Tenant.select([:id, ??? ])
tenants.map {|u| [u.???, u.id]}
end
The form field:
<%= f.input :tenant_id, :collection => tenants %>
Essentially what I'm trying to do is select the :id from the Tenants table and then the associated :first_name + :last_name (represented by "???" above) from the Users table to populate the collection arrays this would generate.
What's the best approach here?
If your helper is specifically used just for this input then I believe you have the correct thought on your query, in that you are concerned on retrieving just the required columns.
To retrieve tenants including attributes from their belongs_to :user relation, your helper definition needs to be updated to:
# app/helpers/users_helper.rb
def tenants
tenants = Tenant.joins(:user).select('tenants.id as tenant_id, users.first_name, users.last_name')
tenants.map { |u| [ [u.first_name, u.last_name].join(' '), u.tenant_id ]}
end
The tenants helper then returns a nested array of first_name and last_name joined with a space as one element and tenant_id as the second element array.
With the updated helper your view would be:
<%= f.select :tenant_id, :collection => tenants %>
Note the use of select helper here which is more suitable for this case.
class Agency < ActiveRecord::Base
has_many :events
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :name, :email, :phone, :address, :city, :state, :zip,
:notes, :is_admin, :password, :password_confirmation, :remember_me
end
class Event < ActiveRecord::Base
belongs_to :agency
has_many :consumers
end
class Consumer < ActiveRecord::Base
belongs_to :event
end
In consumers_controller I am trying to include some field from agency
active_scaffold :consumer do |conf|
list.columns = [
:agency, :event
]
end
There are such associations Agency -> Event -> Consumer. And there is no association between agency and consumer, only through event.
but it causes an error.
How Can I include to list a any field form agency table?
According to the wiki, I think what you want is this:
active_scaffold :consumer do |conf|
conf.columns = [:agency, :event]
end
Also, make sure a consumer has an agency association or column.
Solution was a quite simple but most likely inefficient.
I have added a method to Consumer model:
class Consumer < ActiveRecord::Base
...
def agency_name
self.event.agency[:name]
end
end
Then I have added a virtual column to list:
list.columns = [
:agency_name, :event, ... ]
That's all.
I've four user models: Zone, Product, User, Group
I want to choose what Users can sell a Product in a Zone, this is what Group does, with a many to many relation to User and a foreign key to one Product and one Zone. So I have one group per pair Zone/Product. I will also need to set custom attributes on that many to many relation so I used has_many :through Sell (I was unable to find a better name to describe the relation between Group and User).
So I ended up having 5 models: Zone, Product, User, Group, Sell.
It works fine, but now I'd need to select the next user available in a Group.
I was thinking to exploit Sell.id to find the user assigned to the same group with an higher id, if not present choose the first one again (this allows me to create a ring chain).
It would be useful to have a Group.next_user method.
Unfortunatly I can't figure out how to do this, I'd need help to find the next user available in the group (or the 1st one if there are no more users).
Follows the code for models all the models:
################
# models/group.rb
################
class Group < ActiveRecord::Base
has_many :sells
has_many :users, :through => :sells
belongs_to :zone
belongs_to :product
attr_accessible :priority, :product_id, :user_ids, :zone_id
end
################
# models/zone.rb
################
class Zone < ActiveRecord::Base
belongs_to :location
has_many :cities
has_many :groups
attr_accessible :name, :location_id
validates :location, :presence => true
end
################
# models/user.rb
################
class User < ActiveRecord::Base
after_create :create_calendar
before_destroy :destroy_calendar
belongs_to :location
belongs_to :mall
has_one :event_calendar
has_many :sells
has_many :groups, :through => :sells
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable, :registerable,
# :recoverable, :rememberable,
devise :database_authenticatable, :trackable,
:validatable, :authentication_keys => [:username]
# Setup accessible (or protected) attributes for your model
attr_accessible :username, :password, :password_confirmation, :remember_me, :name,
:surname, :role, :location_id
# attr_accessible :title, :body
ROLES = %w[Admin Agente Hostess HostessAdmin]
validates_uniqueness_of :username, :case_sensitive => false
validates :username, :presence => true
validates_presence_of :role, :name, :surname, :location_id
validates :location, :presence => true
validates :role, :inclusion => { :in => ROLES, :message => "%{value} non è un ruolo valido." }
def display_name
"#{self.name} #{self.surname}"
end
def has_role?(role)
# convert the role string to a sybmol
self.role.downcase.gsub(/\s+/, "_").to_sym == role
end
private
def create_calendar
if self.has_role? :agente
calendar = EventCalendar.new({:user_id => self.id})
calendar.save()
end
end
def destroy_calendar
if self.has_role? :agente
calendar = EventCalendar.find_by_user_id(self.id)
calendar.destroy()
end
end
def email_required?
false
end
def email_changed?
false
end
end
################
# models/product.rb
################
class Product < ActiveRecord::Base
after_create :create_groups
before_destroy :destroy_groups
attr_accessible :name
def create_groups
for zone in Zone.all
group = Group.new({:zone_id => zone.id, :product_id => self.id})
group.save()
end
end
def destroy_groups
for zone in Zone.all
group = Group.find_by_product_id(self.id)
group.destroy
end
end
end
################
# models/sell.rb
################
class Sell < ActiveRecord::Base
belongs_to :user
belongs_to :group
end
Can you give me some help to get this done? Thanks!
If I get this right then addd this to your User model
scope :next, lambda { |p| {:conditions => ["id > ?", p.id], :limit => 1, :order => "id"} }
and this to your group model
def self.next_user
return User.first if Group.users.blank?
next_user = User.next(Group.users.last).first
return next_user || Group.users.first
end
This should do the trick. I didn't write test for this so you should test it :)