This one baffles me. I've banged my head on it for a couple of weeks now and am getting nowhere. Sorry if it's obvious, I'm still a rails newbie ish...
The app is making an API call to the Unsplash pictures service.
As such the application_helper has the following method:
def show_photo(size)
#photo = Unsplash::Photo.random(query:"cars")[:urls][size.to_sym]
end
the view has the following:
<%= image_tag(show_photo('small'), height: "220", width:"220") %>
And that displays fine.
The issue is when I want to pull some other methods from the oject. I've added another method in the application helped like this:
def show_author
#photo.user.name
end
and the corresponding view:
Photo by: <%= show_author %>
I then get this error:
undefined method `user' for #
However when calling the method in the Rails console it works fine:
#photo = Unsplash::Photo.random(query:"cars")
=> #<Unsplash::Photo:0x00000004fcf950 #attributes=#<OpenStruct id="CKeoh-
90U3E", created_at="2017 .......
2.3.0 :003 > #photo.user.name
=> "Florian Schneider"
What do I need to do to have the user.name available in the view?
Thanks a lot in advance,
Rodolphe
#photo is not the photo, it looks like you're calling some meta-data on #photo with [:urls][size.to_sym] and you can't call .user on top of that meta-data.
You're essentially saying Unsplash::Photo.random(query:"cars")[:urls][size.to_sym].user
You might want to do the following:
def photo
#photo ||= Unsplash::Photo.random(query:"cars")
end
def resized_photo(size)
photo[:urls][size.to_sym]
end
def photo_author_name
photo.user.name
end
btw #photo ||= is memoizing the API call so you're not making the same call multiple times.
Related
I'm trying to get a variable from the controller over to the model. Its the value of a checkbox passed up from the View. I cant see it in the controller (0 or 1) and just need to get it to the model. I have seen tons of examples on here but none of them seem to work for me. Maybe its something about the Ruby environment we have setup? Its a Rails 5 environment.
Here is what I have tried so far and the errors it gives in the logs:
Controller:
#vin = Vehicle.create!
#results = #vin.myvin!(params[:vehicle][:vincheck])
Model:
def myvin!(localvin)
logger.info "MADE IT INTO VIN"
end
Error in development.log:
AbstractController::DoubleRenderError (Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action.
I'm not calling render or redirect!! Just trying to call the method in the model.
I have also tried a variation like:
Controller:
Vehicle.myvin(params[:vehicle][:vincheck])
Model:
def self.myvin(localvin)
logger.info "MADE IT INTO VIN"
end
But regardless... I always get that render error in the logs!
I have tried instantiating a new object:
Controller:
Vehicle.new(params[:vehicle][:vincheck])
Model:
attr_reader :localvin
def initialize(localvin)
logger.info "MADE IT INTO VIN"
end
When I do that I get:
500wrong number of arguments (given 0, expected 1)
Short Stack
app/models/vehicle.rb:25:in 'initialize'
app/controllers/vehicles_controller.rb:84:in 'new'
Anyone have any thoughts on how I can get this data over? Maybe it has something to do with the Vehicle Model itself? In the controller it gets instantiated at different places.
For example:
def index
#vehicles = Vehicle.active
end
def create
#this is where I am putting all my code
#not really sure how this is getting created since there was no
#initialize in the code before I added one
#vehicle = Vehicle.new(vehicle_params.merge(
created_by_id: current_user.id,
created_by_name: current_user.name,
deleted: false))
end
thanks!
I have a controller called blogger:
class BloggerController < ApplicationController
def home
end
def favoritePosts
#blogger = current_blogger
#favorites = #blogger.favorite_posts
end
def suggestedPosts
posts = Post.all
#suggestedPosts = posts.similar_posts
end
end
And in the Blogger model i have a method:
def similar_posts
title_keywords = Post.body.split(' ')
Post.all.sort do |post1, post2|
post1_title_intersection = post2.body.split(' ') & title_keywords
post2_title_intersection = post2.body.split(' ') & title_keywords
post2_title_intersection.length <=> post1_title_intersection.length
end
end
When i run the server its gives me an error:
undefined method `similar_posts' for #<Post::ActiveRecord_Relation:0x007fa365029760>
After searching on stackoverflow i tried def self.similar_postsbut it still gives the same error message. I also tried new in the controller like this #suggestedPosts = posts.new.similar_posts which still gives me the same error.
Any suggestions on how to overcome this?
You have 2 issues happening at the same time. The first is that you're using posts in your call, when you should be using something more like post.blogger. The specific object depends on what your intent actually is.
The second issue is that you're making the call to similar_posts on the association, not on an individual record. This can be resolved with a call to each on the association.
So, putting those together and looking at what you might have meant, I think that you might have intended this as your suggestedPosts method:
def suggestedPosts
posts = Post.all
#suggestedPosts = posts.map {|post| post.blogger.similar_posts }
end
I also changed the name of #suggestedDevelopers to #suggestedPosts, because I don't think that you meant 'developers' in this case. This should give you something closer to what it appear you were trying for.
I am trying to create a method that will update a column for all my users at a specific time. I am doing this with the 'whenever' gem but I don't really know where to place the method.
My Users table has a column with :grades that I want to update based on another method (grade). In the rails console, when I do:
user.update(:grades => user.grade)
This works fine. When I define the method within the rails console that I want like this:
def update_grades(users)
users.each do |user|
user.update(:grades => user.grade)
end
end
#users = User.all
update_grades(#users)
This works as well and updates the grades for all the users.
The problem is that I don't know where to place this method for it to work in my scheduler. I tried putting it in the user.rb model file but then when I call update_grades(#users) it gives me this error:
NoMethodError: undefined method `update_grades' for main:Object
I changed it to remove the (#users) and try to call update_grades or #users.update_grades neither of these work and I get this error:
NoMethodError: private method `update_grades' called for #<User::ActiveRecord_Relation:0x007fbb753b1b58>
Any ideas where I can place the method so that I can call update_grades(#users) or update_grades?
You can make it a class method on User
class User
def self.update_grades
all.each do |user|
user.update(:grades => user.grade)
end
end
end
This can be called as User.update_gradesa
Consider wrapping it in a transaction to speed it up:
def self.update_grades
transaction do
all.each do |user|
user.update(:grades => user.grade)
end
end
end
I want to add a bunch of predefined tags to a model.
I have added it to my params in the Controller:
def photo_params
params.require(:photo).permit(:image,:title, :description, :styles_list)
end
I have also included:
act_as_taggable_on :styles
Now I am just trying to add the tags but in my console I keep getting the following error:
Tried Photo.styles_list.add
got
NoMethodError: undefined method `styles_list' for #<Class:0x007fa9ee74aac8>
then I tried styles_list.add as described in documentation https://github.com/mbleigh/acts-as-taggable-on/wiki/Add-Tags
but I still get the same error, what am I doing wrong?
Photo.styles_list.add is trying to invoke the styles_list method on the Photo class. That is incorrect. The styles_list method is available on a photo object.
Create/find a photo object as follows:
#photo = Photo.new
#photo = Photo.find(params[:id])
Then a style can be tagged with the following:
#photo.styles_list.add("awesome")
See https://github.com/mbleigh/acts-as-taggable-on#usage for getting a better understanding of how the gem can be used.
I'm trying to make some changes to the show method in my events controller and noticed the changes making zero difference. I commented out the #event = Event.find_by_slug(params[:slug]) line and the show view still works and does not produce an error! I even deleted the entire show method and it still works. I thought for a moment I was working on a copy of the app, but it's definitely the correct one.
I've never had this problem before, but did recently upgrade my Rails version from 3.2.0 to 3.2.13. Wondering if there's a caching setting somewhere that's causing this. Has anyone experienced similar or got any pointers on where to look for a caching config setting perhaps?
EDIT - Code added
def show
#event = Event.find_by_slug(params[:slug])
#meta_title = "#{#event.headline} at #{#event.venue.name}, #{#event.venue.town} - #{#event.event_date.to_date.to_formatted_s(:my_format)}"
#meta_description = "#{#event.info.to_s.truncate(380, :separator => " ")}"
#facebook_image = "#{#event.event_image.url(:large)}"
respond_to do |format|
format.html # show.html.erb
format.json { render :json => #event }
end
end
The view is quite large, but I would call fields using something like this:
<h2><%= #event.headline %> TEST</h2>
'TEST' is something I just added to see if that would be rendered and it is, so i'm definitely editing the correct version of the app.
EDIT - New development in finding this bug
After extensive searches for dupe actions etc I gradually started trying to manually find the cause. First by scaffolding a new model and seeing if the same behaviour occurred and it didn't. Then looking at what was different, top to bottom in my event controller I started to comment out lines/actions and then test behaviour. Anyway, commenting out load_and_authorize_resource which I am using to call the CanCan gem and it's ability model the caused my app to behave as it should do, obviously now without my role based code.
Can anyone think why CanCan could be causing this?
CanCan have both load_resource, authorize_resource and load_and_authorize_resource. They all do what they say, so in your example will load_resource set the #event instance variable #event = Event.find(params[:id]). authorize_resource will just call authorize! #event before each action. load_and_authorize_resource will fist load the resource and then authorize as before.
Here is another example from the CanCan documentation on github:
class ArticlesController < ApplicationController
load_and_authorize_resource
def show
# #article is already loaded and authorized
end
end