evgenykungurov
@evgenykungurov
Программист Ruby/Rails/Системный администратор

Самописные рельсы. Как выполнить метод внутри вьюхи?

Здравствуйте. Пытаюсь сделать свой MVC фреймворк на подобии рельсов, нужно для саморазвития. Реализовал базовый контроллер и для каждого контроллера вьюхи, все как и в рельсах. Сделал работу с общим шаблоном через yield, но не могу понять, как передать метод внутрь шаблона? Например у меня главный шаблон и там все разделено на блоки, допустим блок <%= render :head %> ниже идет yield для вставки шаблона на основе имени контроллера и экшена.
Пока сделано так:

require 'erubis'

module LiveQueue
	class Controller
		def render(views_action, options = {})
			template = File.read(File.join('app', 'views', controller_name, "#{views_action}.html.erb"))
			Erubis::Eruby.new(template).result(options)
		end

		def default_template(&block)
			template = File.read(File.join('public', 'application.html.erb'))
			Erubis::Eruby.new(template).evaluate(&block)
		end

		def render_layout(name)
			template = File.read(File.join('app', 'views', 'layouts', "_#{name}.html.erb"))
		end

		private

		def controller_name
			self.class.to_s.gsub(/Controller$/, "").downcase
		end
	end
end


Это код гема, а уже в приложении
class AdminController < LiveQueue::Controller
	def index
		default_template { render(:index, name: 'Евгений', last_name: 'Кунгуров') }
	end
end

Реализация render немого выглядит избыточно и скорее всего не так нужно делать, т.к. приходится передавать в главный шаблон нашу вьюху, как отрефакторить примерно догадываюсь, получится один метод render, и если нам не нужен главный шаблон сделаю типа того render default_temp: none.

В консоли пробовал сделать вручную так:
template = "привет <%= render %>"  
def  render;  'еще раз привет';  end
Erubis::Eruby.new(template).evaluate { render }
Так метод передается.


Пока с таким кодом пробовал сделать всяко разно, если учесть пример из консоли пробовал так
def default_template(&block)
	template = File.read(File.join('public', 'application.html.erb'))
	Erubis::Eruby.new(template).evaluate(&block) { метод, который надо передать }
end

Но все равно ругается NoMethod на мой метод в Erubis::Context.
Мб я вообще не так делаю? Если даже получилось бы, пришлось бы передавать все мои хэлперы во вьюхи. Смотрел Action View, целый фреймворк куда мне это все реализовать, хотя бы это сделать. Порылся не понял как там делается.
Все примеры в нете в основном связаны с yield и передачей переменных
  • Вопрос задан
  • 270 просмотров
Решения вопроса 1
evgenykungurov
@evgenykungurov Автор вопроса
Программист Ruby/Rails/Системный администратор
В общем я решил проблему, как и догадывался я расширил класс Context модуля Erubis.
Когда мы делаем Erubis::Eruby.new(template).evaluate, метод evaluate создает экземпляр Context.new, а так как я его расширил его своими методами, все заработало
module Erubis
  class Context
     include MyHelpers
  end
end

Спс за поддержку, ковыряться в исходниках полезное и интересное дело, теперь мой кругозор хорошо расширился.
Еще вот ссылка на интересный блог , как работает рендеринг в рельсах
За доступ во вьюхах в рельсах отвечают 2 метода helper, helper_method
Может быть кому-нибудь пригодится)
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@CapeRatel
Выскажу свое мнение, не более.
Мужик ты молодец. Это очень крутая практика. Каждый должен написать свой велик, чтобы понять как работает язык, как работают фреймы.

НО:
если тут начнут за тебя разбирать "твои рельсы", то ничего хорошего не получится.

Совет:
Попробуй каждый этап логики проверить и пройтись по всем файлам. Также каждое звено погугли по докам и разберись как должно работать.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы