Rails 3: Correct syntax for named_scope with metho

2019-07-09 09:16发布

I have four models in my application, defined as follows

class User < ActiveRecord::Base
    has_many :comments
    has_many :geographies
    has_many :communities, through: :geographies

class Comment < ActiveRecord::Base
    belongs_to :user

class Community < ActiveRecord::Base
    has_many :geographies
    has_many :users

class Geography < ActiveRecord::Base
    belongs_to :user
    belongs_to :community

Users can post comments, which are associated with one or more communities through the geography table.

My task is the display only comments from the community selected from a dropdown list. I learned from this post that I can access the community of a given comment via the comment.user.communities.first object chain.

It seems typically a named_scope with lambda would be the preferred choice to filter the list of all comments, however, I am at a complete loss how to construct this named_scope. I've tried to construct the named_scope by following some RailsCasts, but this is as far as I was able to get. The generated error is below.

class Comment < ActiveRecord::Base
    belongs_to :user

    def self.community_search(community_id)
        if community_id
            c = user.communities.first
            where('c.id = ?', community_id)
        else 
            scoped
        end
    end

    named_scope :from_community, { |*args| { community_search(args.first) } }

This is the error:

syntax error, unexpected '}', expecting tASSOC
named_scope :from_community, lambda { |*args|  { community_search(args.first) } }
                                                            ^

What is the correct syntax for passing a method with arguments into a named_scope?

1条回答
别忘想泡老子
2楼-- · 2019-07-09 09:43

First, you can just use scope now in rails 3 - the older named_scope form was shortened, and it's removed in rails 3.1!

With regard to your error, though, I suspect you don't need the inner set of brackets. They are usually doubled when using a lambda block like that, because you are creating new hash from scratch, like this:

scope :foo, { |bar|
  { :key => "was passed #{bar}" }
}

In your case, though, your are calling community_search which should be returning a value that you can return directly. In this case, an AREL object that has replaced such simple hashes. It's somewhat confusing when reading all the random posts and tutorials out there on this subject, largely due to the huge change in style that AREL caused. Both of those style use use are ok, though - either as a lambda or class method. They largely mean the same thing. The two above links have several examples of this newer style for further reading.

Of course, you could just learn something like squeel, which I find much easier to read, and cuts out a lot of the typing. ^^;

查看更多
登录 后发表回答