Вывод статей с published=1


(МАКСИМ МАЙОРОВ) #1

Привет, задача не нова, я хочу выводить статьи, у которых published=1. В экшкне index я понял как это сделать, но, если после слеша поставить id статьи, можно её открыть. Как это сделать для экшкна show? Он пустой. Гуглинг типа rails action show post where published=1 не помогает. Подскажите что искать, плиз. Хартла читал, не помню, что бы он эту тему освещал.


(Kvokka) #2

понять написанное не легко
но суть такова: когда ты выводишь индекс ты выводишь много статей. фильтр published в твоем случае имеет смысл. а вот когда ты выводишь 1 статью, то, уже вопрос- что ты хочешь фильтровать? или ты хочешь ограничить доступ?

вцелом, постановка задачи на данный момент стоит на уровне поиска телепата.


(Evgeniy) #3

Да не, все просто.

В экшене show вместо Post.find(params[:id]) нужно использовать Post.where(published: 1).find(params[:id]).


(Kvokka) #4

плохому ты молодняк учишь. видимо, экшен show не только будет опубликованное показывать, вот уже еще не успев создать мы впоролись на рефакторинг.
дело контроллера просто отдать. но не знать, как это собирается

так что норм, если в модели был бы метод типа (ну или вложенная модель, но это уже фиг с ним)

scope :published, -> { where published: 1 }

ну и в контроллере тогда будет

Post::Published < ActionController
  def show
    Post.published.find params[:id]
  end
end

ну и роут к нему. тогда все будет на местах.


(Evgeniy) #5

Как здорово, что ты все объяснил, просто я считаю, что если у человека проблема с построением настолько простого запроса, то стоит давать ему по одному шагу за раз)


(Kvokka) #6

ну так моя- не учитель, моя- кодообсиратель :slight_smile:
привычкасъ


(МАКСИМ МАЙОРОВ) #7

Я хочу ограничить доступ, т.е. статьи, у которых published=0 прочитать нельзя.


(МАКСИМ МАЙОРОВ) #8

Что то подобное я находил в сети, но мне не помогло, писал это в модели, а это:

в экшене show. Но это:

там не освещалось. Этот подход работает, что бы не было этой ошибки: Couldn’t find Post with ‘id’=16 [WHERE posts.published = ?] видимо и нужен роут. Будьте любезны, если начали, помогите до конца, пожалуйста. Документацию мне всё равно читать придётся, вопросов ещё масса.


(МАКСИМ МАЙОРОВ) #9

Возвращает это:
Couldn’t find Post with ‘id’=16 [WHERE posts.published = ?]


(Kvokka) #10

по итогу, за работу на руби потому и платят побольше, ибо это нормально, что не освещалось.
Есть официальная документация, ты ее не читал еще, но там все это есть.
Этот путь будет состоять из реально большого количества боли, лучше к ней привыкнуть с самого начала. А еще лучше, быть настоящим извращенным мазохистом


(МАКСИМ МАЙОРОВ) #11

http://guides.rubyonrails.org

Эта?


(МАКСИМ МАЙОРОВ) #12

Сделал так:

  def show
    if Post.find(params[:id]).published?
    @post = Post.find(params[:id])
  else
    redirect_to posts_url
  end
  end

и в модели:

scope :published, -> { where published: 1 }

Работает, но похоже на говнокод.


(Виктор) #13

Ну смотри, ты хотел, чтобы не получалось просмотреть неопубликованную статью, изменив адрес.
Ты этого добился, когда переходишь на url неопубликованной статьи вылезает ошибка “среди опубликованных статей статьи с id=16 не найдено”. Или ты хотел получить что-то другое?

Для твоей реализации scope в модели тебе и не нужен. Да и мне кажется, для show фильтровать, а потом в отфильтрованном искать, это тоже не очень хороший путь.


(МАКСИМ МАЙОРОВ) #14

Нет, всё работает как надо, но этот кусок:

@post = Post.find(params[:id])

уже встречается:

  def set_post
      @post = Post.find(params[:id])
    end

Кажется, что можно сделать короче код, но, опыта не хватает понять как.


(МАКСИМ МАЙОРОВ) #15

Есть ещё такой контроллер:

class TagsController < ApplicationController

	def show
		@tag = Tag.find_by(name: params[:id])
		@posts = @tag.posts.published
	end

end

На published не ругается, эта область видимости, не знаю, правильно ли назвал, объявлена в модели post. Но это не работает. Получается, что на статью по id перейти не могу, index её тоже не показывает, но по тегу её увидеть можно, есть ссылка на статью, но увидеть её опять же нельзя, а задумано не так.


(Виктор) #16

Тогда так.

def show
  set_post
  redirect_to posts_url if @post.nil?
end

protected

def set_post
  @post = Post.find_by(id: params[:id])
end

(Виктор) #17

Когда вы говорите, что по тегу ее можно увидеть, что вы имеете ввиду?
В переменную @posts она не попадает.
“Есть ссылка на статью, но увидеть ее нельзя”, что вы имеете ввиду?

Опишите, как оно должно работать по задумке?


(МАКСИМ МАЙОРОВ) #18

Контроллер posts_controller выводит как надо, index не выводит статью, по id после слеша, на статью не попасть. Есть ещё один контроллер, tags_controller, он выводит статьи по тегам, присвоенным статье во время создания, в отдельной вьюхе. У него один экшен:

class TagsController < ApplicationController

	def show
		@tag = Tag.find_by(name: params[:id])
		@posts = @tag.posts
	end

end

Мне надо дописать в этом экшене что то, что бы статьи не было в выводе, если published=0.
Надеюсь, так яснее картина.


(Виктор) #19

вы зачем убрали? С ним не будет выводить, если, как вы говорите, скоуп у вас есть в модели.

scope :published, -> { where published: 1 }


(МАКСИМ МАЙОРОВ) #20

Так с ним не работает, это оригинальный код, без моих правок, что бы в заблуждение не вводить.