cant understand meaning of following lines in haml file - ruby-on-rails

#{#current_user.allowed_events.size}
#{#current_user.batch_mates.size}
link_to "<span>#{#current_user.related_colleges.size}</span>Colleges".html_safe
in above lines what are these allowed_events.size,related_colleges.size?
are these builtin functions?

Most likely allowed_events and batch_mates are either an association or method on the User model (assuming that's what #current_user references). Take a look in apps/models/user.rb and see if you find anything there.
Those methods are likely returning an ActiveRecord::Relation which is sort like a class wrapper around an array of models, typically returned from a database search. Anyway, the ActiveRecord::Relation class has a size method which is very similar to length or count.
So it's most likely just spitting out the number of allowed events and batch mates that belong to the current user.
As for the #{} that's just triggering Ruby interpolation. You could also do it this way:
= #current_user.allowed_events.size
= #current_user.batch_mates.size

As per the code, current_user is an object of User model. related_colleges and allowed_events could be associations/method/name scope in use model, you need to see your User.rb file in model to get it. I think these are associations (likely has_many) where size is the method to get the count of associated objects

Related

access ActiveRecord Has Many associations

I have a model which has a lot of associations. What I need to do is to check whether one of those associations is not present or all of them are set correctly.
To do so, I created an array which includes all of those needs-to-be-checked fields. And created a loop through each element, but the case is that I can not access has_many related attributes with read_attribute method. It basically returns nil whenever I try to access has many associated fields.
What I am trying to do, I can access all related objects via car.drivers but I can not access the same object with car.read_attribute(:drivers) (because some of them are attributes and some are relations)
I think it's the behavior of read_attribute, so what should I use to access any (attribute or relation) on ActiveRecord object?
Regarding to the comments, it looks like no one understand what I am trying to do. I want to access the relations of one ActiveRecord object such like;
RELATIONS.each do |relation|
puts "#{relation} exists" if #object.relation.present?
end
What I do not know about this, is there any method that I can access the related objects with their string typed name. Similar to, #object.read_attribute(:attribute_name) In that way I can create a for loop, but for relations not for the attributes
To do so, I used dynamical method call. Below is an example of showing it
RELATIONS.each do |relation|
puts "#{relation} exists" unless #object.send('relation').nil?
end

Can I list all dependent objects of an object (say, user)?

I have a model and can manually check every (:has_many, :has_one) dependency, but I want some magic like current_user.attributes for records. So when I update model, I don't need to update method.
I tried Reflections, but it returns all theoretical dependencies/connections of model, isn't it? And I need dependent records from DB.
Something like X.where(user_id: #user.id) or #user.dependents
Is it possible?
You can assign required object to model and then
model.class.reflect_on_all_associations.map { |table| model.method(table.name).call }.select(&:any?)
For example:
user = User.first
user.class.reflect_on_all_associations.map { |table| user.method(table.name).call }.select(&:any?)
# returns all associated objects of first user
You can specify result using :has_many, :has_one or :belongs_to as argument of reflect_on_all_associations.
Possibly there is more elegant way, but it works.
TL;DR Don't do this :)
You can do something quite similar using reflections. For example
#user.class.reflections.keys.flat_map { |reflection| me.send(reflection) }
will give you an array with all the objects associated with the user. But what's next?
For almost any real-world logic around this list's members (except the basics that come from AR::Base) you will have to check either a class of an object or use bug-prone try magic - both options are reasonable trade-off sometimes, but in most practical cases I'd prefer less smelly solutions (even if they are a bit more verbose).

How do I call a static function with model scopes in Rails?

I wasn't sure how to get it to work syntax wise. I did get it to work like the following though:
scope :out_of_stock, lambda{ |company| get_inventory(company, 'out_of_stock') }
scope :in_stock, lambda{ |company| get_inventory(company, 'in_stock') }
def self.get_inventory(company, stock_status)
StockInventory.find_all_by_....
end
However, is there a way to do it without the anonymous functions?
First of all, there are no static functions in Ruby. The self.get_inventory is a class method, which is in effect a singleton instance method on the Company class. The scope call is itself a class method that dynamically defines other class methods, in this case out_of_stock and in_stock.
Second, it's hard to tell what you're trying to do, since you didn't include your entire method, but I'll assume you're trying to get the instances of StockInventory that have a particular company id and inventory status.
ActiveRecord allows you to use finders, as it appears you've done here, or relations, which are a bit more flexible, as they are typically chainable, and because their execution is delayed until absolutely necessary, meaning you can pass them around to different methods without hitting the database. Unless I'm looking up a single object with a known id, I usually stick to relations for this reason.
I'm going to make a few assumptions, since your question isn't particularly clear. If you have defined a relation between Company and StockInventory (like has_many :stock_inventories and belongs_to :company), you can use that relation as a starting point and defined a method like this on the StockInventory class:
def self.in_stock
where(stock_status: "in stock") # or whatever
end
Note that instead of passing in a Company instance as an argument to a Company class method that ultimately loads some other class (this should be a red flag), you call this directly on the StockInventory class or any StockInventory relation. Plus, since it's a relation, you can chain other ActiveRecord methods to it, i.e. my_company.stock_inventories.in_stock.limit(10).
You'll need to alter this method to fit your particular database columns and statuses, but this is as complicated as it needs to get.
Whatever the case, I recommend you read the Active Record Query Interface guide - there's a lot you can do with it once you understand how it works.

Force reload another model's methods in rails?

I have a model that defines methods based off of the entries in another model's table: eg Article and Type. An article habtm types and vice versa.
I define in Article.rb:
Type.all.each do |type|
define_method "#{type.name}?" do
is?(:"#{type.name}")
end
end
This works great! it allows me to ensure that any types in the type db result in the methods associated being created, such as:
article.type?
However, these methods only run when you load the Article model. This introduces certain caveats: for example, in Rails Console, if I create a new Type, its method article.type_name? won't be defined until I reload! everything.
Additionally, the same problem exists in test/rspec: if I create a certain number of types, their associated methods won't exist yet. And in rspec, I don't know how to reload the User model.
Does anyone know a solution here? Perhaps, is there some way to, on creation of a new Type, to reload the Article model's methods? This sounds unlikely.. Any advice or guidance would be great!
I think you'll be better off avoiding reloading the model and changing your api a bit. In Article, are you really opposed to a single point of access through a more generic method?
def type?(type)
return is? type if type.is_a? String # for when type is the Type name already
is? type.name # for when an instance of Type is passed
end
If you're set on having separate methods for each type, perhaps something like this would work in your Type class
after_insert do
block = eval <<-END.gsub(/^ {6}/, '')
Proc.new { is? :#{self.name} }
END
Article.send(:define_method, "#{self.name}?", block)
end

problem using sql instead of named scope in rails

I have a method "search" in my model, which depending upon the various parameters passed runs an sql query in which i am joining seven tables. but when i am using this method with another named scope then error is shown "undefined method call for array".
but when instead of this search method if i use group of named scope then it works fine.
so how to integrate named scope with that method
It's a little hard to tell for sure without seeing the code. But it sounds like the search method is intended to be called on the Model class and when you chain the named_scope calls either they don't know what to do with the array your search method supplies or your search method doesn't know what to do with the array of records the names scope supplies.
I think your #search method is probably returning something (an Array?) that does not implement some method that named_scope expects. From a quick look into activerecord/lib/active_record/named_scope.rb it appears that named_scope returns a Scope object, which does implement #call (and a bunch of other non-Array methods too). That looks to be why chaining scopes works. So an Array just isn't going to work.
Could you rework your #search method into a named_scope? I realise that you're going to get an unusually (for me, at least) complex definition, but you should then be able to chain your results with other scopes.
Alternatively, how about making your custom search method work so that it returns (and must also take, for chaining before and after to work) a Scope? Probably haarder to do than a big named_scope though.
hey sorry for replying late, but found the answer
I have stored the query in a variable and then passed to the named scope where i do find_by_sql.
hence got the desired result.

Resources