No Method Error // Helper // Rails 3 - ruby-on-rails

I'm trying to get my admin avatar from Gravatar using my email address. I copied some code from Ryan Bate's Railscast http://railscasts.com/episodes/244-gravatar
The application helper:
module ApplicationHelper
def avatar_url(current_admin)
if current_admin.avatar_url.present?
current_admin.avatar_url
else
default_url = "#{root_url}images/guest.png"
gravatar_id = Digest::MD5.hexdigest(current_admin.email.downcase)
"http://gravatar.com/avatar/#{gravatar_id}.png?s=48&d=#{CGI.escape(default_url)}"
end
end
end
My Application controller has helper :all
My view has <%= image_tag, avatar_url(current_admin), :class => "img-circle" %> The error I get is NoMethodError and more specifically, undefined method 'avatar_url' for #<Admin:0x007fc4ae804ee8>
The current_admin is set by devise.

I looked through this RailsCast and it is very poor actually. At one point Ryan says just to add avatar_url to User without giving any hint where data for this field should come from.
So unfortunately you need to add this field by yourself by creating a rails migration if using ActiveRecord.
rails g migration AddAvatarUrlToUser avatar_url
But this is ONLY required if you want to allow users having their own non-gravatar images. If you want to stick with gravatar ones you can skip everything from section "Using Images From Other Sites With OmniAuth"

The error is telling your that the attribute avatar_url does not exists in your Admin model.
You should add it creating a rails migration if using ActiveRecord.

Related

Rails - Creating Associated Object with URL params

I’m wanting to create an Asset from an Organisation Show page. I need the Organisation ID to be passed to the Asset for creation.
# ../models/organisation.rb
has_many :assets
# ../models/asset.rb
belongs_to :organisation
I have a button to create an asset, which is passing the organisation.id in the URL params.
# ../views/organisations/show.html.erb
<%= link_to 'New Asset', new_asset_path(:organisation_id => #organisation.id) %>
I'm able to access the organisation_id value in the ../views/assets/new view, however, when I submit the form I'm receiving a “Method not allowed” error.
# ../controllers/assets_controller.rb
def create
#asset = Asset.new(params[:organisation_id])
...
end
Q1: Why am I getting this error:
Q2: Is there another way to pass the organisation_id through to the Asset new page? I.e. not in the URL.
Q3: If I can only pass the ID through the URL, Is there a way to stop a user tampering with it? I.e. changing the Org ID to something else and saving the asset to another organisation.
Q4: Would nested resources help in this instance?
Rails 5.0.0.1, Ruby 2.3.1
You need to tell Asset.new what the organisation_id param is for eg:
#asset = Asset.new(:organisation_id => params[:organisation_id])
otherwise you're just passing it a random number and it's going "wtf is this?" :D
(well, technically it's looking for a version of the new method that takes a single argument that isn't a hash... which it can't find, then telling you that method doesn't exist... but same diff). ;)
I think you should use like:
def create
#asset = Asset.new(organisation_id:params[:organisation_id])
end
Q.1 - The error is due to the name of the model - "Assets". This is a reserved word in Rails.
It can be fixed by moving the asset pipeline to another mount point. For example:
# config/initializers/assets.rb
Rails.application.config.assets.prefix = '/pipeline_assets'
As mentioned here:
405 Error when trying to POST a file in rails
Rails 4 Method Not Allowed after Upgrading from Rails 3

railstutorial.org - make new users follow admin users

