Ruby on Rails getting wrong number of arguments (1 for 0) - ruby-on-rails

I'm using similar code to Railscast 213 to display a calendar with records.
The do line is causing a "getting wrong number of arguments (1 for 0):
<%= calendar #date do |date| %>
<%= date.day %>
<% if #wolabors_by_date[date] %>
<ul>
<% #wolabors_by_date[date].each do |wolabor| %>
<li><%= link_to wolabor.name, wolabor %></li>
<% end %>
</ul>
<% end %>
<% end %>
The calendar_helper.rb starts out with:
module CalendarHelper
def calendar(date = Date.today, &block)
Calendar.new(self, date, block).table
end
wolabors_controller.rb has
class WolaborsController < ApplicationController
def index
#wolabors = Wolabor.all
#wolabors_by_date = #wolabors.group_by(&:date)
#date = params[:date] ? Date.parse(params[:date]) : Date.today
end`

I think that first line is supposed to be
<% calendar_for #date do |date| %>
That railscast has been revised and it does not use that table_builder plugin in the new version.
http://railscasts.com/episodes/213-calendars-revised

I've found in the discussion about this Railscast , that the statement :
first = date.beginning_of_month.beginning_of_week(START_DAY)
gives the same arguments error . It seems methods
beginning_of_month
and
beginning_of_week
are Rails 3.2 specific and if you are on lower version , you should upgrade.

Related

Ruby on rails create a new variable to make an each

i'm new into ruby on rails and i want to assign a variable to make an each like this
<% 3.times do |calendar| %>
<% test = #lessons_calendar %>
<% test.each do |lesson| %>
display html here
<% end %>
<% end %>
The thing is that in my controller i have assigned 3 variables like this #lessons_1 #lessons_2 and #lessons_3 but when i run the code it says undefined method `each' for nil:NilClass, how can i join the number created by calendar to the new variable ? Thanks
Instead of below
<% 3.times do |calendar| %>
<% test = #lessons_calendar %>
<% test.each do |lesson| %>
display html here
<% end %>
<% end %>
Make changes in your controller as well as in view as below
Controller Code
# take new variable
#lessons = []
#lessons << #lessons_1
#lessons << #lessons_2
#lessons << #lessons_3
Now do code in view file as below
<% #lessons.each do |lesson| %>
<% lesson.each do |ls| %>
your code here
<%end%>
<%end%>
Hope this will help you.
<% 3.times do |calender| %>
<%= #lessons_calendar.collect{ |lesson| Write Your Code Here }.join("").html_safe rescue 'No Record' %>
<% end %>
With in the collect iterator you can assign it to instance var if you want to. Thanks

How to implement archives in blog with ruby and sinatra?

