How to pass different parameters from a controller? - ruby-on-rails

I have 3 models as category, posts and comments. I want to display posts and number of comments in the category page.
category.(:id)Post.(:id).comments.count will return the number of comments.
But how should I pass those parameters from category controller? I'm also trying to write the jbuilder view for the same.
or Can I do something like this directly from jbuilder view?
#this work
json.number #category.posts.count
#this one doesn't work
json.number #category.posts.comments.count

json.number #category.posts.count it works but
json.number #category.posts.comments.count this does not.
You can test in rails console.. like #category.posts.comments.count.
it may throw error like
NoMethodError: undefined method 'comments' for #<ActiveRecord::Associations::CollectionProxy::ActiveRecord_Associations_CollectionProxy_Post:0x0000000920b058>
This happens because #category.posts returns a collection not Post object.
One possible solution is
#category.posts.map {|post| [post, post.comments.count] }
This gives you the total count of comments per post in array. This may not be exactly what you wanted but you may modify to meet your requirement.

The easiest way to pass parameters from the controller to a view you are going to present is using the # (instance variable). Therefore you can pass:
#count = <your code above>
#all_posts = <your post code>
If you have alot of different parameters, just create an object to pass them across in:
#post_info = {
count: <your code above>,
all_posts: <your post code>
}
And then retrieve them in your view using #post_info[:count] and #post_info[:all_posts]

Related

undefined method for #<Array

I have this inside User model
def self.home_opinions (user)
home_opinions = user.opinions
user.follows.find_each do |follow|
home_opinions+=(follow.opinions)
end
home_opinions.order_by_most_recent
end
I have this scope inside Opinion model
scope :order_by_most_recent, -> { includes(:author).order(created_at: :desc) }
It shows this error
undefined method `order_by_most_recent' for #<Array:0x00007eff64d076f8>
But when I try User.home_opinions(User.find(9)) inside rails console
It works
I have two questions
why It shows the error
What are the best practices for this code maybe using includes?
.order_by_most_recent will only work on an ActiveRecord::Relation.
When you call home_opinions = user.opinions you get a relation object back.
The problem comes when you call
home_opinions += follow.opinions
That action converts the relation into an array, and then .order_by_most_recent is no longer available.
If you can, you should try and get all relevant opinions in a single ActiveRecord call. That way, you'll have an ActiveRecord::Relation object which you can chain with other scopes – plus, you can do everything in a fixed number of database calls, rather than an extra call for every member of the follows association.
Try something like:
opinion_owner_ids = [user.id] + user.follow_ids
home_opinions = Opinion.where(user_id: opinion_owner_ids)
home_opinions.order_by_most_recent

Pluck with condtions in rails

I want to compare a param extracted from a link to the list of data present in column...
I am using pluck to generate a array of list(in controller) but not getting any success in comparing it
any method that I can fetch records in model and compare with param in controller or model
as passing controller instances in model seems inappropriate to me
Initially i am trying fetching and comparing in controller..
#abc=Group.pluck(:group_token)
what I tried to do before is defined group_fetch method in model and used it in controller to check condition but I was not able to compare param which comes frome url dynamically
def self.group_fetch
Group.find_by group_token: 'UuzsG7NMvYFzxwPDdYgLxJbF'
end
what will be the best way to fetch db column and compare it with the link param
You can use the exists? method which pretty much does what it says.
Group.exists?(group_token: params[:token])
You can use include? to check if the param is in the list. For example:
def your_method
list = Model.pluck(:attribute)
list.include?(params[:your_param])
end

How does Rails know the difference between these two identical expressions?

I am using a 4-year old Rails tutorial and I have Rails 4.0.2. I made a model called "Thing" and a controller called "Things". The "Thing" model has one attribute called "data". In my create action, I had this line:
#thing = Thing.new(params[:thing])
which results in this error:
ActiveModel::ForbiddenAttributesError in ThingsController#create
I found a StackOverflow thread that said I needed to require my needed parameters, and that worked just fine.
Before I looked that up I tried putting the hash from my params directly into the Thing.new() method and I didn't get an error. I started with this line:
puts params[:thing]
in my create action, typed "12345" in my text field, hit submit and got this in the console:
{"data"=>"12345"}
So I tried this in the create action:
#thing = Thing.new({"data" => "12345"})
and I didn't get the error. I even confirmed they were identical by doing this:
puts params[:thing] == {"data"=>"12345"}
and I get "true" on the console. So,
Thing.new(params[:thing])
gives me the error, but
Thing.new({"data"=>"12345"})
does not.
How can Rails tell the difference between these two arguments when they seem to be identical?
params[:thing] is not the same thing as {"data" => "12345"}, they just have the same value when inspect is called on them, and params's class overrides == to say it's equal to the hash.
Rails 4+ uses Strong Parameters, which is a security feature to make sure you know what you're putting in your models. Basically, Rails wants to you check the validity of the parameters. It lets you do Thing.new({"data" => "12345"}) because you, the developer, are creating the Hash directly, and are more trustworthy than someone on the internet calling your server.

Print results of Active Record query

I was wondering if someone could help me or point me to a tutorial to help me understand how to send the results of a rails query into a view? At the moment, I am only able to run a query using the console, but I'm not sure how to render the results into a view. For example, I have a model called City with the attributes state, population_size, and capital. For example, if I run a query in the console:
results = City.where(:state => 'Virginia')
How can I run that same query in Rails? Specifically, where would I place that code? Sorry for the noob question, but I can't find any guides that explicitly show me how to do this. I have only found guides on how to work in the console, but now how to actually render a view of the results...
Thanks!!
You can create the instance var to use it in your views
#results = City.where(:state => 'Virginia')
Now in your view you have access to #results
You can create the instance var to access it throughout the request.
if you want an array of results.
#results = City.where(:state => 'stateName')
if you want a single object
#result = City.find_by(state: 'stateName', id: :id)
Both can help you in different circumstances.
Now in your view you have access to #results

How to refer to the current record in a Rails query?

In a Rails controller I'm using a JSON request to an external database to return integers that are used to order a collection of records:
Model.order(JSON.parse(open("http://myapp.com/models/#{:id}")).read)['attribute'])
I want to make this dynamic to aid switching between environments. Something like:
Model.order(JSON.parse(open(model_url(model))).read)['attribute'])
This is not correct, and model_url(model) is returning an error:
undefined local variable or method 'model'
How do I refer to self in query?
There must be a more elegant solution than
...JSON.parse(open("#{root_url}/models/{:id}"))....
EDIT:
Lightswitch05's answer below does anser the question I asked. The query should reference params[:id] to get the url of the current record.
In fact, I have decided to move this JSON call into a virtual attribute on the model. This means I can simply call Model.order(:my_virtual_attribute). While this solution brings its own share of issues—I needed to make url_helpers available to the model—in the long run I think this will be a cleaner solution.
As per our discussion the problem is that model is not defined. Since all you are trying to do with model is get the url to it, all you really need is params[:id]. This will fix your error message:
Model.order(JSON.parse(open(model_url(params[:id]))).read)['attribute'])
where model has been replaced with params[:id]
Change your code:
Model.order(JSON.parse(open(model_url(model))).read)['attribute'])
to:
model_tableized = Model.to_s.tableize
model_url = "#{model_tableized}_url(#{model_tableized.chomp('s')})"
Model.order(JSON.parse(open(model_url).read)["attribute"])
I think that should work.
You need the name method.
If you're using the model, and not an instance of the model, it would be Model.name
If you're using an instance, it would be
#model = Model.first
#model.class.name

Resources