I've followed Michael Hartl's Ruby on Rails Tutorial making an app like Twitter and I want to change it so that all new users to automatically 'follow' the Admin/s.
I've tried to do it following answers to similar questions here and here, but they throw errors on account creation. Here's the relevant section of my user controller.
Edit: find_all_by_admin is deprecated in Rails 4.2.0 as explained in the selected answer by Vinay.
controllers/users_controller.rb
class UsersController < ApplicationController
...
def follow_admins
admins = User.find_all_by_admin(true) # EDIT - Deprecated: May have worked prior to rails 4.2
admins.each do |admin|
self.follow!(admin)
end
end
The error message is
NoMethodError in UsersController#create
undefined method `find_all_by_admin' for #
It seems to me that there is no column with admin name in your User model as we might can see Michael Hartl's sample_app_3rd_edition
So in order to make follow_admins method work you need to add admin column in users table type boolean and default: false.
def follow_admins
admins = User.find_all_by_admin(true) # would be worked in rails 4.0 not rails 4.2.2
admins = User.where(admin: true) # Should be work in rails 4.2.2
# Most of the Dynamic finder has been removed form rails 4.2.2
admins.each do |admin|
self.follow!(admin)
end
end
note As I mention in my answer default to false ,It is not mandatory but as you are following Michael Hartl's Ruby on Rails Tutorial It good to go accordingly .
hope this answer would help you !!!
It's likely you never defined the find_all_by_admin method in the User model.
Open the User model file and check if the method is there. If not, define it as a class method.

Undefined method 'url_for' while rendering a Rails 2.3.x template inside a ActiveRecord model

I know that this not an "acceptable" practice but as a background process I am caching a rendered Rails partial into the database for faster output via JSONP. I have found many resources on the topic and successfully output a Rails 2.3.x partial within a ActiveRecord model, BUT if I use dynamic URLs within a partial Rails blows up.
I get a successful output (minus the dynamic URLs) with this...
def self.compile_html
viewer = Class.new(ApplicationController)
path = ActionController::Base.view_paths rescue ActionController::Base.view_root
Question.all.each do |q|
q.html = ActionView::Base.new(path, {}, viewer).render(:partial => "questions/cached_output", :locals => { :question => q })
sleep 1 # hold for complete output and debugging only
q.save( false ) # bypass validations
end
return "Caching complete"
end
I have tried including ActionController::UrlWriter Modules and ActionView::Helpers::UrlHelper with no luck. I cannot seems to find the instantiation/inclusion order to allow the partial to access ActionController::Base.new.url_for() to write the dynamic routes to the partial.
I did attempt a similar process as RoR: undefined method `url_for' for nil:NilClass without luck
I know that render_anywhere is a solution for Rails 3.x apps, but I am working in Rails 2.3.11
Thoughts?
I have an old app that I had to do something similar (but made use of polymorphic_path and polymorphic_url) in a model.
The following includes gave me access to url_for and polymorphic_path etc.
include ActionView::Helpers::UrlHelper
include ActionView::Helpers::TagHelper
include ActionController::PolymorphicRoutes
include ActionController::UrlWriter

how do i get the "current_user" in a "visible do" block in config/initializers/rails_admin.rb

I'm trying to implement something similar to this:
RailsAdmin.config do |config|
config.model Team do
list do
field :name
field :created_at
field :revenue do
visible do
current_user.roles.include?(:accounting) # metacode
end
end
end
end
end
I know in the README it says the example is theoretical, but I keep getting that current_user is not found within that block. I'm authorizing with CanCan:
RailsAdmin.authorize_with :cancan
At the top of rails_admin.rb in config/initializers
Can anyone tell me how to get current_user available within the visible block? I'd like to only show certain fields in the "List" view if a user is an admin.
Since current_user is included as a helper in the view, you can get it through the bindings hash:
visible do
bindings[:view].current_user.has_role? :admin # This works for Devise
end
I got the idea from this other question: How to set the user to current_user when creating a new model using rails_admin
More info about rails_admin bindings in its wiki: https://github.com/sferik/rails_admin/wiki/Railsadmin-DSL
Hope it helps.
Initializers are run once on application startup, so I don't think you can get a current user from within an initializer like this.
I have not tried this myself, but you may find this useful:
https://github.com/sferik/rails_admin/issues/559
In short, define RailsAdmin::Config.current_user_method in the rails_admin initializer.

Permalinks with Ruby on Rails (dynamic routes)

I am currently developing a blogging system with Ruby on Rails and want the user to define his "permalinks" for static pages or blog posts, meaning:
the user should be able to set the page name, eg. "test-article" (that should be available via /posts/test-article) - how would I realize this in the rails applications and the routing file?
for user-friendly permalinks you can use gem 'has_permalink'. For more details http://haspermalink.org
Modifying the to_param method in the Model indeed is required/convenient, like the others said already:
def to_param
pagename.parameterize
end
But in order to find the posts you also need to change the Controller, since the default Post.find methods searches for ID and not pagename. For the show action you'd need something like this:
def show
#post = Post.where(:pagename => params[:id]).first
end
Same goes for the other action methods.
You routing rules can stay the same as for regular routes with an ID number.
I personally prefer to do it this way:
Put the following in your Post model (stick it at the bottom before the closing 'end' tag)
def to_param
permalink
end
def permalink
"#{id}-#{title.parameterize}"
end
That's it. You don't need to change any of the find_by methods. This gives you URL's of the form "123-title-of-post".
You can use the friendly_id gem. There are no special controller changes required. Simple add an attribute for example slug to your model..for more details check out the github repo of the gem.
The #63 and #117 episodes of railscasts might help you. Also check out the resources there.
You should have seolink or permalink attribute in pages' or posts' objects. Then you'd just use to_param method for your post or page model that would return that attribute.
to_param method is used in *_path methods when you pass them an object.
So if your post has title "foo bar" and seolink "baz-quux", you define a to_param method in model like this:
def to_param
seolink
end
Then when you do something like post_path(#post) you'll get the /posts/baz-quux or any other relevant url that you have configured in config/routes.rb file (my example applies to resourceful urls). In the show action of your controller you'll just have to find_by_seolink instead of find[_by_id].

Resources