How to use activemodel to validates date_time_select - ruby-on-rails-4

I am using rails 4.0
I wonder how to validate date_select with activemodel
let's suppose I have the code as follow
app/models/book.rb
class Book
include ActiveModel::Model
include ActiveModel::Validations
attr_accessor :title, :written_on
validates :title, presence: true, allow_blank: false
# How validates :written_on if I use date_select Please look in my view below
end
app/controllers/books.rb
class BooksController < ApplicationController
#...
def new
#book = Book.new
end
def create
#book = Book.new(book_params)
if #book.valid?
#Do something
end
end
#...
end
app/views/books/new.html.erb
<% form_for #book do |f| %>
...
<%= f.date_select :written_on %>
...
<% end %>
I have also try adding
attr_accessor 'written_on(1i)'
to my book model but I got the error invalid attribute name 'written_on(1i)'
Really appreciated for the help here.

Just to clarify, I think you're asking why you're not even able to set the written_on attribute, let alone validate it-- when I used your exact code locally and tried to create a new book, on submit I got undefined method `written_on(1i)=' for Book.
This is because the Book model isn't inheriting from ActiveRecord::Base; you're just including ActiveModel::Model and ActiveModel::Validations. The Rails guide on form helpers says "when Active Record sees parameters with such names it knows they must be combined with the other parameters and given to a constructor appropriate to the column type."
So I started looking through the Rails source to see where this functionality was implemented, and it's currently in ActiveRecord::AttributeAssignment. There is currently an open pull request that moves this functionality to ActiveModel so that in cases like yours, you'd be able to use it by including ActiveModel::AttributeAssignment.
I'm not sure what you can do until that gets merged in and released. I tried including ActiveRecord::AttributeAssignment and still got the same error, and looking at the pull request, it doesn't seem to be that straightforward. You could fork Rails and apply that pull request, but you'd have to maintain your own Rails for a while until that lands, then get back on a released version.

Related

Can't get sabisu gem to render - shows no input found for inet error

so i'm working through the api on rails tutorial - http://apionrails.icalialabs.com/book - and i keep getting the error 'no input found for inet' in my error window.
the error highlights this block of code as where the issue is occuring:
<div class="appeareable">
<% #explorer.resource_columns.each do |column| %>
<%= f.input column, input_html: {name: "#{#explorer.resource_name}[#{column}]" }, as: #explorer.column_type(column), required: #explorer.required_attribute?(column) %>
<% end %>
</div>
I tried locking out the compass and simple_form gems, but there are dependencies that start to fall apart using rails 4.1.4 and ruby 2.1.5.
it looks like simple_form is trying to render a resource named 'inet', but i can't find that anywhere in the gem code or even referenced anywhere on google.
It turns out that simple_form has a problem handling the 'inet' datatype now included in rails 4 by default for postgres - https://blog.engineyard.com/2013/new-in-rails-4 (ctrl-f for inet).
IPs used to be string datatype (varchar 255 in postgres) and so converting the db to string for the 2 IP fields in the user table (current_sign_in_ip and last_sign_in_ip) resolves this issue.
I would imagine simple_form will be updating to handle this new datatype at somepoint...though I didn't see any mention of it in their issue logs.
I did this by adding a new migration:
rails g migration change_ip_columns_in_users_table
Then I edited the migration file:
class ChangeIpColumnsInUsersTable < ActiveRecord::Migration
def change
change_column :users, :current_sign_in_ip, :string
change_column :users, :last_sign_in_ip, :string
end
end
The migration solved the problem.

url_for in an email sent by a rake task in rails 4

I have a rake task that sends out daily digest emails of player activity during a day. (See example code below.) If I run PlayerActivityMailer.activity_report.deliver in my console, everything works just fine. However, when I try to invoke the rake task, I get the following error:
rake aborted!
ActionView::Template::Error: arguments passed to url_for can't be handled.
Please require routes or provide your own implementation
After doing some research, I found that in Rails 4, they totally nerfed ActionView::Helpers::UrlHelper.url_for (http://apidock.com/rails/v4.1.8/ActionView/Helpers/UrlHelper/url_for - notice the giant red minus sign under the 4.0.2). If you look at the source, you can see the error I'm seeing - it no longer takes options. As far as I can tell, that functionality still exists in other url_fors, such as the one in ActionDispatch::Routing::UrlFor. Also, the error message suggests including Rails.application.routes.url_helpers.
What I've tried
include ActionDispatch::Routing::UrlFor in both the rake task (inside the task) and the mailer (both at the same time, and each separately)
include Rails.application.routes.url_helpers in the same places and configurations, both with and without the UrlFor include.
The error still persists. My guess is that the page view is still insisting on using the ActionView::Helpers::UrlHelper version of url_for. I don't think I can include things actually in the views (which is sloppy looking and hacky even if I could).
Example Code
(heavily sanitized)
config/environtments/development.rb:
config.action_mailer.default_url_options = { host: 'localhost:3000' }
lib/tasks/player.rake:
namespace :player do
task :activity => :environment do
PlayerActivityMailer.activity_report.deliver
end
end
app/mailers/player_activity_mailer.rb:
class PlayerActivityMailer < ActionMailer::Base
def activity_report
#activities = PlayerActivity.all
mail(to: 'foo#bar.com', subject: 'activity report')
end
end
app/views/player_activity_mailer/activity_report.html.erb:
<% #activites.each do |activity| %>
Player: <%= link_to activity.player.name, player_url(id: activity.player.id) %>
...
<% end %>
I also have a model Player, resources :players in my routes.rb file, and a PlayerActivity class with an association to Player.
I'm currently using the (really horrifying) workaround of #base_url = Rails.configuration.action_mailer.default_url_options[:host] in my mailer action and "http://#{#base_url}/players/#{activity.player.id}" in my view instead of the player_url part.
Help!
Have you tried passing just your player in the URL? Like this:
<% #activites.each do |activity| %>
Player: <%= link_to activity.player.name, player_url(activity.player) %>
<% end %>

How do I make a method available inside a partial?

I'm a rails beginner learning rails 4 and I'm trying to learn by doing. I'm making a simple blog that I want some simple user authentication on. I'm trying to learn here, so I don't want to implement Devise, etc. I have a header partial that takes care of my site header and I'm trying to put a link to logout that only shows if a user is logged in. I have a simple session controller that has a new action for the signup form, a create action that sets the current user after matching the email and password and sets session[:user_id] = #current_user.id, and a destroy action that nils out the session. In my application controller I have a method like this
def logged_in?
!session[:user_id].nil?
end
In my _header.html.erb partial, I have
<% if logged_in? %>
(My link)
<% end %>
When I load the page it tells me it can't find the "logged_in?" method. Anyone know why? Thanks.
Methods on controllers are by default not exposed to the views (which your partial is part of).
2 solutions:
Create your logged_in? method as a helper method, for example in an AuthenticationHelper. Doing this you cannot access it from controllers, though.
Expose your controller method to the view using helper_method:
class ApplicationController < ActionController::Base
helper_method :logged_in?
def logged_in?
[...]
end
end
Couldn't you just use:
if #current_user

Multi select file upload field with nested attributes in Rails

Currently I have a Note model which accepts nested attributes for an Attachments model, which uses Carrierwave. When adding a Note, I have a nested form to allow attaching file to the new Note:
Nested form field:
<%= f.file_field :image, multiple: true, name: "attachment[file]" %>
I am using the Cocoon gem to add the nested field. While I can easily let them add multiple file upload fields with Cocoon, and add multiple attachments that way, I only want to load one file upload field, and let them use multi select to select multiple images.
When I do this, the file upload field says '2 Images' next to it. However, upon form submission, only one file is listed under 'attachments_attributes'. I need all of the attachments to submit at once as the Note has not yet been saved.
What is the proper way to accomplish this? I am aware of the Railscast on this topic however it did not seem to address my particular scenario.
Any help is appreciated.
Just append [] to your params
<%= f.file_field :image, multiple: true, name: "attachment[file][]" %>

rails3-jquery-autocomplete foreign key

Hi I need help with setting up the rails3-jquery-autocomplete gem with a manually assigned foreign key in my database.
Here is what my models look like
class User < ActiveRecord::Base
has_many :reservations, :foreign_key => 'reserver_id'
attr_accessible :login, :first_name, :last_name
end
class Reservation < ActiveRecord::Base
belongs_to :reserver, :class_name => 'User'
attr_accessible :reserver, :reserver_id, :reserver_login
end
The users table in my database has all of the columns
The Reservations Controller has
autocomplete :users, :login
Routes.rb has
resources :reservations do
get :autocomplete_users_login, :on => :collection
end
And in the reservations view I have this
<%= f.autocomplete_field :reserver_id, autocomplete_users_login_reservations_path %>
Now when I try and test it I see that the calls are being made in my javascript console but I get the error 500. For example I tried searching for xno which is in a login column of my users database.
GET http://0.0.0.0:3000/reservations/autocomplete_users_login?term=xno 500 (Internal Server Error) jquery.js:8241
jQuery.ajaxTransport.send jquery.js:8241
jQuery.extend.ajax jquery.js:7720
jQuery.each.jQuery.(anonymous function) jquery.js:7246
jQuery.extend.getJSON jquery.js:7263
a.railsAutocomplete.fn.extend.init.a.autocomplete.source autocomplete-rails.js:17
$.widget._search jquery-ui.js:6547
$.widget.search jquery-ui.js:6540
(anonymous function) jquery-ui.js:6335
Does this have anything to do with the fact that I am using foreign key in my database? If yes how should I structure my routing. I was following the gem documentation and tried to set it up so that I can look up the users table and list people by the login column of the users table, but so that the id gets returned and stored as :reserver_id once the user is selected. Previous code that worked with select field was
<%= f.select :reserver_id, User.select_options, :prompt => true %>
where select_options method creates an array of login strings and id pairs in individual arrays.
I know that the solution is probably really easy, thank you for your help...
My problem was silly but it turned out it had nothing to do with the fact that the category table used a custom foreign key. My first problem was using plural version of the table name rather than the singular. Once I changed all references to users to user I noticed that javascript console wasn't throwing any exceptions at me so I figured that I had either broken everything and the call wasn't being made or it was going through and it wasn't rendering properly.
The presence of proper MYSQL calls in the console confirmed my suspicion. That's when I saw that the list was rendering way off to the right of my page probably due to strange styling happening somewhere else.
Bottom line is having a custom foreign key doesn't change usage of the gem at all. THe original table name should be used.