I'm doing archives for my blog ,actually I'm moving from rails to sinatra because of the requirements.I'm trying the same for Sinatra
In my app.rb:
def index
#posts = Post.all(:select => "title, id, created_at", :order => "created_at DESC")
#post_months = #posts.group_by { |t| t.created_at.beginning_of_month }
end
and in Layout.erb :
<div class="archives">
<h2>Blog Archive</h2>
<% #post_months.sort.reverse.each do |month, posts| %>
<h3><%=h month.strftime("%B %Y") %></h3>
<ul>
<% for post in posts %>
<li><%=h link_to post.title, post_path(post) %></li>
<% end %>
</ul>
<% end %>
Can anyone please help me how to do it for sinatra? I'm trying the same code and I'm getting this :undefined method `sort' for nil:NilClass
You are not using Sinatra's notation for defining actions. Instead of:
def index
# your code...
end
You need to define actions like so:
get '/' do
# your code...
end
You should probably read this before continuing: http://www.sinatrarb.com/intro.html

how to group_by day in rails

Hello I'm trying to make grouping news by date. I can't understand what is the problem?
feed_entries_controller.rb
def index
#feed_entries = FeedEntry.page(params[:page]).per_page(12).where('published_at < ?', DateTime.now)
#feed_entries_by_day = #feed_entries.group_by { |t| t.published_at.beginning_of_day }
end
index.html.erb
<% #feed_entries_by_day.each do |day, feed_entries| %>
<h3><%= h day.strftime("%d %B %Y") %></h3>
<%= render #feed_entries%>
<% end %>
Without seeing the data, I suspect our problem is the published_at column also contains time and we're just interested in the date part for the purposes of querying and grouping, and we need to reference the grouped data in the view..
If that's the case, we can amend our .where() clause like so:
feed_entries_controller.rb
def index
feed_entries = FeedEntry
.page(params[:page])
.per_page(12)
.where('published_at::date <= ?', Date.current)
#feed_entries_by_day = feed_entries.group_by { |t| t.published_at.to_date }
end
And in our view, we need to pick a different name to iterate through our grouped feed_entries (I've chosen entry)
index.html.erb
<% #feed_entries_by_day.each do |day, entry| %>
<h3><%= h day.strftime("%d %B %Y") %></h3>
<%= render entry%>
<% end %>

Rails: capture method

The following code is from a Ryan Bates' RailsCasts in which he turns the front page of a blog into a calendar, so that articles show up as links on days. The following helper module creates the Calendar. I have two questions about this code
In the day_cell method, he uses a method called capture. I found some docs on it but I still can't figure out how capture is working in this context. Also, what is the &callback that's passed as an argument to capture? Would it be the same :callback that's passed to Struct.new? If so, how does it get into capture? What is the :callback that's passed to Struct?
def day_cell(day)
content_tag :td, view.capture(day, &callback), class: day_classes(day)
end
source code
module CalendarHelper
def calendar(date = Date.today, &block)
binding.pry
Calendar.new(self, date, block).table
end
class Calendar < Struct.new(:view, :date, :callback)
HEADER = %w[Sunday Monday Tuesday Wednesday Thursday Friday Saturday]
START_DAY = :sunday
delegate :content_tag, to: :view
def table
content_tag :table, class: "calendar" do
header + week_rows
end
end
def header
content_tag :tr do
HEADER.map { |day| content_tag :th, day }.join.html_safe
end
end
def week_rows
weeks.map do |week|
content_tag :tr do
week.map { |day| day_cell(day) }.join.html_safe
end
end.join.html_safe
end
def day_cell(day)
content_tag :td, view.capture(day, &callback), class: day_classes(day)
end
def day_classes(day)
classes = []
classes << "today" if day == Date.today
classes << "notmonth" if day.month != date.month
classes.empty? ? nil : classes.join(" ")
end
def weeks
first = date.beginning_of_month.beginning_of_week(START_DAY)
last = date.end_of_month.end_of_week(START_DAY)
(first..last).to_a.in_groups_of(7)
end
end
end
I have done my research, and I've finally unraveled the mystery.
So, a couple of things to start with; as usual the documentation isn't very clear,
the capture(*args) method is supposed to grab a piece of template into a variable, but it doesn't dig deeper into explaining that you may pass variables to the grabbed piece of template, that of course comes in the form of a block
source code from Ryan Bate's Calendar Screen-cast:
<div id="articles">
<h2 id="month">
<%= link_to "<", date: #date.prev_month %>
<%= #date.strftime("%B %Y") %>
<%= link_to ">", date: #date.next_month %>
</h2>
<%= calendar #date do |date| %>
<%= date.day %>
<% if #articles_by_date[date] %>
<ul>
<% #articles_by_date[date].each do |article| %>
<li><%= link_to article.name, article %></li>
<% end %>
</ul>
<% end %>
<% end %>
</div>
In the code above, the block would be exclusively this part:
do |date| %>
<%= date.day %>
<% if #articles_by_date[date] %>
<ul>
<% #articles_by_date[date].each do |article| %>
<li><%= link_to article.name, article %></li>
<% end %>
</ul>
<% end %>
<% end %>
So, When he makes this call:
content_tag :td, view.capture(day, &callback), class: day_classes(day)
particularly:
view.capture(day, &callback)
What's happening here is that he's passing the day argument to the Block above as the |date| parameter (in the block).
What needs to be understood here, is that in the context of the Problem (making a 30-day Calendar); each day of the Month is passed to the capture method, along with the piece of template (&callback), doing so.. in consequence renders the block above for each day of a Given Month. The final step, of course is.. Placing that rendered content (for each day) as the content for the content_tag :td
A final note; Ryan is calling the capture method on a view variable, it isn't stated in the documentation either, but he does mention during the ScreenCast that he needs this view as a "proxy" to access the view, and of course the view is the only one that has access to ViewHelper methods.
So, in summary, it's very beautiful code, but it's only beautiful once you understand what it does, So, I agree is very confusing at first sight.
Hope this helps, it's the best explanation I could come up with. :)

Refactoring code out of the view

I have the following view code which displays events, along with headers informing the user if the following events occured today, yesterday, or in the past week.
It all works fine, but I would prefer to refactor it out of the view, I can't put it in a helper because it needs to maintain the variables state between loop iterations. Any idea how to tidy this up? thanks
<% displayed_week_already = false %>
<% displayed_yesterday_already = false %>
<% displayed_today_already = false %>
<% #events.each do |event| %>
<%= event.title &>
<% if (Time.now - 1.week) > event.created_at && !displayed_week_already %>
<% displayed_week_already = true %>
Events in past week
<% elsif (Time.now - 1.day) > event.created_at && (Time.now - 2.day) < event.created_at && !displayed_yesterday_already %>
<% displayed_yesterday_already = true %>
Events yesterday
<% elsif (Time.now - 1.day) < event.created_at && !displayed_today_already %>
<% displayed_today_already = true %>
Events in past day
<% end %>
<% end %>
Expected output would be:
Events in past day
John created a new artice
Dan commented on article 1
Sue deleted article 2
Events yesterday
Sue created a new article
Events in past week
Carol was promoted
Dan cerated a new article
I might do something like the following. I am leaving out the implemented methods defined on the model itself.
existing view
<%= render "events", :title => "Events in past day", :events => from_today(#events) %>
<%= render "events", :title => "Events yesterday", :events => from_yesterday(#events) %>
<%= render "events", :title => "Events in past week", :events => from_this_week(#events) %>
_events.html.erb
<% if events.present? %>
<%= title %>
<% events.each do |event| %>
<%= event.title %>
<% end %>
<% end %>
app/helpers/event_display_helper.rb
module EventDisplayHelper
def from_today(events)
events.select{|x| x.happened_today?}
end
def from_yesterday(events)
events.select{|x| x.happened_yesterday?}
end
def from_this_week(events)
events.select{|x| x.happened_this_week_before_yesterday?}
end
end
You could easily do this in the model, with named scopes (I'm assuming Rails 3 because that's what I know best). You'll need to define them yourself but they're pretty simple.
#last_week = #event.last_week
#yesterday = #event.yesterday
#today = #event.today
Then just iterate over each of the groups in your view. Should make it a lot cleaner and you won't need so much logic, as it's where it actually belongs.

Resources