I am using cell to render Navigation Bar for current_user devise. But went i try to render page i get an error. I am using rails 7 and ruby 3.0.2
Error
undefined method `new_user_session_path' for #<Navigation::Cell::Show:0x00007fac566e3570 #model=#<User id: 1, email: "email#gmail.com", first_name: "Otto", last_name: "Otto", phone: nil, birthday: nil, gender: nil, city: nil, street: nil, house: nil, apartment: nil, created_at: "2023-01-07 18:10:10.925669000 +0000", updated_at: "2023-01-07 18:30:10.207258000 +0000">, #options={}>
My application.html.erb
<body>
<%= Navigation::Cell::Show.(current_user) %>
<%= yield %>
</body>
Gemfile
gem 'trailblazer-cells', '~> 0.0.3'
gem 'trailblazer-rails', '~> 2.4', '>= 2.4.3'
gem 'cells-erb', '~> 0.1.0'
Navigation::Cell:Show (app/concepts/navigation/cell/show.rb)
class Navigation::Cell::Show < Trailblazer::Cell
include Devise::Controllers::Helpers
include ActionView::Helpers::UrlHelper
include Cell::Erb
def show
render
end
private
def username
"#{model.first_name} #{model.last_name}"
end
def current_user
model
end
def profile_link
link_to username, new_user_session_path(current_user.id)
end
def logout_link
link_to 'Log Out', destroy_user_session_path, method: :delete
end
def login_link
link_to 'Login', new_user_session_path
end
def registration_link
link_to 'Registration', new_user_registration_path
end
end
And my view (app/concepts/navigation/view/show.erb)
<nav>
<div>
<% if current_user %>
<h1><%= profile_link %></h1>
<%= logout_link %>
<% else %>
<%= login_link %>
<%= registration_link %>
<% end %>
</div>
</nav>
I try to include include ActionView::Helpers::UrlHelper it didn`t work.
When i add gem gem 'cells-rails' to rails app i have another error that looks like this
error
Your error
undefined method `new_user_session_path'
This method is from routes URL helpers (named route helper)
You need this line additionally:
include Rails.application.routes.url_helpers
Related
So I'm using the following in both my show and index:
<%= image_tag posts.avatar(:large), alt: 'Avatar for #{posts.title}', class: 'img-responsive' %>
Since they are the same in both I'm trying to move them to a view helper. Then in my views I'm putting:
<%= post_image_tag %>
My initial take was the following:
def post_image_tag
image_tag posts.avatar(:large), alt: 'Avatar for #{posts.title}', class: 'img-responsive'
end
I end up with : undefined local variable or method `posts' for #<#:0x007fcdd273e860>
Did you mean? #posts
Cool. So I change it to:
def post_image_tag
image_tag #posts.avatar(:large), alt: 'Avatar for #{posts.title}', class: 'img-responsive'
end
Now I end up with: undefined method `avatar'.
So I decided that it might just be that I'm not referencing it correctly and trying to pull ActiveRecord on a single post so I try:
def post_image_tag
#posts.each do |posts|
image_tag posts.avatar(:large), alt: 'Avatar for #{posts.title}', class: 'img-responsive'
end
end
At this point something FINALLY renders on the page. Except it looks like an HTML nightmare with:
[#<SpudPost id: 1, spud_user_id: 2, title: "The Top ", content: "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transi...", comments_enabled: false, visible: true, published_at: "2018-01-30 14:45:58", created_at: "2018-02-05 17:41:42", updated_at: "2018-02-05 17:41:42", url_name: "the-top", is_news: false, meta_keywords: nil, meta_description: nil, content_format: "HTML", content_processed: nil, blog_key: "blog", custom_author: nil, identifier: "9b0d97c9-6855-4ad6-85ac-cade6012b5de", avatar_file_name: "ice.jpg", avatar_content_type: "image/jpeg", avatar_file_size: 68494, avatar_updated_at: "2018-02-05 17:41:40">,
It goes further repeating the next item and the next, etc. What in the world can I put on the image_tag to make it render correctly? I've also tried changing the view helper in my view to:
<%= raw(post_image_tag)%>
Then I end up with [#, #, #, #]
You took a wrong turn in this rabbit hole. Go back to your first version of the helper and pass the post as parameter
def post_image_tag(post)
image_tag(post.avatar(:large), alt: 'Avatar for #{post.title}', class: 'img-responsive')
end
# this "posts" should really be named "post", since it's a single post,
# not a collection of them.
<%= post_image_tag(posts) %>
The image is for 1 post, so you should name the variable 'post' and not 'posts'. Anyway this is just for clarity and not an error.
You can define a helper that accepts a param:
def post_image_tag post
image_tag post.avatar(:large), alt: 'Avatar for #{post.title}', class: 'img-responsive'
end
and call it this way (assuming post is 1 post):
<%= post_image_tag(post) %>
If you have many posts in #posts, you should do:
<%= #posts.each do |post| %>
<%= post_image_tag(post) %>
<% end %>
You can also make another helper to handle many posts (it may need some changes, but you get the idea):
def posts_image_tag posts
result=''
posts.each do |post|
result += post_image_tag(post)
end
result.thml_safe
end
and call it this way (assuming #posts has all your posts):
<%= posts_image_tag(#posts) %>
hi ive just started to learn ruby on rails so i might make some little obvious mistakes but theres one thing i cant get around,
my controller action currently passes the variable to my view:
class HomepageController < ApplicationController
def index
end
def Value
#users = User.all
render "homepage/Value"
end
end
and this is my current view:
<ul class="users">
<% #users.each do |user| %>
<%= user.first_name %>
<% end %>
</ul>
this outputs nothing on my view,
if i change the each statement to:
<%= #users.each do |user| %>
it displays :
[#<User id: 1, first_name: "hello", last_name: "world", email: "", password: nil, created_at: "2017-08-31 10:33:01", updated_at: "2017-08-31 10:33:01">, #<User id: 2, first_name: nil, last_name: "anewworld", email: "emailnew", password: "123", created_at: "2017-08-31 12:35:41", updated_at: "2017-08-31 12:35:41">]
i have absolutely no clue why <%= user.first_name %> wouldnt work
<ul class="users">
<% if #users %>
<% #users.each do |user| %>
<li>
<%= user.first_name %>
</li>
<%else%>
<li> No Users </li>
<%end%>
</ul>
"li" tag missing
so im using the ruby twitter gem and api in conjunction with omniauth, to log into twitter via a simple rails app, and return the first 20 followers of a user. The main piece of code to do this is a method in a lib file stating:
def followers
client.followers.take(20)
end
For some reason, the app works perfectly locally, but after being deployed to heroku, it displays my first follower, 20 times repeated, as opposed to the first 20 followers. Any help would be appreciated. Here is my code:
I have a basic twitter api app in rails, which works perfectally locally, however when I pushed to Heroku it doesn't work and upon checking the logs there is an error saying uninitialized constant WelcomeController::TwitterApi. I can not find out how to rectify this. Many thanks.
lib/twitter_api.rb
class TwitterApi
def initialize(user)
#user = user
end
def our_public_tweets
client.user_timeline(user, count: 1, exclude_replies: true, include_rts: false)
end
def followers
client.followers.take(20)
end
private
attr_reader :user
def client
#client ||= Twitter::REST::Client.new do |config|
config.consumer_key = Rails.application.secrets.twitter_api_key
config.consumer_secret = Rails.application.secrets.twitter_api_secret
config.access_token = user.token
config.access_token_secret = user.secret
end
end
end
application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
# to enable the current_user variable to be used in the view file
helper_method :current_user
end
welcome_controller.rb
class WelcomeController < ApplicationController
require 'twitter_api'
def index
#twitter_api = TwitterApi.new(current_user)
end
end
views/welcome/index.html.erb
<div class="wrapper">
<h1>OMNIAUTH AND TWITTER API</h1>
<!-- <%= link_to "Sign in with Twitter", "/auth/twitter" %> -->
<% if current_user %>
<div id="sign_in_wrapper">
<p id="sign_in">Signed in as <span><%= current_user.name %></span> </p>
<%= image_tag current_user.profile_image, class: "profile_image" %>
<p><%= link_to "Sign out", signout_path, id: "sign_out" %></p>
</div>
<div class="public_tweets">
<p>Latest tweet from <%= current_user.name %>:</p>
<% #twitter_api.our_public_tweets.each do |tweet| %>
<% cache('our_public_tweets', expires_in: 6.hours) do %>
<%= parsed_tweet(tweet) %>
<% end %>
<% end %>
</div>
<ul class="followers">
<p>First 20 followers for <%= current_user.name %>:</p>
<% #twitter_api.followers.each do |follower| %>
<% cache('followers', expires_in: 6.hours) do %>
<li><%= follower.name %></li>
<hr>
<% end %>
<% end %>
</ul>
<% else %>
<%= link_to "/auth/twitter", id: "link_button" do %>
<i class="fa fa-twitter fa-3x"></i>
<% end %>
<p class="date">Click the twitter icon to sign in and view followers</p>
<% end %>
</div>
models/user.rb
class User < ApplicationRecord
def self.from_omniauth(auth_hash)
#Look up the user or create them using keys in the auth hash
user = where(provider: auth_hash.provider, uid: auth_hash.uid).first_or_create
user.update(
name: auth_hash.info.name,
profile_image: auth_hash.info.image,
twitter_user_name: auth_hash.info.nickname,
token: auth_hash.credentials.token,
secret: auth_hash.credentials.secret
)
user
end
# token and secret is what came back from omniauth and this was saved to the user database.
end
application_helper.rb
module ApplicationHelper
def parsed_tweet(tweet)
_parsed_tweet = tweet.text.dup
tweet.urls.each do |entity|
html_link = link_to(entity.display_url.to_s, entity.expanded_url.to_s, target: 'blank')
_parsed_tweet.sub!(entity.url.to_s, html_link)
end
tweet.media.each do |entity|
html_link = link_to(entity.display_url.to_s, entity.expanded_url.to_s, target: 'blank')
_parsed_tweet.sub!(entity.url.to_s, html_link)
end
_parsed_tweet.html_safe
end
end
There is your problem, incorrect caching.
<% cache('followers', expires_in: 6.hours) do %>
<li><%= follower.name %></li>
<hr>
<% end %>
When cache is empty, you don't find anything by key "followers". You take first follower and cache it with that key. And by the time you display the second follower, there is a usable cache entry already, so you use the cache, not second follower's data.
Same problem with your other blocks. I think you meant to cache entire loops, not individual elements.
For some reason, the app works perfectly locally
Because locally you have :null cache_store, I think.
I've scoured the internet for an answer and found nothing... this is driving me insane!
No assert_select statements are working in any of my tests. I've repeatedly confirmed that the element is actually in the dom on the targeted page — and it is — but every test fails on an assert_select statement. Even one as general as assert_select 'body'!
Here's one test:
require 'test_helper'
class UsersIndexTest < ActionDispatch::IntegrationTest
def setup
#user = users(:matt)
end
test "index including pagination" do
log_in_as(#user)
get users_path
assert_template 'users/index'
assert_select 'div.pagination'
User.paginate(page: 1).each do |user|
assert_select 'a[href=?]', user_path(user), text: user.first_name
end
end
end
Here's users/index.html.haml
%h1 All Users
= link_to 'New User', new_user_path
= will_paginate
%table
%thead
%tr
%th
%th First name
%th Last name
%th Email
%th
%th
%th
%tbody
- #users.each do |user|
%tr
%td= gravatar_for(user)
%td= user.first_name
%td= user.last_name
%td= user.email
%td= link_to 'Show', user
%td= link_to 'Edit', edit_user_path(user)
%td= link_to 'Destroy', user, :method => :delete, :data => { :confirm => 'Are you sure?' }
= will_paginate
Pretty boring stuff, right? And yet, the test fails:
FAIL["test_index_including_pagination", UsersIndexTest, 0.9574]
test_index_including_pagination#UsersIndexTest (0.96s)
Expected at least 1 element matching "div.pagination", found 0..
Expected 0 to be >= 1.
test/integration/users_index_test.rb:12:in `block in <class:UsersIndexTest>'
Even when I change the assertion to assert_select div, it fails. And, again, I can confirm that the div is present when I visit the index page.
What am I missing here!?!?!?!
If it helps, here's my gemfile:
source 'https://rubygems.org'
gem 'rails', '4.2.0'
gem 'pg'
gem 'puma'
gem 'turbolinks'
gem 'jquery-rails'
gem 'bcrypt', '~> 3.1.7'
gem 'faker', '~> 1.4.2'
gem 'sass-rails', '~> 5.0.1'
gem 'bootstrap-sass', '~> 3.2.0'
gem 'will_paginate', '~>3.0.7'
gem 'bootstrap-will_paginate','~>0.0.10'
gem 'uglifier', '>= 2.5.0'
gem 'haml-rails', '~> 0.8'
gem 'jbuilder', '~> 2.2.3'
gem 'sdoc', '~> 0.4.0', group: :doc
gem 'rest-client', '~> 1.7.3'
gem 'bourbon'
group :development, :test do
gem 'byebug'
gem 'web-console', '~> 2.0.0'
gem 'spring'
gem 'better_errors'
end
group :test do
gem 'minitest-reporters', '~> 1.0.5'
gem 'mini_backtrace', '~> 0.1.3'
gem 'guard-minitest', '~> 2.3.1'
end
group :production do
gem 'rails_12factor'
end
ruby '2.2.0'
Thanks to Steve Klein for the suggestion of printing out the response body. Unfortunately, the plot only thickens. The body clearly has the tag I'm targeting!
Added a line to the above test
assert_template 'users/index'
puts #response.body
assert_select 'div.pagination'
And the output has the tag!
← Previous 1 2 Next →
And yet still fails!!!
FAIL["test_index_as_admin_including_pagination_and_delete_links", UsersIndexTest, 1.412393] test_index_as_admin_including_pagination_and_delete_links#UsersIndexTest (1.41s)
Expected at least 1 element matching "div.pagination", found 0..
Expected 0 to be >= 1.
test/integration/users_index_test.rb:15:in `block in <class:UsersIndexTest>'
Make sure you are loading enough test data to trigger pagination. This selector won't be on your page unless pagination kicks in (depends on how you have configured will_paginate in your controller action).
It might be that the problem lies in line 13: User.paginate(page: 1).each do |user|. Try commenting the loop or cutting it out and run the test again. If it succeeds now, it could be that you have changed the default pagination method in your /users_controller.rb file. Try matching your custom pagination method with the one in your integration test. Something like the following for example: User.paginate(page: 1, per_page: 10).each do |user|
I had same problem with assert_select 'div.pagination', so I cought this thread googling the error.
I read the thread and got back to my app.
I tried to test:
assert_select 'div'
which passed.
I then switched back to:
assert_select 'div.pagination'
and test passed as well :O
For your reference, this is my users_index_test.rb
require 'test_helper'
class UsersIndexTest < ActionDispatch::IntegrationTest
def setup
#user = users(:archer)
end
test "index including pagination" do
log_in_as(#user)
get users_path
assert_template 'users/index'
assert_select 'div.pagination'
User.paginate(page: 1).each do |user|
assert_select 'a[href=?]', user_path(user), text: user.name
end
end
end
and this is my fixture users.yml
michael:
name: Michael Example
email: michael#example.com
password_digest: <%= User.digest('password') %>
archer:
name: Sterling Archer
email: duchess#example.gov
password_digest: <%= User.digest('password') %>
lana:
name: Lana Kane
email: hands#example.gov
password_digest: <%= User.digest('password') %>
mallory:
name: Mallory Archer
email: boss#example.gov
password_digest: <%= User.digest('password') %>
<% 30.times do |n| %>
user_<%= n %>:
name: <%= "User #{n}" %>
email: <%= "user-#{n}#example.com" %>
password_digest: <%= User.digest('password') %>
<% end %>
I really don't know why now it pass, but I wanted to contribute in the research of a more logical solution.
Double check your fixture file for typos and make sure that you are indeed loading enough comments to trigger inclusion of a pagination.
I had the same problem as you, originating from chapter 13 of the Ruby on Rails Tutorial. I included 'puts response.body' in my test and discovered that the ERb comments that I attempted to generate in my "comments.yml" were not being generated during the test. The issue turned out to be that I forgot a single '=' sign in an ERb tag. Hopefully for you the solution is equally simple!
For whoever runs into this problem in the future, knowing fully well you tried all of the solutions above and nothing changed.
Pay attention to this line in the users.yml file
Wrong:
<% 30.times do |n| %>
user_<%= n %>:
name: <%= "User #{n}" %>
email: <%= "user-#{n}#example.com" %>
password_digest: <%= User.digest('password') %>
<% end %>
Wrong:
<% 30.times do |n| %>
user_<%= n %>:
name: <%= "User #{n}" %>
email: <%= "user-#{n}#example.com" %>
password_digest: <%= User.digest('password') %>
<% end %>
Correct:
<% 30.times do |n| %>
user_<%= n %>:
name: <%= "User #{n}" %>
email: <%= "user-#{n}#example.com" %>
password_digest: <%= User.digest('password') %>
<% end %>
I am experimenting with nested resources:
My routes:
resources :conversations do
resources :replies do
resources :comments
end
end
I was able to get the form for replies to work with the conversation, but now I'm adding the additional complexity of getting comments to work with replies.
The entirety of the forms are all under the conversation show path.
<%= form_for([#conversation, #reply]) do |f| %>
<%= render 'shared/response_form', f: f %>
<%= f.submit "Reply", class: "btn btn-large btn-primary" %>
<% end %>
The above form for replies works fine and gets no errors, the below form for comments gets an error:
undefined method `reply_comments_path'
<%= form_for([#reply, #comment]) do |f| %>
<%= render 'shared/response_form', f: f %>
<%= f.submit "Comment", class: "btn btn-large btn-primary" %>
<% end %>
Here is my conversations controller for show, this is where I think the problem is:
def show
#conversation = Conversation.find(params[:id])
#replies = #conversation.replies
#reply = current_user.replies.build
#If I change the above line to #conversations.replies.build
#it breaks the ability to show replies above the form.
#comments = #reply.comments
#comment = #reply.comments.build
end
However, someone else suggested doing this:
<%= form_for([#conversation, #reply, #comment]) do |f| %>
<%= render 'shared/response_form', f: f %>
<%= f.submit "Comment", class: "btn btn-large btn-primary" %>
<% end %>
But it only ended up with a routing error:
No route matches {:controller=>"comments", :format=>nil, :conversation_id=>#<Conversation id: 3, content: "Goes here.", user_id: 1, created_at: "2012-12-10 21:20:01", updated_at: "2012-12-10 21:20:01", subject: "Another conversation">, :reply_id=>#<Reply id: nil, content: nil, user_id: 1, created_at: nil, updated_at: nil, conversation_id: nil>}
I always get this undefined method path error when I try making new forms and I always manage to forget what I did wrong. The answer never seems to be the routes.
EDIT:
Under the create section in the controller I have:
#replies = #conversation.replies
#reply = current_user.replies.build
#If I change the above line to #conversations.replies.build
#it breaks the ability to show replies above the form.
I have no idea why #reply = #conversation.replies.build breaks the ability to show the existing replies. I get an error saying it can't convert nil to a number, and can't see the reply.created_at or reply.content. Whatever is causing that may be a clue as to why I'm having this problem. However, in the replies controller I AM using
#reply = conversation.replies.build(content: params[:reply][:content], user_id: current_user.id)
EDIT:
Just to add, Stackoverflow does something very similar to what I'm trying to achieve here, except that you can comment on the questions as well as the answers.
Look at the end of your error:
... :reply_id=>#<Reply id: nil, content: nil, user_id: 1, created_at: nil, updated_at: nil, conversation_id: nil>}
You can't create a form for #comment if #reply is not saved. You need to persist #reply before create a #comment to it.
If you haven't validates on Reply model try this simple test on show action:
# #reply = current_user.replies.build
#reply = current_user.replies.create
See comments for answer.