2017-07-09 13:41:28 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2005-04-03 06:52:05 -04:00
|
|
|
class Author < ActiveRecord::Base
|
2008-09-10 13:50:01 -04:00
|
|
|
has_many :posts
|
2014-10-31 11:43:38 -04:00
|
|
|
has_many :serialized_posts
|
2012-04-05 15:21:48 -04:00
|
|
|
has_one :post
|
2016-08-06 13:37:57 -04:00
|
|
|
has_many :very_special_comments, through: :posts
|
|
|
|
has_many :posts_with_comments, -> { includes(:comments) }, class_name: "Post"
|
2020-07-05 22:56:01 -04:00
|
|
|
has_many :popular_grouped_posts, -> { includes(:comments).group("type").having("SUM(legacy_comments_count) > 1").select("type") }, class_name: "Post"
|
2016-08-06 13:37:57 -04:00
|
|
|
has_many :posts_with_comments_sorted_by_comment_id, -> { includes(:comments).order("comments.id") }, class_name: "Post"
|
2018-02-18 08:21:31 -05:00
|
|
|
has_many :posts_sorted_by_id, -> { order(:id) }, class_name: "Post"
|
2016-08-06 13:37:57 -04:00
|
|
|
has_many :posts_sorted_by_id_limited, -> { order("posts.id").limit(1) }, class_name: "Post"
|
|
|
|
has_many :posts_with_categories, -> { includes(:categories) }, class_name: "Post"
|
|
|
|
has_many :posts_with_comments_and_categories, -> { includes(:comments, :categories).order("posts.id") }, class_name: "Post"
|
|
|
|
has_many :posts_with_special_categorizations, class_name: "PostWithSpecialCategorization"
|
|
|
|
has_one :post_about_thinking, -> { where("posts.title like '%thinking%'") }, class_name: "Post"
|
|
|
|
has_one :post_about_thinking_with_last_comment, -> { where("posts.title like '%thinking%'").includes(:last_comment) }, class_name: "Post"
|
2013-07-08 06:51:15 -04:00
|
|
|
has_many :comments, through: :posts do
|
|
|
|
def ratings
|
|
|
|
Rating.joins(:comment).merge(self)
|
|
|
|
end
|
|
|
|
end
|
Add option to skip joins for associations.
In a multiple database application, associations can't join across
databases. When set, this option tells Rails to make 2 or more queries
rather than using joins for associations.
Set the option on a has many through association:
```ruby
class Dog
has_many :treats, through: :humans, disable_joins: true
has_many :humans
end
```
Then instead of generating join SQL, two queries are used for `@dog.treats`:
```
SELECT "humans"."id" FROM "humans" WHERE "humans"."dog_id" = ? [["dog_id", 1]]
SELECT "treats".* FROM "treats" WHERE "treats"."human_id" IN (?, ?, ?) [["human_id", 1], ["human_id", 2], ["human_id", 3]]
```
This code is extracted from a gem we use internally at GitHub which
means the implementation here is used in production daily and isn't
experimental.
I often get the question "why can't Rails do this automatically" so I
figured I'd include the answer in the commit. Rails can't do this
automatically because associations are lazily loaded. `dog.treats` needs
to load `Dog`, then `Human` and then `Treats`. When `dog.treats` is
called Rails pre-generates the SQL that will be run and puts that
information into a reflection object. Because the SQL parts are pre-generated,
as soon as `dog.treats` is loaded it's too late to skip a join. The join
is already available on the object and that join is what's run to load
`treats` from `dog` through `humans`. I think the only way to avoid setting
an option on the association is to rewrite how and when the SQL is
generated for associations which is a large undertaking. Basically the
way that Active Record associations are designed, it is currently
impossible to have Rails figure out to not join (loading the association
will cause the join to occur, and that join will raise an error if the
models don't live in the same db).
The original implementation was written by me and Aaron. Lee helped port
over tests, and I refactored the extraction to better match Rails style.
Co-authored-by: Lee Quarella <leequarella@gmail.com>
Co-authored-by: Aaron Patterson <aaron@rubyonrails.org>
2020-11-03 13:01:41 -05:00
|
|
|
|
|
|
|
has_many :comments_with_order, -> { ordered_by_post_id }, through: :posts, source: :comments
|
|
|
|
has_many :no_joins_comments, through: :posts, disable_joins: :true, source: :comments
|
|
|
|
|
|
|
|
has_many :comments_with_foreign_key, through: :posts, source: :comments, foreign_key: :post_id
|
|
|
|
has_many :no_joins_comments_with_foreign_key, through: :posts, disable_joins: :true, source: :comments, foreign_key: :post_id
|
|
|
|
|
|
|
|
has_many :members,
|
|
|
|
through: :comments_with_order,
|
|
|
|
source: :origin,
|
|
|
|
source_type: "Member"
|
|
|
|
|
|
|
|
has_many :no_joins_members,
|
|
|
|
through: :comments_with_order,
|
|
|
|
source: :origin,
|
|
|
|
source_type: "Member",
|
|
|
|
disable_joins: true
|
|
|
|
|
|
|
|
has_many :ordered_members,
|
|
|
|
-> { order(id: :desc) },
|
|
|
|
through: :comments_with_order,
|
|
|
|
source: :origin,
|
|
|
|
source_type: "Member"
|
|
|
|
|
|
|
|
has_many :no_joins_ordered_members,
|
|
|
|
-> { order(id: :desc) },
|
|
|
|
through: :comments_with_order,
|
|
|
|
source: :origin,
|
|
|
|
source_type: "Member",
|
|
|
|
disable_joins: true
|
|
|
|
|
|
|
|
has_many :ratings, through: :comments
|
|
|
|
has_many :good_ratings,
|
2021-11-15 13:46:01 -05:00
|
|
|
-> { where("ratings.value > 5").order(:id) },
|
Add option to skip joins for associations.
In a multiple database application, associations can't join across
databases. When set, this option tells Rails to make 2 or more queries
rather than using joins for associations.
Set the option on a has many through association:
```ruby
class Dog
has_many :treats, through: :humans, disable_joins: true
has_many :humans
end
```
Then instead of generating join SQL, two queries are used for `@dog.treats`:
```
SELECT "humans"."id" FROM "humans" WHERE "humans"."dog_id" = ? [["dog_id", 1]]
SELECT "treats".* FROM "treats" WHERE "treats"."human_id" IN (?, ?, ?) [["human_id", 1], ["human_id", 2], ["human_id", 3]]
```
This code is extracted from a gem we use internally at GitHub which
means the implementation here is used in production daily and isn't
experimental.
I often get the question "why can't Rails do this automatically" so I
figured I'd include the answer in the commit. Rails can't do this
automatically because associations are lazily loaded. `dog.treats` needs
to load `Dog`, then `Human` and then `Treats`. When `dog.treats` is
called Rails pre-generates the SQL that will be run and puts that
information into a reflection object. Because the SQL parts are pre-generated,
as soon as `dog.treats` is loaded it's too late to skip a join. The join
is already available on the object and that join is what's run to load
`treats` from `dog` through `humans`. I think the only way to avoid setting
an option on the association is to rewrite how and when the SQL is
generated for associations which is a large undertaking. Basically the
way that Active Record associations are designed, it is currently
impossible to have Rails figure out to not join (loading the association
will cause the join to occur, and that join will raise an error if the
models don't live in the same db).
The original implementation was written by me and Aaron. Lee helped port
over tests, and I refactored the extraction to better match Rails style.
Co-authored-by: Lee Quarella <leequarella@gmail.com>
Co-authored-by: Aaron Patterson <aaron@rubyonrails.org>
2020-11-03 13:01:41 -05:00
|
|
|
through: :comments,
|
|
|
|
source: :ratings
|
|
|
|
|
|
|
|
has_many :no_joins_ratings, through: :no_joins_comments, disable_joins: :true, source: :ratings
|
|
|
|
has_many :no_joins_good_ratings,
|
2021-11-15 13:46:01 -05:00
|
|
|
-> { where("ratings.value > 5").order(:id) },
|
Add option to skip joins for associations.
In a multiple database application, associations can't join across
databases. When set, this option tells Rails to make 2 or more queries
rather than using joins for associations.
Set the option on a has many through association:
```ruby
class Dog
has_many :treats, through: :humans, disable_joins: true
has_many :humans
end
```
Then instead of generating join SQL, two queries are used for `@dog.treats`:
```
SELECT "humans"."id" FROM "humans" WHERE "humans"."dog_id" = ? [["dog_id", 1]]
SELECT "treats".* FROM "treats" WHERE "treats"."human_id" IN (?, ?, ?) [["human_id", 1], ["human_id", 2], ["human_id", 3]]
```
This code is extracted from a gem we use internally at GitHub which
means the implementation here is used in production daily and isn't
experimental.
I often get the question "why can't Rails do this automatically" so I
figured I'd include the answer in the commit. Rails can't do this
automatically because associations are lazily loaded. `dog.treats` needs
to load `Dog`, then `Human` and then `Treats`. When `dog.treats` is
called Rails pre-generates the SQL that will be run and puts that
information into a reflection object. Because the SQL parts are pre-generated,
as soon as `dog.treats` is loaded it's too late to skip a join. The join
is already available on the object and that join is what's run to load
`treats` from `dog` through `humans`. I think the only way to avoid setting
an option on the association is to rewrite how and when the SQL is
generated for associations which is a large undertaking. Basically the
way that Active Record associations are designed, it is currently
impossible to have Rails figure out to not join (loading the association
will cause the join to occur, and that join will raise an error if the
models don't live in the same db).
The original implementation was written by me and Aaron. Lee helped port
over tests, and I refactored the extraction to better match Rails style.
Co-authored-by: Lee Quarella <leequarella@gmail.com>
Co-authored-by: Aaron Patterson <aaron@rubyonrails.org>
2020-11-03 13:01:41 -05:00
|
|
|
through: :comments,
|
|
|
|
source: :ratings,
|
|
|
|
disable_joins: true
|
|
|
|
|
2016-08-06 13:37:57 -04:00
|
|
|
has_many :comments_containing_the_letter_e, through: :posts, source: :comments
|
|
|
|
has_many :comments_with_order_and_conditions, -> { order("comments.body").where("comments.body like 'Thank%'") }, through: :posts, source: :comments
|
2017-09-01 16:12:42 -04:00
|
|
|
has_many :comments_with_include, -> { includes(:post).where(posts: { type: "Post" }) }, through: :posts, source: :comments
|
2017-10-09 02:18:59 -04:00
|
|
|
has_many :comments_for_first_author, -> { for_first_author }, through: :posts, source: :comments
|
2008-05-07 16:35:41 -04:00
|
|
|
|
2010-12-12 11:35:27 -05:00
|
|
|
has_many :first_posts
|
2016-08-06 13:37:57 -04:00
|
|
|
has_many :comments_on_first_posts, -> { order("posts.id desc, comments.id asc") }, through: :first_posts, source: :comments
|
2010-12-19 09:17:29 -05:00
|
|
|
|
|
|
|
has_one :first_post
|
2016-08-06 13:37:57 -04:00
|
|
|
has_one :comment_on_first_post, -> { order("posts.id desc, comments.id asc") }, through: :first_post, source: :comments
|
2010-12-12 11:35:27 -05:00
|
|
|
|
2016-08-06 13:37:57 -04:00
|
|
|
has_many :thinking_posts, -> { where(title: "So I was thinking") }, dependent: :delete_all, class_name: "Post"
|
|
|
|
has_many :welcome_posts, -> { where(title: "Welcome to the weblog") }, class_name: "Post"
|
2008-05-07 16:35:41 -04:00
|
|
|
|
2014-01-05 11:55:39 -05:00
|
|
|
has_many :welcome_posts_with_one_comment,
|
2020-07-05 22:56:01 -04:00
|
|
|
-> { where(title: "Welcome to the weblog").where(comments_count: 1) },
|
2016-08-06 12:26:20 -04:00
|
|
|
class_name: "Post"
|
2013-08-24 12:12:05 -04:00
|
|
|
has_many :welcome_posts_with_comments,
|
2020-07-17 07:53:50 -04:00
|
|
|
-> { where(title: "Welcome to the weblog").where("legacy_comments_count > 0") },
|
2016-08-06 12:26:20 -04:00
|
|
|
class_name: "Post"
|
2013-08-24 12:12:05 -04:00
|
|
|
|
2018-02-18 08:21:31 -05:00
|
|
|
has_many :comments_desc, -> { order("comments.id DESC") }, through: :posts_sorted_by_id, source: :comments
|
2017-09-06 18:33:38 -04:00
|
|
|
has_many :unordered_comments, -> { unscope(:order).distinct }, through: :posts_sorted_by_id_limited, source: :comments
|
2016-08-06 13:37:57 -04:00
|
|
|
has_many :funky_comments, through: :posts, source: :comments
|
|
|
|
has_many :ordered_uniq_comments, -> { distinct.order("comments.id") }, through: :posts, source: :comments
|
|
|
|
has_many :ordered_uniq_comments_desc, -> { distinct.order("comments.id DESC") }, through: :posts, source: :comments
|
|
|
|
has_many :readonly_comments, -> { readonly }, through: :posts, source: :comments
|
2010-03-07 19:53:21 -05:00
|
|
|
|
2006-10-15 12:37:11 -04:00
|
|
|
has_many :special_posts
|
2016-08-06 13:37:57 -04:00
|
|
|
has_many :special_post_comments, through: :special_posts, source: :comments
|
|
|
|
has_many :special_posts_with_default_scope, class_name: "SpecialPostWithDefaultScope"
|
|
|
|
|
|
|
|
has_many :sti_posts, class_name: "StiPost"
|
|
|
|
has_many :sti_post_comments, through: :sti_posts, source: :comments
|
|
|
|
|
|
|
|
has_many :special_nonexistent_posts, -> { where("posts.body = 'nonexistent'") }, class_name: "SpecialPost"
|
|
|
|
has_many :special_nonexistent_post_comments, -> { where("comments.post_id" => 0) }, through: :special_nonexistent_posts, source: :comments
|
|
|
|
has_many :nonexistent_comments, through: :posts
|
|
|
|
|
|
|
|
has_many :hello_posts, -> { where "posts.body = 'hello'" }, class_name: "Post"
|
|
|
|
has_many :hello_post_comments, through: :hello_posts, source: :comments
|
|
|
|
has_many :posts_with_no_comments, -> { where("comments.id" => nil).includes(:comments) }, class_name: "Post"
|
2021-01-06 07:13:25 -05:00
|
|
|
has_many :posts_with_no_comments_2, -> { left_joins(:comments).where("comments.id": nil) }, class_name: "Post"
|
2016-08-06 13:37:57 -04:00
|
|
|
|
|
|
|
has_many :hello_posts_with_hash_conditions, -> { where(body: "hello") }, class_name: "Post"
|
|
|
|
has_many :hello_post_comments_with_hash_conditions, through: :hello_posts_with_hash_conditions, source: :comments
|
|
|
|
|
|
|
|
has_many :other_posts, class_name: "Post"
|
|
|
|
has_many :posts_with_callbacks, class_name: "Post", before_add: :log_before_adding,
|
|
|
|
after_add: :log_after_adding,
|
|
|
|
before_remove: :log_before_removing,
|
|
|
|
after_remove: :log_after_removing
|
2019-11-06 04:15:13 -05:00
|
|
|
has_many :posts_with_thrown_callbacks, class_name: "Post", before_add: :throw_abort,
|
|
|
|
after_add: :ensure_not_called,
|
|
|
|
before_remove: :throw_abort,
|
|
|
|
after_remove: :ensure_not_called
|
2016-08-06 13:37:57 -04:00
|
|
|
has_many :posts_with_proc_callbacks, class_name: "Post",
|
2016-08-16 03:30:11 -04:00
|
|
|
before_add: Proc.new { |o, r| o.post_log << "before_adding#{r.id || '<new>'}" },
|
|
|
|
after_add: Proc.new { |o, r| o.post_log << "after_adding#{r.id || '<new>'}" },
|
|
|
|
before_remove: Proc.new { |o, r| o.post_log << "before_removing#{r.id}" },
|
|
|
|
after_remove: Proc.new { |o, r| o.post_log << "after_removing#{r.id}" }
|
2016-08-06 13:37:57 -04:00
|
|
|
has_many :posts_with_multiple_callbacks, class_name: "Post",
|
2016-08-16 03:30:11 -04:00
|
|
|
before_add: [:log_before_adding, Proc.new { |o, r| o.post_log << "before_adding_proc#{r.id || '<new>'}" }],
|
|
|
|
after_add: [:log_after_adding, Proc.new { |o, r| o.post_log << "after_adding_proc#{r.id || '<new>'}" }]
|
2016-08-06 13:37:57 -04:00
|
|
|
has_many :unchangeable_posts, class_name: "Post", before_add: :raise_exception, after_add: :log_after_adding
|
2005-07-04 04:43:57 -04:00
|
|
|
|
2018-09-25 13:18:20 -04:00
|
|
|
has_many :categorizations, -> { }
|
2016-08-06 13:37:57 -04:00
|
|
|
has_many :categories, through: :categorizations
|
|
|
|
has_many :named_categories, through: :categorizations
|
2006-03-20 20:07:16 -05:00
|
|
|
|
2010-12-12 12:03:41 -05:00
|
|
|
has_many :special_categorizations
|
2016-08-06 13:37:57 -04:00
|
|
|
has_many :special_categories, through: :special_categorizations, source: :category
|
|
|
|
has_one :special_category, through: :special_categorizations, source: :category
|
2006-03-20 20:07:16 -05:00
|
|
|
|
Fix incorrect result when eager loading with duplicated through association with join scope
I had found the issue while working on fixing #33525.
That is if duplicated association has a scope which has `where` with
explicit table name condition (e.g. `where("categories.name": "General")`),
that condition in all duplicated associations will filter the first one
only, other all duplicated associations are not filtered, since
duplicated joins will be aliased except the first one (e.g.
`INNER JOIN "categories" "categories_categorizations"`).
```ruby
class Author < ActiveRecord::Base
has_many :general_categorizations, -> { joins(:category).where("categories.name": "General") }, class_name: "Categorization"
has_many :general_posts, through: :general_categorizations, source: :post
end
authors = Author.eager_load(:general_categorizations, :general_posts).to_a
```
Generated eager loading query:
```sql
SELECT "authors"."id" AS t0_r0, ... FROM "authors"
-- `has_many :general_categorizations, -> { joins(:category).where("categories.name": "General") }`
LEFT OUTER JOIN "categorizations" ON "categorizations"."author_id" = "authors"."id"
INNER JOIN "categories" ON "categories"."id" = "categorizations"."category_id" AND "categories"."name" = ?
-- `has_many :general_posts, through: :general_categorizations, source: :post`
---- duplicated `through: :general_categorizations` part
LEFT OUTER JOIN "categorizations" "general_categorizations_authors_join" ON "general_categorizations_authors_join"."author_id" = "authors"."id"
INNER JOIN "categories" "categories_categorizations" ON "categories_categorizations"."id" = "general_categorizations_authors_join"."category_id" AND "categories"."name" = ? -- <-- filtering `"categories"."name" = ?` won't work
---- `source: :post` part
LEFT OUTER JOIN "posts" ON "posts"."id" = "general_categorizations_authors_join"."post_id"
```
Originally eager loading with join scope didn't work before Rails 5.2
(#29413), and duplicated through association with join scope raised a
duplicated alias error before alias tracking is improved in 590b045.
But now it will potentially be got incorrect result instead of an error,
it is worse than an error.
To fix the issue, it makes eager loading to deduplicate / re-use
duplicated through association if possible, like as `preload`.
```sql
SELECT "authors"."id" AS t0_r0, ... FROM "authors"
-- `has_many :general_categorizations, -> { joins(:category).where("categories.name": "General") }`
LEFT OUTER JOIN "categorizations" ON "categorizations"."author_id" = "authors"."id"
INNER JOIN "categories" ON "categories"."id" = "categorizations"."category_id" AND "categories"."name" = ?
-- `has_many :general_posts, through: :general_categorizations, source: :post`
---- `through: :general_categorizations` part is deduplicated / re-used
LEFT OUTER JOIN "posts" ON "posts"."id" = "categorizations"."post_id"
```
Fixes #32819.
2020-05-25 12:29:10 -04:00
|
|
|
has_many :general_categorizations, -> { joins(:category).where("categories.name": "General") }, class_name: "Categorization"
|
|
|
|
has_many :general_posts, through: :general_categorizations, source: :post
|
|
|
|
|
2018-01-10 17:18:35 -05:00
|
|
|
has_many :special_categories_with_conditions, -> { where(categorizations: { special: true }) }, through: :categorizations, source: :category
|
|
|
|
has_many :nonspecial_categories_with_conditions, -> { where(categorizations: { special: false }) }, through: :categorizations, source: :category
|
2016-01-20 15:53:17 -05:00
|
|
|
|
2016-08-06 13:37:57 -04:00
|
|
|
has_many :categories_like_general, -> { where(name: "General") }, through: :categorizations, source: :category, class_name: "Category"
|
2006-09-01 01:31:56 -04:00
|
|
|
|
2016-08-06 13:37:57 -04:00
|
|
|
has_many :categorized_posts, through: :categorizations, source: :post
|
|
|
|
has_many :unique_categorized_posts, -> { distinct }, through: :categorizations, source: :post
|
2006-05-06 19:37:56 -04:00
|
|
|
|
2021-05-31 12:27:47 -04:00
|
|
|
has_many :nothings, through: :kateggorizatons, class_name: "Category"
|
2005-12-11 13:06:51 -05:00
|
|
|
|
2006-03-20 20:07:16 -05:00
|
|
|
has_many :author_favorites
|
2016-08-06 13:37:57 -04:00
|
|
|
has_many :favorite_authors, -> { order("name") }, through: :author_favorites
|
2006-03-20 20:07:16 -05:00
|
|
|
|
2016-08-06 13:37:57 -04:00
|
|
|
has_many :taggings, through: :posts, source: :taggings
|
|
|
|
has_many :taggings_2, through: :posts, source: :tagging
|
|
|
|
has_many :tags, through: :posts
|
2017-10-26 19:22:16 -04:00
|
|
|
has_many :ordered_tags, through: :posts
|
2016-08-06 13:37:57 -04:00
|
|
|
has_many :post_categories, through: :posts, source: :categories
|
|
|
|
has_many :tagging_tags, through: :taggings, source: :tag
|
2012-07-13 14:34:40 -04:00
|
|
|
|
2016-08-06 13:37:57 -04:00
|
|
|
has_many :similar_posts, -> { distinct }, through: :tags, source: :tagged_posts
|
2017-10-26 19:22:16 -04:00
|
|
|
has_many :ordered_posts, -> { distinct }, through: :ordered_tags, source: :tagged_posts
|
2016-08-06 13:37:57 -04:00
|
|
|
has_many :distinct_tags, -> { select("DISTINCT tags.*").order("tags.name") }, through: :posts, source: :tags
|
2012-07-13 14:34:40 -04:00
|
|
|
|
2016-08-06 13:37:57 -04:00
|
|
|
has_many :tags_with_primary_key, through: :posts
|
2006-04-05 11:36:02 -04:00
|
|
|
|
2010-09-26 08:17:18 -04:00
|
|
|
has_many :books
|
2019-05-08 08:41:43 -04:00
|
|
|
has_many :published_books, class_name: "PublishedBook"
|
2017-05-02 15:37:06 -04:00
|
|
|
has_many :unpublished_books, -> { where(status: [:proposed, :written]) }, class_name: "Book"
|
2016-08-06 13:37:57 -04:00
|
|
|
has_many :subscriptions, through: :books
|
|
|
|
has_many :subscribers, -> { order("subscribers.nick") }, through: :subscriptions
|
|
|
|
has_many :distinct_subscribers, -> { select("DISTINCT subscribers.*").order("subscribers.nick") }, through: :subscriptions, source: :subscriber
|
2010-10-31 07:21:28 -04:00
|
|
|
|
2016-08-06 13:37:57 -04:00
|
|
|
has_one :essay, primary_key: :name, as: :writer
|
|
|
|
has_one :essay_category, through: :essay, source: :category
|
|
|
|
has_one :essay_owner, through: :essay, source: :owner
|
2010-10-19 07:47:19 -04:00
|
|
|
|
2016-08-06 13:37:57 -04:00
|
|
|
has_one :essay_2, primary_key: :name, class_name: "Essay", foreign_key: :author_id
|
|
|
|
has_one :essay_category_2, through: :essay_2, source: :category
|
2010-10-19 07:47:19 -04:00
|
|
|
|
2016-08-06 13:37:57 -04:00
|
|
|
has_many :essays, primary_key: :name, as: :writer
|
|
|
|
has_many :essay_categories, through: :essays, source: :category
|
|
|
|
has_many :essay_owners, through: :essays, source: :owner
|
2010-10-31 07:21:28 -04:00
|
|
|
|
2016-08-06 13:37:57 -04:00
|
|
|
has_many :essays_2, primary_key: :name, class_name: "Essay", foreign_key: :author_id
|
|
|
|
has_many :essay_categories_2, through: :essays_2, source: :category
|
2009-07-15 16:22:25 -04:00
|
|
|
|
2016-08-06 13:37:57 -04:00
|
|
|
belongs_to :owned_essay, primary_key: :name, class_name: "Essay"
|
|
|
|
has_one :owned_essay_category, through: :owned_essay, source: :category
|
2010-10-19 11:13:06 -04:00
|
|
|
|
2016-08-06 13:37:57 -04:00
|
|
|
belongs_to :author_address, dependent: :destroy
|
|
|
|
belongs_to :author_address_extra, dependent: :delete, class_name: "AuthorAddress"
|
2006-03-19 14:32:07 -05:00
|
|
|
|
2016-08-06 13:37:57 -04:00
|
|
|
has_many :category_post_comments, through: :categories, source: :post_comments
|
2010-10-31 07:21:28 -04:00
|
|
|
|
2016-08-06 13:37:57 -04:00
|
|
|
has_many :misc_posts, -> { where(posts: { title: ["misc post by bob", "misc post by mary"] }) }, class_name: "Post"
|
|
|
|
has_many :misc_post_first_blue_tags, through: :misc_posts, source: :first_blue_tags
|
2010-10-18 19:27:40 -04:00
|
|
|
|
2016-08-06 13:37:57 -04:00
|
|
|
has_many :misc_post_first_blue_tags_2, -> { where(posts: { title: ["misc post by bob", "misc post by mary"] }) },
|
|
|
|
through: :posts, source: :first_blue_tags_2
|
2010-10-12 13:16:31 -04:00
|
|
|
|
2016-08-06 13:37:57 -04:00
|
|
|
has_many :posts_with_default_include, class_name: "PostWithDefaultInclude"
|
|
|
|
has_many :comments_on_posts_with_default_include, through: :posts_with_default_include, source: :comments
|
2011-05-24 02:21:32 -04:00
|
|
|
|
2021-06-16 14:54:57 -04:00
|
|
|
has_many :posts_with_signature, ->(record) { where(arel_table[:title].matches("%by #{record.name.downcase}%")) }, class_name: "Post"
|
|
|
|
has_many :posts_mentioning_author, ->(record = nil) { where(arel_table[:body].matches("%#{record&.name&.downcase}%")) }, class_name: "Post"
|
|
|
|
has_many :comments_on_posts_mentioning_author, through: :posts_mentioning_author, source: :comments
|
|
|
|
has_many :comments_mentioning_author, ->(record) { where(arel_table[:body].matches("%#{record.name.downcase}%")) }, through: :posts, source: :comments
|
2014-05-08 11:39:02 -04:00
|
|
|
|
2019-12-28 22:40:16 -05:00
|
|
|
has_one :recent_post, -> { order(id: :desc) }, class_name: "Post"
|
|
|
|
has_one :recent_response, through: :recent_post, source: :comments
|
|
|
|
|
2016-03-03 10:49:31 -05:00
|
|
|
has_many :posts_with_extension, -> { order(:title) }, class_name: "Post" do
|
|
|
|
def extension_method; end
|
|
|
|
end
|
|
|
|
|
|
|
|
has_many :posts_with_extension_and_instance, ->(record) { order(:title) }, class_name: "Post" do
|
|
|
|
def extension_method; end
|
|
|
|
end
|
|
|
|
|
2018-04-25 04:36:27 -04:00
|
|
|
has_many :top_posts, -> { order(id: :asc) }, class_name: "Post"
|
|
|
|
has_many :other_top_posts, -> { order(id: :asc) }, class_name: "Post"
|
|
|
|
|
2020-05-12 15:18:45 -04:00
|
|
|
has_many :topics, primary_key: "name", foreign_key: "author_name"
|
2020-06-22 01:35:55 -04:00
|
|
|
has_many :topics_without_type, -> { select(:id, :title, :author_name) },
|
|
|
|
class_name: "Topic", primary_key: "name", foreign_key: "author_name"
|
2020-05-12 15:18:45 -04:00
|
|
|
|
2020-05-20 17:32:50 -04:00
|
|
|
has_many :lazy_readers_skimmers_or_not, through: :posts
|
2020-05-21 10:58:19 -04:00
|
|
|
has_many :lazy_readers_skimmers_or_not_2, through: :posts_with_no_comments, source: :lazy_readers_skimmers_or_not
|
2021-01-06 07:13:25 -05:00
|
|
|
has_many :lazy_readers_skimmers_or_not_3, through: :posts_with_no_comments_2, source: :lazy_readers_skimmers_or_not
|
2020-05-20 17:32:50 -04:00
|
|
|
|
2005-07-04 04:43:57 -04:00
|
|
|
attr_accessor :post_log
|
2009-09-08 11:22:45 -04:00
|
|
|
after_initialize :set_post_log
|
2005-07-04 04:43:57 -04:00
|
|
|
|
2009-09-08 11:22:45 -04:00
|
|
|
def set_post_log
|
2005-11-07 23:36:37 -05:00
|
|
|
@post_log = []
|
2005-07-04 04:43:57 -04:00
|
|
|
end
|
|
|
|
|
2007-06-29 23:31:48 -04:00
|
|
|
def label
|
|
|
|
"#{id}-#{name}"
|
|
|
|
end
|
|
|
|
|
2010-04-29 17:39:05 -04:00
|
|
|
def social
|
|
|
|
%w(twitter github)
|
|
|
|
end
|
|
|
|
|
2010-07-13 15:30:23 -04:00
|
|
|
validates_presence_of :name
|
|
|
|
|
2005-07-04 04:43:57 -04:00
|
|
|
private
|
2019-11-06 04:15:13 -05:00
|
|
|
def throw_abort(_)
|
|
|
|
throw(:abort)
|
|
|
|
end
|
|
|
|
|
|
|
|
def ensure_not_called(_)
|
|
|
|
raise
|
|
|
|
end
|
|
|
|
|
2005-11-07 23:36:37 -05:00
|
|
|
def log_before_adding(object)
|
2007-10-16 01:07:58 -04:00
|
|
|
@post_log << "before_adding#{object.id || '<new>'}"
|
2005-11-07 23:36:37 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def log_after_adding(object)
|
|
|
|
@post_log << "after_adding#{object.id}"
|
|
|
|
end
|
|
|
|
|
|
|
|
def log_before_removing(object)
|
|
|
|
@post_log << "before_removing#{object.id}"
|
|
|
|
end
|
|
|
|
|
|
|
|
def log_after_removing(object)
|
|
|
|
@post_log << "after_removing#{object.id}"
|
|
|
|
end
|
|
|
|
|
|
|
|
def raise_exception(object)
|
|
|
|
raise Exception.new("You can't add a post")
|
|
|
|
end
|
|
|
|
end
|
2006-03-19 14:32:07 -05:00
|
|
|
|
|
|
|
class AuthorAddress < ActiveRecord::Base
|
|
|
|
has_one :author
|
2008-01-19 00:30:42 -05:00
|
|
|
|
|
|
|
def self.destroyed_author_address_ids
|
2010-03-07 19:53:21 -05:00
|
|
|
@destroyed_author_address_ids ||= []
|
2008-01-19 00:30:42 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
before_destroy do |author_address|
|
2010-03-07 19:53:21 -05:00
|
|
|
AuthorAddress.destroyed_author_address_ids << author_address.id
|
2008-01-19 00:30:42 -05:00
|
|
|
end
|
2006-03-20 20:07:16 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
class AuthorFavorite < ActiveRecord::Base
|
2019-02-26 21:57:10 -05:00
|
|
|
belongs_to :author
|
|
|
|
belongs_to :favorite_author, class_name: "Author"
|
|
|
|
end
|
|
|
|
|
|
|
|
class AuthorFavoriteWithScope < ActiveRecord::Base
|
|
|
|
self.table_name = "author_favorites"
|
|
|
|
|
2019-02-26 18:07:13 -05:00
|
|
|
default_scope { order(id: :asc) }
|
|
|
|
|
2006-03-20 20:07:16 -05:00
|
|
|
belongs_to :author
|
2016-08-06 13:37:57 -04:00
|
|
|
belongs_to :favorite_author, class_name: "Author"
|
2006-05-06 19:37:56 -04:00
|
|
|
end
|