RoR - undefined method `merge' - ruby-on-rails

I'm studing Ruby on Rails with the "RoR Bible" by Thimothy Fisher. But one of the examples doesn't work. It's code - http://pastebin.com/gtjLsdt0
The error is: NoMethodError in Contact#new where line #4 raised:
undefined method `merge' for "first_name":String
that's my contact_controller. I'm just retyping example's code, and there weren't any words about merge
class ContactController < ApplicationController
def index
#contacts = Contact.find(:all);
end
def show
end
def new
#contact = Contact.new;
end
def create
end
def update
end
end
What is wrong??

Lol that example is completely wrong!
Instead of writing sth like this:
<%= f.text_field 'contact', 'first_name' %>
You should write
<%= f.text_field :first_name %>
Because by using f.field_type you assign the field to the :contact form which provides the f methods by iteration! Also you can write
<%= f.label :first_name, "description of first_name" %>
Instead of writing it manual!
// I loked up the book you refered it seems to be quit outdated. You may buy "The Rails 3 Way" or sth. that can hold up to the current rails version!

Related

name error uninitialized constant path in rails

I'm trying to make a form that will post to a database, I'm really struggling at the moment and i'm getting this error.
NameError in AddController#index
uninitialized constant AddController::Newevents
Could you advise what i would need to do?
Heres all the code i have
Form
<%= simple_form_for(#newevent) do |f| %>
<%= f.input :eventname, required: true %>
<%= f.input :eventdate %>
<%= f.input :eventimage %>
<%= f.button :submit %>
<% end %>
controller
class AddController < ApplicationController
def index
#newevent = Newevent.new
end
end
Model
class Newevent < ActiveRecord::Base
def event_params
params.require(:Newevent).permit(:eventname, :eventdate, :eventimage)
end
end
Routes
resources :add
Edit
i now have this error undefined methodnewevents_path'` after changing this
#newevents = Newevent.new
It seems that you miscopied your code here. The error message indicates that your index method actually looks like this
def index
#newevent = Newevents.new
end
Remove the s from the end of Newevent and it should work.
RE: your edit
Your routes declare that you have a resource named add, if you want to show and create your Newevent objects, then you should create a controller for that. Declare resources :newevents in your routes and create a controller to handle it.
You should research RESTful routes, because that's what Rails's resource routing works best with. The form to create a new object should be displayed by the new action and not index.
You should be using create method instead of index if you are using POST http method. index will be called if you are using GET method and it shouldn't be used to post the form data. Refer this link for more information on rails routing.
class AddController < ApplicationController
def create
#newevent = Newevent.new
end
end

Search after multiple parameters, Ruby on Rails

I'm very new to Ruby on Rails and trying to create a search function that allows the user to serach multiple parameters at the same time; from, and to. Something to keep in mind is that there will probably be even more parameters later on in the development. I've got it to work when searching for one of the fields, but not more than that.
Search view:
<%= form_tag(journeys_path, :method => "get", from: "search-form") do %>
<%= text_field_tag :search_from, params[:search_from], placeholder: "Search from", :class => 'input' %>
<%= text_field_tag :search_to, params[:search_to], placeholder: "Search to", :class => 'input' %>
<%= submit_tag "Search", :class => 'submit' %>
<% end %>
Method:
class Journey < ActiveRecord::Base
def self.search(search_from)
self.where("from_place LIKE ?", "%#{search_from}%")
end
end
Controller:
class JourneysController < ApplicationController
def index
#journeys = Journey.all
if params[:search_from]
#journeys = Journey.search(params[:search_from])
else
#journeys = Journey.all.order('created_at DESC')
end
end
def search
#journeys = Journey.search(params[:search_from])
end
end
I've tried some gems and all kind of solutions that I've found in other questions, but I'm just not good enough at RoR yet to succesfully apply them correctly without help. I would appreciate any help I can get.
Thank you!
Model:
class Journey < ActiveRecord::Base
def self.search(search_from, search_to)
self.where("from_place LIKE ? and to_place LIKE ?", "%#{search_from}%", "%#{search_to}%")
end
end
Controller:
class JourneysController < ApplicationController
def index
if params[:search_from] and params[:search_to]
#journeys = search
else
#journeys = Journey.all.order('created_at DESC')
end
end
def search
#journeys = Journey.search(params[:search_from], params[:search_to])
end
end
The best approach here is to incapsulate your search form as a separate Ruby class. Using Virtus here helps to get type coercion for free.
class SearchForm
include Virtus.model # Our virtus module
include ActiveModel::Model # To get ActiveRecord-like behaviour for free.
attribute :from, String
attribute :to, String
# Just to check if any search param present,
# you could substitute this with validations and just call valid?
def present?
attributes.values.any?{|value| value.present?}
end
```
In Rails 3 IIRC you also have to include ActiveModel::Validations to be able to validate your form input if needed.
Now, let's see how to refactor controller. We instantiate form object from params and pass that to the model query method to fetch records needed. I also moved ordering out of if clause and used symbol ordering param - cleaner IMO.
def index
#search_form = SearchForm.new(search_params)
if #search_form.valid? && #search_form.present?
#journeys = Journey.search(#search_form)
else
#journeys = Journey.all
end
#journeys = #journeys.order(created_at: :desc)
end
def search
#journeys = Journey.search(SearchForm.new(search_params)
end
private
def search_params
params.require(:search_form).permit(:from, :to)
end
Now to the view: form_for will work perfectly with our form object, as will simple_form_for
<%= form_for #search_form, url: journeys_path, method: :get do |f| %>
<%= f.text_field :from, placeholder: "Search from", class: 'input' %>
<%= f.text_field :to, placeholder: "Search to", class: 'input' %>
<%= f.submit "Search", class: 'submit' %>
<% end %>
View looks now much shorter and cleaner. Incapsulating params in object makes working with search params muuuuch easier.
Model:
class Journey < ActiveRecord::Base
def self.search(search_form)
if search_form.kind_of?(SearchForm)
journeys = all # I'm calling Journey.all here to build ActiveRecord::Relation object
if search_form.from.present?
journeys = journeys.where("from_place LIKE ?", "%#{search_form.from}%")
end
if search_form.to.present?
journeys = journeys.where("to_place LIKE ?", "%#{search_form.to}%")
end
else
raise ArgumentError, 'You should pass SearchForm instance to Journey.search method'
end
end
end
Notice how I build ActiveRecord::Relation object by calling Journeys.all and applying each search param if present. Chaining where like that would put AND in between automatically, if you need OR Rails 4 has it: Journey.or(condition).
Pros of this approach:
You are using Plain Old Ruby Classes, almost no magic here, and it works like usual Rails model in many ways. Putting search params in the object makes it a lot easier to refactor code. Virtus is the only dependency, sans Rails itself of course, and it's more for convenience and to avoid writing boring boiler-plate code.
You can easily validate input if needed (If you really want to be strict about input and show user validation error instead of silently executing stupid query with contradicting conditions and returning no results).

Ruby on rails can't create with params

I have a from created in Ruby on rails. The code the form looks like this:
<%= simple_form_for(#action) do |f|%>
<%= render 'shared/error_messages' %>
<%=f.label :action_name, "Action name"%>
<%=f.text_field :action_name%></br>
<%=f.input :startDate,:as => :datetime_picker, :label =>"Start date"%>
<%=f.input :endDate,:as => :datetime_picker, :label =>"End date"%>
<%=f.label :contentURL, "Content url"%>
<%=f.text_field :contentURL%></br>
<%= f.button :submit, class: "btn btn-large btn-primary" %>
<%end%>
But when I click the submit button I get this error:
undefined method `permit' for "create":String
def action_params
params.require(:action).permit(:action_name, :startDate,:endDate,:contentURL)
All other forms a working ok, I guess it is something really obvious, just can't see it :(
I really appreciate any help, solving this problem.
Thanks!!
EDIT:
Controller code:
def create
action = Action.new(action_params)
if #action.save
flash[:success] = "New Action saved"
redirect_to "/"
else
render 'new'
end
end
private
def action_params
params.require(:action).permit(:action_name, :startDate,:endDate,:contentURL)
end
In Rails 4, you must use Strong Parameters in your controllers. Here's some explanation from the official blog. And some example:
class PeopleController < ActionController::Base
# This will raise an ActiveModel::ForbiddenAttributes exception because it's using mass assignment
# without an explicit permit step.
def create
Person.create(params[:person])
end
# This will pass with flying colors as long as there's a person key in the parameters, otherwise
# it'll raise a ActionController::MissingParameter exception, which will get caught by
# ActionController::Base and turned into that 400 Bad Request reply.
def update
redirect_to current_account.people.find(params[:id]).tap do |person|
person.update_attributes!(person_params)
end
end
private
# Using a private method to encapsulate the permissible parameters is just a good pattern
# since you'll be able to reuse the same permit list between create and update. Also, you
# can specialize this method with per-user checking of permissible attributes.
def person_params
params.required(:person).permit(:name, :age)
end
end
Notice how, in the last lines, under the private keyword, the person_params method is defined, which declares the permitted fields to be assigned by the create and update methods on top. And it's the person_params that is used for updating - the valid example - instead of the raw params array.

letsrate gem ActionView::Template::Error (undefined method `average' for nil:NilClass):

I am really new to the letsrate gem.
I am currently going through the example on the wiki, https://github.com/muratguzel/letsrate
I installed the gem, installed devise, generated a user model, and generated a restaurant model, generated a restaurants controller with a simple show method, set the route to the controller#show. The problem is with the helper method,
this is my show.html.erb template
friendliness <%= rating_for #restaurant, "friendliness" %>
Taste : <%= rating_for #restaurant, "taste" %>
Price : <%= rating_for #restaurant, "price" %>
with my restaurant.rb model like this
class Restaurant < ActiveRecord::Base
# attr_accessible :title, :body
letsrate_rateable "friendliness", "price", "taste"
end
and my restaurants_controller.rb like this
class RestaurantsController < ApplicationController
def show
end
end
this is my error,
ActionView::Template::Error (undefined method `average' for nil:NilClass):
This average method should be a part of the gem. Is this a gem problem or my problem? Its suppose to show the average of the stars.

Undefined method 'model_name' when attempting to use Simple Form in Rails

I am attempting to get a form generated by simple-form in my modal, however I keep running into the following error upon loading the page.
undefined method 'model_name' for NilClass:Class
Here is the simple code I was using to try to generate the form
_header.html.erb (under the view_pages_controller)
<%= simple_form_for #update do |f| %>
<%= f.input :lang %>
<%= f.input :book %> #temp, just for testing simpform
<%= f.button :submit %>
<% end %>
I am pretty sure the problem lies with my controller code
updates_controller.rb
class UpdatesController < ApplicationController
before_filter :signed_in_user, only: [:create, :destroy]
def create
#update = current_user.updates.build(params[:update])
if #update.save
flash[:success] = "Update successful"
redirect_to root_path
else
flash[:error] = "Failed to update, please try again"
redirect_to root_path
end
end
end
update.rb
class Update < ActiveRecord::Base
attr_accessible :book, :user_id, :lang, :round_id
belongs_to :user
end
Any help/tips would be greatly appreciated. I know my code sucks.
The problem is that #update is null in your view. You should clarify which action renders this view, and set value to #update. The create action only sets it based on the params, and then redirects to root.
I believe you are using some kind of RESTfull controller, and you are rendering your form on action :new. So, to solve your trouble, add
#update = current_user.updates.build(params[:update])
to your new action
Have you tried putting a debugger in above the line in your controller where you declare #update.
You could then see your current_user object and what methods are available using something like current_user.methods
Have you included resource:'updates' or resources:'updates' in routes.rb.This may solve the problem.

Resources