I saw some similar questions but didn't success with this.
I want to display the 3 latest posts on my homepage.
I define this method on my PostsController
def noticia
#posts = Posts.all(:limit => 3)
end
helper_method :noticia
and I invoke this on my view
- if #noticia
%h4.feed
A Sair
%h6
%span= #noticia.created_at.strftime("%d %b. %Y")
= link_to #noticia.content, posts_path
%p
- if current_admin
= link_to "Adicionar notícia", new_post_path
It gives NoMethodError
undefined method `each' for #<Post:0x00000102fb6fc8>
There is a lot of strange things in your code.
Your noticia method should be :
def noticia
#posts = Post.order("created_at desc").limit(3)
end
You don't need to use helper_method.
And your view file must be something like :
- if #posts.any?
- #posts.each do |post|
= # do something with my post
Hope it helps!
#posts = Post.order('created_at').limit(3)
#posts = Post.order('created_at DESC').limit(3)
#posts = Post.order('created_at ASC').limit(3)
Is your model 'Post' (not Posts)?
This is how you'd use limit with ActiveRecord.
def noticia
#posts = Post.limit(3)
end
Related
I'm very beginner in RoR and even in web-programming. So I guess my question is so easy for many developers!
I'm implementing simple weeks calendar, it should have day's names and two "buttons" - 'next week' and 'previous week'. That's all for beginning!
I have controller with index action:
def index
#today = Date::today
#monday = #today.beginning_of_week
#sunday = #today.end_of_week
#currentweek = #monday..#sunday
end
and two other actions:
def go_next_week
#monday = #sunday + 1
#sunday = #monday.end_of_week
end
def go_prev_week
#sunday = #monday - 1
#monday = #sunday.beginning_of_week
end
index view code:
<div class="wrapper">
<table class="data">
<thead>
<tr class="month-names">
<td><%= form_tag(work_days_go_prev_week_path, method: "get") do %>
<%= submit_tag(l(("workdays_show_prev" + period).to_sym)) %>
<% end %>
</td>
<td><%= render :partial => 'days_names_header' %></td>
<td><%= form_tag(work_days_go_next_week_path, method: "get") do %>
<%= submit_tag(l(("workdays_show_next" + period).to_sym)) %>
<% end %>
</td>
</tr>
</thead>
</table>
</div>
And the routes file:
RedmineApp::Application.routes.draw do
match 'work_days/go_next_week' ,:to => 'work_days#go_next_week', via: [:get]
match 'work_days/go_prev_week' ,:to => 'work_days#go_prev_week', via: [:get]
match 'work_days/(:action(/:id))',via: [:get], :controller => 'work_days'
end
The main goal on that stage in short terms is:
Controller has a Date variables 'monday','sunday' and Range
'currentweek'
Index view shows table of days according that variables
Index view has 2 "buttons": 'next week' and 'previous week'
Clicking on this buttons should change Controller's variables
Index view should "refresh" with changed Controller's variables
This code isn't working. I got such error in log when clicking on 'Previous month' button:
Started GET
"/work_days/go_prev_week?tf8=%E2%9C%93&commit=Previous+week" for
127.0.0.1 at 2015-12-09 14:00:27 +0600 Processing by WorkDaysController#go_prev_week as HTML Parameters:
{"utf8"=>"✓","commit"=>"Previous week"} Current user: admin (id=1)
Completed 500 Internal Server Error in 3ms (ActiveRecord: 0.2ms)
NoMethodError (undefined method `-' for nil:NilClass)
I'm very beginner in RoR and even in web-programming.
Welcome!
Your problem is that you're populating your controller action with #instance_variables which are reliant on each other:
def go_next_week
#monday = #sunday + 1 # needs #sunday
#sunday = #monday.end_of_week # needs #monday
end
In old school programming, that would have probably lead to an unrecognized reference error or perhaps a stack overflow error, typically due to infinite recursion.
The error confirms this:
undefined method `-' for nil:NilClass
Ruby is different than most other languages in that it assigns undeclared variables to the NilClass object. This makes it very difficult for developers to determine the error - basically if you receive undefined method for NilClass, it's that you've not declared your variable.
--
The fix would be to get the data you're trying to manipulate into the instance of the class. This can be achieved with a before_action filter:
#app/controllers/work_days_controller.rb
class WorkDaysController < ApplicationController
before_action :set_dates
def index
##today, #monday, #sunday will be available in here.
end
private
def set_dates
#today = Date::today
#monday = #today.beginning_of_week
#sunday = #today.end_of_week
end
end
You could also improve your routes to make use of the resources directive:
#config/routes.rb
resources :work_days do
get :go_next_week, on: :collection
get :go_prev_week, on: :collection
end
It look like that you want to have the same controller action and view but only with other dates.
If that's the case I would recommend you something like this:
class MyController < ApplicationController
before_action :set_date
def index
end
private
def set_date
if params[:week].present? && params[:year].present?
#today = Date.commercial(params[:year].to_i, params[:week].to_i)
end
#today ||= Date::today # <= Just use date today if it's not set already
#monday = #today.beginning_of_week
#sunday = #monday - 1
#monday = #sunday.beginning_of_week
end
end
The routes:
RedmineApp::Application.routes.draw do
get 'calendar' => 'my_controller#index', as: :index_action
end
Then you can add next/previous links to your view like this:
<%= link_to "Next", index_action_path(year: #today.year, week: #today.cweek + 1) %>
<%= link_to "Previous", index_action_path(year: #today.year, week: #today.cweek - 1) %>
I haven't tested this implementation yet but it should work. You should add tests anyway.
But you should definitively check the parameters if they are correct. For example if they are in the range of 1 to 52 for week and so on. Otherwise it will raise an exception if the week is out of range.
Try also to not put logic into the view but in helper methods.
I hope this helps and happy coding. :)
You should probably initialize these instance variables in a before_action.
So for example:
class MyController < ActionController
before_action :set_dates
def index
# ... Your index implementation
end
def go_next_week
#monday = #sunday + 1
#sunday = #monday.end_of_week
end
def go_prev_week
#sunday = #monday - 1
#monday = #sunday.beginning_of_week
end
private
def set_dates
#today = Date::today
#monday = #today.beginning_of_week
#sunday = #today.end_of_week
#currentweek = #monday..#sunday
end
end
In this way the dates will be initialized in every single action. But be careful! This this implementation above just allows to go one week back of further. To make this work with every week you have to provide a param with the current week for example.
I hope this helps and if you need more information you are welcome. :)
You are using #monday in the action go_prev_week,you are not calculating #monday inside the method,#monday is an instance variable its by default value is nil.
You have two way to resolve this issue -
First -
def go_prev_week
index
#sunday = #monday - 1
#monday = #sunday.beginning_of_week
end
Second - calculate #monday
def go_prev_week
#today = Date::today
#monday = #today.beginning_of_week
#sunday = #monday - 1
#monday = #sunday.beginning_of_week
end
You have to do same thing in the action go_next_week
I am using kaminari library, and I want to display users' pictures.
In my UserController, I put
def index
#users = User.order(:name).page params[:page]
end
Before, I was accessing the pictures like
#users.transitions-enabled
- #users.each do |user|
- user.pictures.each do |pic|
.box.panel.panel-default
= link_to (image_tag(pic.image.url(:origin))), user
I am now wondering how I can display images by using the following command:
<%= paginate #users %>
Edit:
Now I changed the code in UserController to
#users = User.all
#pictures = #users.pictures.page(params[:page]).per(2)
And it is giving me the error
undefined method `total_pages' for nil:NilClass
I was following the answer here but I am not sure how I can apply it in my case.
I'm working on a little stock market app where the users can lookup company stock info based on the ticker symbol. After the user has posted the :symbol param in the search field, they should be redirected to the appropriate "company" page (like Wall Street Journal, Yahoo Finance, Google Finance, etc). I'm currently able to manually type in the route with the symbol and everything works good. For example, localhost:9292/company/GOOG. I'm a total noob, so any help would be greatly appreciated. Thanks!
I currently have this in my view:
<%== search_field_tag(:symbol, "Enter symbol") %>
<%== submit_tag ("Search") %>
This is in my routes:
get "/company/:symbol" => "main#company"
post "/company/:symbol" => "main#company_post"
EDIT: I'm using the MarketBeat gem to pull in the data, but I also have a Company table where I have columns symbol and name. Here is my controller:
class MainController < ApplicationController
def index
render :index and return
end
def company
#name = MarketBeat.company params["symbol"]
#symbol = MarketBeat.symbol params["symbol"]
#price = MarketBeat.last_trade_real_time params["symbol"]
#change = MarketBeat.change_and_percent_change params["symbol"]
#volume = MarketBeat.volume params["symbol"]
#days_range = MarketBeat.days_range params["symbol"]
#eps = MarketBeat.earnings_to_share params["symbol"]
#pe = MarketBeat.pe_ratio params["symbol"]
#stock_exchange = MarketBeat.stock_exchange params["symbol"]
market_cap = MarketBeat.market_capitalization params["symbol"]
# #market_cap is rounded to billions
#market_cap = market_cap.to_i / 1000
render :company and return
end
In your main#company_post method, put the following:
redirect_to "/company/#{params[:symbol]}"
So the routes should be:
get "/company/:symbol" => "main#company"
post "/company" => "main#company_post"
The controller:
def company_post
redirect_to "/company/#{params[:symbol]}"
end
The view:
<%= form_tag("/company", method: :post) do %>
<%= search_field_tag(:symbol, "Enter symbol") %>
<%= submit_tag ("Search") %>
<% end %>
At the end of your #company controller method you probably will do something like this
render "#{params[:symbol]}"
or
render partial: "#{params[:symbol]}"
along with have a template file with the same name of the company, like google.html.erb
Give it a try!
I make simple search system that looks almost like your task
Full example
routes.rb
post 'search' => 'vids#prepare_search', as: :prepare_search_vids
get 'search(/*query)' => 'vids#search', as: :search_vids
vids_controller.rb
# GET /search(/*query)
def search
#results = Title.search params[:query] if search_query?
if #results.count == 1
flash[:notice] = I18n.t 'vids.search.signle_result'
redirect_to #results[0].vid
end
#query = params[:query]
end
# POST /search
def prepare_search
query = params[:q] ? params[:q] : ''
redirect_to search_vids_path(query)
end
private
def search_query?
params[:query] and !params[:query].blank?
end
Also in your situation I recommend use asteriks instead of colon in routes http://guides.rubyonrails.org/routing.html#route-globbing-and-wildcard-segments
I searched and searched, but nothing solved my problem. Here's my controller:
def show
#topic = Topic.find(params[:id])
#topic.posts = #topic.posts.page(params[:page]).per(2) # 2 for debugging
end
That functions just fine, because the topic view is reduced to two posts. However, when I add this to show.html.erb:
<%= paginate #topic.posts %>
I'm given this error:
undefined method `current_page' for #<ActiveRecord::Relation:0x69041c9b2d58>
Try with:
def show
#topic = Topic.find(params[:id])
#posts = #topic.posts.page(params[:page]).per(2)
end
And then:
<%= paginate #posts %>
If you get pagination errors in Kaminari like
undefined method `total_pages'
or
undefined method `current_page'
it is likely because the AR scope you've passed into paginate has not had the page method called on it.
Make sure you always call page on the scopes you will be passing in to paginate!
This also holds true if you have an Array that you have decorated using Kaminari.paginate_array
Bad:
<% scope = Article.all # You forgot to call page :( %>
<%= paginate(scope) # Undefined methods... %>
Good:
<% scope = Article.all.page(params[:page]) %>
<%= paginate(scope) %>
Or with a non-AR array of your own...
Bad:
<% data = Kaminari.paginate_array(my_array) # You forgot to call page :( %>
<%= paginate(data) # Undefined methods... %>
Again, this is good:
<% data = Kaminari.paginate_array(my_array).page(params[:page]) %>
<%= paginate(data) %>
Some time ago, I had a little problem with kaminari that I solved by using different variable names for each action.
Let's say in the index action you call something like:
def index
#topic = Topic.all.page(params[:page])
end
The index view works fine with <%= paginate #topic %> however if you want to use the same variable name in any other action, it throu an error like that.
def list
# don't use #topic again. choose any other variable name here
#topic_list = Topic.where(...).page(params[:page])
end
This worked for me.
Please, give a shot.
Apologies in advance, I am a newbie trying to get my head around rails.
My View at the bottom works when I use:
def show
#posts = Post.all
end
However in my controller I now have:
def show
#posts = Post.find_by_category_id params[:id];
end
In my view I have
<%= #posts.each do |post| %>
<%= post.title %>
<% end %>
Some please explain why I get this error. What should I use. category_id is a foreign key on the Post table.
Look at http://api.rubyonrails.org/classes/ActiveRecord/FinderMethods.html#method-i-find_by
Finds the first record matching the specified conditions
find_by_ will return only one post, not a collection. So you are not able to use each.
try
def show
#posts = Post.all.find_by_category_id params[:id];
end