I've got a posts model and of course authors which is a foreign key relationship to my users.
I am trying to output in JSON, the posts with the authors names.
I know this is rails 101, but I can't call post.author because I'm not in a view.
I've tried doing this a few ways, but none seem to be working.
My post model has
belongs_to :user, :foreign_key => :author_id
def post_author
self.each {|a| a['author'] = User.find(a.id)}
end
in my controller I've tried all sorts of
posts=Post.find(:all).includes(:user)
#or
posts=Post.find(:all).includes(:post_author) #don't think this is right anyway, but tried
#and
posts = Post.find(:all)
posts = JSON::Parse(posts.to_json()).merge('author'=>posts.author) #or posts.user, etc etc
of course, none of these have worked, which is why I'm posting here. What's the best way to get the author of a post.
----------------------update ---------------------------
#rjz provided a response which works, but I'm hoping isn't the best way.
He suggested using
posts.to_json(:include=> :user,:only[:username])
this meant I was only getting the username back, but I need more than that so I started using :except instead. The problem here is that I've got a fields like id which I need in the post, but not in the author, but if I exclude them in this manner, the field is excluded from the results completely. I'm also having to list out each field I need, and I'm not sure if that is the best way.
You might have to tease the name of your association a bit to get exactly what you want, but what you're looking for is the :include option when you serialize with to_json:
posts.to_json(:include => :user)
Related
I'm using the devise and acts_as_votable gems to allow users to cast their votes on posts. My current objective is to query a list of the posts liked by the user.
Looking around in the Rails console I found out that when a post is voted on a votes_for table gets appended on containing information like the timestamp, vote weight and the voter_id which is what I would like to call upon.
Here's what the user controller looks like (user controller because I'm attempting to query the likes on the users/show page):
#user = current_user
#links = Link.all
#likes = #links.where.votes_for(:voter_id => #user.id) // line I'm trying to figure out, I reckon it'd look something like this
I could definitely be going about this the wrong way altogether, if that's the case I'd just appreciate some direction.
Explanation would be appreciated... I'm learning the fundamentals of Rails and finding its naming conventions convoluted and hard to follow.
If you're using Devise, I guess the current_user method should be available in your view and you shouldn't need a reassignment to #user
To understand how ActiveRecord works you might want to look into the documentation here.
As for the links and the voter_id, here's the way I think your query should be:
#likes = Link.where(votes_fors: {voter_id: current_user.id}) # OR Link.where(voter: current_user)
Basically the query will be transformed to a SQL query which says:
"SELECT * FROM links INNER JOIN votes_fors ON links.id = votes_fors.votable_type='Link' WHERE votes_fors.voter_id = ?" [voter_id, 1]
You get the idea?
A better approach would be to use the ActiveRecord methods to fetch these collections e.g
class User
has_many :votes_fors, foreign_key: :voter_id
has_many :favorites, through: :votes_fors, source: :votable # not really sure of this syntax but it should work I think.
end
With the above, you should be able to do:
current_user.favorites which would fetch you all the links voted by the user.
I have a table with nested comments and they have comment_id field to point to parent comment. I put has_many :comments, :class_name => "Comment" in comment's model and so i have a tree. The question is how with all power of Rails and ActiveRecord i can get whole comments tree from database and respond with it in json format? I know about ancestry
but i want to find solution without any side gems. I want to learn best ways in Rails for manipulation tree-like structures because this task will appear again and again in my further practice.
UPDATE:
I found some related question here and used answer from it. I define method in model
def self.get_tree(comments)
comments.map { |comment|
{:responses => get_tree(comment.comments), :user => comment.user, :text => comment.text}
}
end
and then just call it to get whole tree (with some conditions)
render :json => Comment.get_tree(Comment
.where('announce_id = ?', params[:id])
.where('comment_id is NULL'))
With this implementation i clearly see now that there no need in side gems for this task. But also in current implementation i should list all comment's properties inside map. Are there any way to just extend existing object with {:responses => get_tree(comment.comments), :user => comment.user}? I
found << for arrays and .update for hashes but then i ended up with that i have no idea whatcomment inside map block is. Either it array or hash or object...
I use Rails 3 with MongoMapper.
I want to add some records to the result of has many association.
For example, user has_many posts
class User
include MongoMapper::Document
many :posts
end
By default it will show only posts which belongs to the user, but if he/she specify special option in query (or in the user's settings menu, say show-commented=true), then I also need to add posts where user left any comments. So I think to override posts method
def posts
super + (show_commented_posts ? commented_posts : [])
end
But of course it doesn't work. How can I correctly override this method using mongo_mapper? Or is there any better approach for that problem?
Overriding methods on mongomapper is a very bad idea, you should try to refrain from doing it as it creates a lot of problems that are hard to trace back (I've been burned before by this).
Instead, you should consider using a scope such as
class Post
scope :related_to_user, lambda {|user| where('$or' => [ {user_id: user.id}, {'comments.user_id' => user.id}]) }
end
Then you can call
Post.related_to_user(current_user)
Two questions:
1) How can I make a column in the 'list' for a model consist of data from the record's association? In other words, I have a user model and a user has_many posts. I want to simply have a "post count" column in the list. I tried doing:
field :posts do
formatted_value do
value.count
end
end
but that results in a divide by zero error. I even tried doing:
field :posts do
formatted_value do
bindings[:object].posts.count
end
end
but got the same results.
2) How can I filter the listing to a particular scope? For example, I want to make the users post count be a link that is clickable which will show all posts for the given user.
The best I could figure out how to do this was to do:
# note that I created a method post_count to temporarily solve problem #1
field :post_count do
formatted_value do
bindings[:view].link_to value, "/admin/posts?query=#{bindings[:object].id}"
end
end
Which doesn't work very well. Is there a way to instruct rails-admin to do a .where(:user_id => xxx) on the model?
The other thing I wasn't crazy about was having to manually put in 'admin/posts'.. I was trying to see if I could do rails_admin_list_path(:model_name => "posts"). but that didn't seem to work.
You'd probably get a better response on the rails_admin mailing list - http://groups.google.com/group/rails_admin/
For your first question, this should do the trick:
field :posts, :virtual do
formatted_value do
bindings[:object].posts.count
end
end
For your second question, rails_admin now has a filter system - see the "add filter" dropdown at http://demo.railsadmin.org/admin/players . Tapping into that would be a much better method.
rails_admin_list_path(:model_name => "posts") should work, you might have to include Rails.application.routes.url_helpers or similar.
Try adding this to your rails_admin.rb
RailsAdmin.config {|c| c.label_methods << :field_name}
worked for me
I am using acts-as-taggable on. Two models: User and Posts.
Posts belongs_to :user
User has_many :posts
Posts acts-as-taggable.
Users acts-as-tagger
All of this is straightforward and is working. However, I have a use-case which may be outside of how this plugin works.
I want Posts to be able to be tagged by multiple users. When a tag is created on a post from a user, it does not show when you do the following:
p = Post.first
p.tag_list # this returns []
If you look at the SQL being generated it selects records where 'tagger_id' is NULL. The tagger_id is, of course, the user_id in this case and is very much not NULL.
If you back into it, however, you can get what you want.
p = Post.find(1) # get a post to work with
p.tags_from(p.user) # returns an array of the tags: ['cats','dogs','wildebeasts']
This works.
Now, the problem is I want another user to be able to come along and add a tag to the post. Maybe this user will think it is helpful. Let's just assume it makes sense to do so. Could be a moderator... whatever.
Given the above, how would I get a list of all the tags on a given post assuming that more than one user added tags?
Gratefully,
NJ
I don't know anything about the plug-in you specified and I'm still learning Rails. But I don't think
p = Post.tag_list
would be what you want, anyways. You're asking for a taglist of the Post class rather than the taglist of a particular post. For example, if users have 'email' and 'name' columns, you also couldn't do:
u = User.names
u = User.emails
It doesn't really make sense. But you could do something like:
User.column_names
#=> ["id", "email", "hashed_password", "created_at", "updated_at"]
Because that's a class method. Now, maybe tag_list is a class method, but it looks like it's used to find orphaned tags or something due to how it looks for null tag_givers.
But since I'm still new to Rails and I also don't know how your plugin works, here are some things you can try off the top of my head:
p = Post.find(1)
p.tag_list # p.column_name_of_the_column_that_holds_the_tags should work
# or, maybe pass in ALL users as an array
p.tags_from(User.all)
Lemme know what those do.
Maybe I'm missing something but:
p = Post.tag_list # this returns []
#should be
#...
#post.find params[:id]
#...
#post.tag_list
You're currently calling tag_list on the post class, rather than an instance of it.