I have an extension for RefineryCMS. In that extension I need to get data from object Block in the PagesController.
My code:
def show
if should_skip_to_first_child?
redirect_to refinery.url_for(first_live_child.url) and return
elsif page.link_url.present?
redirect_to page.link_url and return
elsif should_redirect_to_friendly_url?
redirect_to refinery.url_for(page.url), :status => 301 and return
end
#block = Refinery::Blocks::BlocksController::Block.find_by(:name => 'Footer')
render_with_templates?
end
In development the first launch is successful, but after refreshing or redirecting to another site's page:
uninitialized constant Refinery::Blocks::BlocksController::Block
can you paste whole code of your controller and model.
I think problem in this line.
#block = Refinery::Blocks::BlocksController::Block.find_by(:name => 'Footer')
You are trying to access from controller.
Use Model name like
Module::Model.find_by(:name => "Footer")
Answer: https://github.com/refinery/refinerycms/issues/3051
Related
New to Ruby on Rails and been cracking my head on this. I have been following this tutorial here to make this form to save records into my DB - https://human-se.github.io/rails-demos-n-deets-2020/demo-resource-create/
This is my controller:
class ViewaddparamController < ActionController::Base
def view_add_param
newParam = ViewaddparamController.new
respond_to do |format|
format.html{ render :viewaddparam, locals: { newParam: newParam } }
end
end
def add_param
# new object from params
mlParam = ViewaddparamController.new(params.require(:Viewaddparam_Controller).permit(:name, :machine_model, :parameter_1, :parameter_2, :parameter_3, :data_train_set, :start_date, :end_date))
# respond_to block
respond_to do |format|
format.html do
if mlParam.save
# success message
flash[:success] = "ML parameters saved successfully"
# redirect to index
redirect_to model_url
else
# error message
flash.now[:error] = "Error: parameters could not be saved"
# render new
render :viewaddparam, locals: { newParam: newParam }
end
end
end
end
end
My route:
get 'viewparam', to: 'viewaddparam#view_add_param'
post 'add_param', to: 'viewaddparam#add_param', as: 'add_param'
My view:
<%= form_with model: newParam, url: add_param_path, method: :post, local: true, scope: :Viewaddparam_Controller do |f| %>
...
I kept getting this error whenever I try to submit the form
ArgumentError in ViewaddparamController#add_param
Wrong number of arguments (given 1, expected 0)
The error highlighted at my controller class, line 11.
What am I doing wrong here? I looked through the tutorial over and over but I can't see the fault here.
Thanks in advance.
It seems that you’re treating ViewaddparamController as both the controller – which in Rails terms is what responds to user requests - and the data model.
There’s often a one-to-one correlation to controllers and models, especially if you’re following what’s known as the RESTful pattern. So if your model was a Product, you might set it up in routes using a resources directive:
resources :products
That would set the app up to expect to use a ProductsController. And, using a similar coding style to your example, that would look a little like:
class ProductsController < ApplicationController
def new
product = Product.new
render :new, locals: { product: product }
end
def create
product = Product.new(params.require(:product).permit(…))
# etc
end
# etc
end
So you can see from this example that controller and model are related, but are named differently.
By using your controller name where you should be using the model, you’re calling #new on the controller, which is not normally something you need to do – controller instances are managed by the Rails app framework. And their initialiser doesn’t take any arguments, so Ruby complains that an initialiser that takes 0 arguments is being given 1.
My website has an RSS feed with a route http://example.com/rss
I have now to provide a feed for Outbrain, and they need a feed with about 5000 contents. I can provide the feed "live" but I choose to add a task scheduled with whenever to save my feed offline in the public folder. Every night I will update the feed.
I add a class method to my content class...
def self.render_outbrain
data = render_to_string( :controller=>:NewsFeedController, :action => :outbrain )
File.open('outbrain.xml','w'){|f| f << data }
end
But it doesn't work in Rails 4.2:
NoMethodError: undefined method `render_to_string' for main:Object
I want to save the output of http://example.com/rss to a static file http://example.com/feed.rss
Edit
Here is my task:
task :generate_feed_rake => :environment do
session = ActionDispatch::Integration::Session.new(Rails.application)
session.get "/generate_feed"
end
Here is my controller
def generate_feed
# the news items
#items = Content.published.limit(1000)
# this will be our Feed's update timestamp
#updated = #items.first.updated_at unless #items.empty?
respond_to do |format|
format.atom { render :layout => false }
format.rss { redirect_to feed_path(:format => :atom), :status => :moved_permanently }
end
end
render_to_string is defined in ActionController::Base. Unless your class inherits from that class, it makes sense that your object doesn't know how to render_to_string.
It's not clear what exactly you're trying to accomplish, but the way render_to_string works is, in a controller, instead of rendering an HTML view for the browser, you simply send back the HTML as a string
I've got a long controller method with a lot of redirect conditions:
def show
get_param_user
if params[:id].match(/\D/)
#document = Document.where(:user_id => #user.id, :issue => params[:id]).first
else
#document = Document.find(params[:id])
end
unless #document.blank?
unless #document.template.name == "Media"
unless #document.retired?
#creator = User.find(#document.user)
if #creator == #user # if document exists, based on name and id
#document.components.each do |a|
redirect_to share_error_url, :flash => { :error => "#{#document.title} contains retired content and is now unavailable." } if a.retired? and return
end
render #document.template.name.downcase.parameterize.underscore
end
else # if retired
redirect_to share_error_url, :flash => { :error => "That document has expired." } and return
end
else # if media
redirect_to share_error_url, :flash => { :error => "Media has no public link." } and return
end
else # if document doesn't exist
redirect_to share_error_url, :flash => { :error => "Can't find that document. Maybe check your link. Or maybe it was deleted. Ask #{#user.name}." } and return
end
end
As you might guess, it's prone to errors under certain conditions. Is there a neater way to rewrite it to make it more robust? I know methods should have only one render or redirect_to each, but I'm not sure how else to achieve what I need.
Thanks!
A few specific and little things.
First, in general, better don't use until with an else condition, and even less if you can use an if:
unless #document.blank?
is the same as
if #document.present?
Second, you use
#creator = User.find(#document.user)
when usually you can simply use:
#creator = #document.user
The semantics is a bit different (in the first case if #document.user is nil you'll immediatelly get an exception, in the secnond case not), but the second is what you commonly need.
Third, if it is sensible, you can move code to the model away from the controller, and use some nice enumerators:
def has_retired_components?
#document.components.any?(&:retired?)
end
Also, your controller method is not that complex. It is just
if #document.present? and #document.showable? # also #document.try(:showable?)
render whatever
else
redirect_to error_url, flash: { error: error_message }
end
error_message may be the result of a method call (on the object itself if it makes sense). That way you move the logic to verify if the oject is showable somewhere else where it is less muddled with rendering logic.
The problem is that if you have a showable? method and another to show error messages, you have to be sure that the business logic is always correct in both. An option is to treat it similarly to how validations work: have a method (lets call it with the horrible name showable_validation here just to go on) that returns a hash with the errors and messages (the reasons for the object not being showable, like {title: 'this is an error message'}. The showable? method would then be:
def showable?
showable_validation.empty?
end
and then you would also have in the model something like:
def showable_error
showable_validation.values.first
end
And that would be the error_message (#document.showable_error). That way, the logic is only in one method.
How Do I use redirect and pass an object to the edit action? The following code does not work:
def edit
#promotion = Promotion.find_by_id(#params['promo_id'])
end
def update
promotion = Promotion.find(params[:promotion_profile][:promotion_id])
promo_perfil = promotion.profile
if promo_perfil.update_attributes(params[:promotion_profile])
redirect_to admin_edit_path(promotion.id => #params[:promo_id])
else
end
The edit action is looking for params['promo_id'] (why #params['promo_id']?).
So pass :promo_id this way:
redirect_to admin_edit_path(:promo_id => promotion)
You shouldn't redirect in this case just: render :action => :edit
This is standard Rails behaviour, you will see this in all scaffolded controllers as a way of re rendering the edit form with the current object in the update action without having to rely on stuffing objects into cookies to pass around.
I am building a small application in RoR that has a form asking for a URL. Once the URL has been filled in and submit button is pressed I have downloaded a web-scraping plugin scrAPI(which is working fine) which gets the of URL and creates a record in db with title.
My issue right now is that I am able to make the whole thing work if the URL is valid and scrAPI is able to process it. If a URL entered does not work it gives this "Scraper::Reader::HTTPInvalidURLError" which is expected, but my knowledge of working in Model is preventing me from handing that error in a correct manner.
Controller:
#controller
class ArticleController < ApplicationController
def savearticle
#newarticle = params[:newarticle]
#link = #newarticle["link"]
#id = #newarticle["id"]
Article.getlink(#link)
success = Article.find(:last).update_attributes( params[:newarticle] )
if success
render :partial => 'home/articlesuccess'
else
render :partial => 'home/articlebad'
end
end
end
# model
require 'scrapi'
class Article < ActiveRecord::Base
attr_accessor :getlink
def self.getlink(link)
scraper = Scraper.define do
process "title", :title => :text
result :title
end
uri = URI.parse(link)
Article.create(:title => scraper.scrape(uri))
end
end
How to:
1) Handle the Scraper::Reader::HTTPInvalidURLError properly, so text could be returned to view with proper error.
2) I would also like to know how I can return 'uri' from model and use it in the controller or view.
3) Also, I would like to return the ID of the Article created in Model so I can use that in the controller instead of doing find(:last) which seems like bad practice.
Something like...
class ApplicationController < ActionController::Base
rescue_from 'Scraper::Reader::HTTPInvalidURLError', :with => :invalid_scrape_url
private
def invalid_scrape_url
flash[:error] = 'The URL for scraping is invalid.'
render :template => 'pages/invalid_scrape_url'
end
end
rescue_from is what you need.
That's 1)
for 2) You could just use #uri but personally I'd create a new model called Scrape and then you can retrieve each Scrape that is attempted.
for 3) I'm not quite sure of the question but
#article = Article.create(:title => scraper.scrape(uri))
then
#article.id
Hope that helps!
(1) In Ruby, you can handle any exception as follows:
begin
# Code that may throw an exception
rescue Scraper::Reader::HTTPInvalidURLError
# Code to execute if Scraper::Reader::HTTPInvalidURLError is raised
rescue
# Code to execute if any other exception is raised
end
So you could check for this in your controller as follows:
begin
Article.getlink(#link)
# all your other code
rescue Scraper::Reader::HTTPInvalidURLError
render :text => "Invalid URI, says scrAPI"
rescue
render :text => "Something else horrible happened!"
end
You'll need to require 'scrapi' in your controller to have access Scraper::Reader::HTTPInvalidURLError constant.
I would probably make the creation of the new Article and the call to scrAPI's method separate:
title = scraper.scrape(uri)
Article.create(:title => title)
(2) and (3) In Ruby, the last statement of a method is always the return value of that method. So, in your self.getlink method, the return value is the newly created Article object. You could get the ID like this in your controller:
article = Article.getlink(#link)
article_id = article.id
You may need to refactor the code a bit to get the results you want (and make the code sample on the whole cleaner).