I am very new to Rails and I am facing a somehow weird problem, and my googling didn't helped me so far...
I have implemented a classical CRUD ressource following the Getting Started with Rails guide and I am blocking on the "update" part:
http://guides.rubyonrails.org/getting_started.html#updating-articles
This is part of my model "Devwork":
class Devwork < ActiveRecord::Base
validates :short_title, presence: true, uniqueness: true
validates :title_fr, presence: true, allow_blank: false
translates :title, :summary, :description
globalize_accessors
end
I am using the Globalize gem to persist localized data, and Globalize-accessor for the helpers.
Here is the controller's update action:
class DevworksController < ApplicationController
def update
#devwork = Devwork.find(params[:id])
if #devwork.update(devwork_params)
redirect_to #devwork
else
render :edit
end
end
private
def devwork_params
params.require(:devwork)
.permit!
end
end
And part of the form:
<%= form_for #devwork do |f| %>
<p>
<%= f.label :short_title %>
<%= f.text_field :short_title %>
</p>
<p>
<%= f.label :title_fr %>
<%= f.text_field :title_fr %>
<%= f.label :title_en %>
<%= f.text_field :title_en %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
short_title and title_fr are mandatory, while there exist another field title_en which is not. I want the update form to be shown again if the update fails (typically because of empty title_fr).
But it doesn't work. The update never fails (never entering render :edit) even if title_fr is empty. In fact, the update does nothing if one of the field is empty, it only updates non-empty fields.
I surely missed something somewhere, but I can't figure it out... perhaps a missuses of Globalize ?
Thanks for your help !
Related
I'm new on rails. I work on a project, and I try to add physical address to my users. I want that the address can be help-complete with Google map for later exploitation. I find the jt-rails-address which look like perfect for my project. But I can't implement it. I need complete address (street, zip code, city & country).
add_address_to_users.rb :
class AddAddressToUsers < ActiveRecord::Migration[5.1]
def change
add_column :users, :address, :address
end
end
form edit.html.erb :
<div class="col-md-6 col-md-offset-3">
<%= form_for (#user), :html => { :multipart => true } do |f| %>
<%= render 'shared/error_messages' %>
<%= f.label :phone, "Téléphone :" %>
<%= f.phone_field :phone, class: 'form-control' %>
<%= f.label :address, "Addresse :" %>
<div class="jt-address-autocomplete">
<!-- This field is used to search the address on Google Maps -->
<%= f.text_field :address, class: 'jt-address-search' %>
<!-- All fields are hidden because the javascript will set their value automatically -->
<% for attr in JT::Rails::Address.fields %>
<%= f.hidden_field "address_#{street}", class: "jt-address-field-#{street}" %>
<% end %>
<% for attr in JT::Rails::Address.fields %>
<%= f.hidden_field "address_#{zip_code}", class: "jt-address-field-#{zip_code}" %>
<% end %>
<% for attr in JT::Rails::Address.fields %>
<%= f.hidden_field "address_#{city}", class: "jt-address-field-#{city}" %>
<% end %>
<% for attr in JT::Rails::Address.fields %>
<%= f.hidden_field "address_#{country}", class: "jt-address-field-#{country}" %>
<% end %>
</div>
<%= f.submit "Enregistrer les changements", class: "btn btn-primary" %>
<% end %>
</div>
application.js :
// This function is call when Google Maps is loaded
window.googleMapInitialize = function(){
// Simple usage
$('.jt-address-autocomplete').jt_address();
};
I have already put :address in my user_params in the users controller and has_address :address in the user model
I also have put my Google Api.
My actual error:
undefined local variable or method `street' for #<#Class:0x00007fe91ec7f768:0x00007fe91dfaefc0>
Thanks in advance for your help.
No more error but a bug, maybe because of Google Map, I don't know how
to resolve it, I can't write the address and there is an error message:
problem
Here the code of the inspector:
First, you should add fields like in documentation or scope them using select, now you have code that will create duplicated hidden fields.
You should check from rails console that method address is available on User instance of model.` Maybe you forgot to run migration or didn't restart server after installing this gem as this is js gem and will need restart.
Hope this answers your questions. Add comment to this answer if problem is still there.
class Person < ActiveRecord::Base
before_save {self.email = email.downcase}
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\-.]+\.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
has_secure_password
validates :password, length: { maximum: 6}
end
I am really new to Ruby. I was learning from Michael Hartl's tutorial. When creating signup form (tutorial 7) I got stuck in displaying error messages ( like if we leave any field blank there should be notifications in red right?).I added error_messages.html.erb file. Rendered it in form. Still there are no messages.
What I guessed is, I am using :user in my form creation to save the user. where as it should be #user. So that it can create user?
but when I did so, It gave me anonymous error of user_path. I searched for that display of error messages on stack but was not able to find.
Kindly help me with it. I am stuck since very long.
<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(:person) do |f| %>
<%= render 'shared/error_messages' %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :email %>
<%= f.email_field :email %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation %>
<%= f.submit "Create my account", class: "btn btn-primary" %>
<% end %>
</div>
</div>
<% if #person.errors.any? %>
<div id="error_explanation">
<div class="alert alert-danger">
the form contains <%= #person.errors.count %> errors.
</div>
<ul>
<%= #person.errors.full_messages.each do |msg| %>
<li> <%= msg %> </li>
<% end %>
</ul>
</div>
<% end %>
class PersonsController < ApplicationController
def show
#person = Person.find(params[:id])
end
def new
#person = Person.new
end
def create
#person = Person.new(user_params)
if #person.save
else
render new
end
end
private
def user_params
params.require(:person).permit(:name, :email, :password, :password_confirmation)
end
end
Rails.application.routes.draw do
get 'persons/show'
root 'staticpages#home'
get 'help' => 'staticpages#help'
get 'about' => 'staticpages#about'
get 'signUp' => 'persons#new'
resource :person
resources :persons
end
// error when i use #user in form. Instead of :user
NoMethodError in PersonsController#new
undefined method `users_path' for #<#<Class:0x007fdb68c0ee78>:0x007fdb68c0e428>
Extracted source (around line #220):
if options.empty?
recipient.send(method, *args)
else
recipient.send(method, *args, options)
end
Based on the code I have seen in the GitHub repo, the major problem I identified was with the naming. There was a large level of conflict in the name person in that its plural is people and not persons.
Rails has its way of pluralizing model names so User has a UsersController and Person has PeopleController and so forth.
Following are the changes required to fix the problems with sign up:
You need to change your controller name from PersonsController to PeopleController (both class name and file name).
In the PeopleController, the strong parameters method Person_params needs to change to lowercase (person_params). Otherwise, Rails would treat it as a constant name and start hunting for it and wouldn't find it.
You'll have to update the persons folder name in the app/views folder to people for the same reason specified above.
In your routes.rb file, there are two changes required. Change resource :person to resources :people and get 'signUp' should match to 'people#new' instead of 'persons#new' (now you know why).
Create a new file in app/views/people called create.html.erb. Once a person is created, Rails automatically renders this file and will throw an exception if it does not find it.
In the file app/views/people/new.html.erb, change the variable passed to form_for from :person to #person. #person is an instance variable initialized when that page is visited (see the new action in the PeopleController).
I'm not sure if this change will be needed, but if you face any errors after making the above changes, add gem 'therubyracer' to your Gemfile and run bundle install. This will install the rubyracer gem which I believe will be required for this version of Rails.
You should really familiarize yourself with the fundamentals of the framework and the Ruby language. It'll help you identify and debug these issues yourself. But I figured since you're new to it, this lengthy answer might help get rid of your frustration :).
You have used the User model in multiple places. The actual model is called Person. Switch to this model name in all the controllers and the model class.
And I'd also like to make a suggestion. When studying the tutorial, please do not blindly copy and paste snippets. Understand what their purpose is and write them in your files on your own.
In my rails project I use Carrierwave to upload images to S3 via fog. So far I have the Create Read and Delete portions of the CRUD spectrum working.
My problem is the edit/update portion. Im use the same _form.html.erb to edit that I used for creating records. When I click the edit link the form loads all of my data into the form fields for editing with the exception of the image. The form field is blank as though there is no image associated with the record.
How do I update an image that is already saved to S3?
Models/listing.rb
class Listing < ActiveRecord::Base
attr_accessible :body, :price, :title, :image
mount_uploader :image, ListingUploader
end
Controllers/listings_controller.rb (edit/update portion)
def edit
#listing = Listing.find(params[:id])
end
def update
#listing = Listing.find(params[:id])
if #listing.update_attributes(params [:listing])
redirect_to :action => 'show', :id => #listing
else
render :action => 'edit'
end
end
_form.html.erb
<%= form_for #listing, :html => { :multipart => true } do |l| %>
<p>
<%= l.label :title %>
<%= l.text_field :title %>
</p>
<p>
<%= l.label :price %>
<%= l.text_field :price %>
</p>
<p>
<label>Upload a Picture</label>
<%= l.file_field :image %>
<%= l.hidden_field :image_cache %>
</p>
<div class="image-pre">
<%= image_tag(#listing.image_url(:thumb)) if #listing.image? %>
</div>
<p>
<%= l.label :body %>
<%= l.text_area :body, :class => "tinymce" %>
<%= tinymce %>
</p>
<%= l.submit %>
<% end %>
In your listings_controller.rb, try something like:
def edit
#listing = Listing.find(params[:id])
#listing.image.cache!
end
Haven't tested this out myself, but I think it might work, given that image_cache field is used to circumvent this problem normally.
I had upgraded my app to Rails 6 sometime ago, then started experiencing this issue.
tldr; you need a carrierwave gem version 2.1.0 or higher for Rails 5.0 and up.
I used bundle outdated --strict to see if carrierwave could be upgraded. Check Gemfile to see if the requested version is set correctly. Also check Gemfile.lock to see if other gems are holding it back; you'll need to upgrade them as well. Then I used bundle update --strict to perform the actual upgrade.
I'm working on my first rails app and having a weird issue.
I'm using Rails 3.2.6 with mongodb.
In my view, I can get a label to display like so:
<%= f.label :percent %>
But when I try the same thing with a text field
like so:
<%= f.text_field :percent %>
the page doesn't even load, nothing happens.
Here is my controller:
class TrimmingsController < ApplicationController
def new
#order = Order.find params[:order_id]
end
And my model:
class Trimming
include Mongoid::Document
embedded_in :order
field :percent, type: String
end
And here is my whole view:
<%= form_for #order do |f| %>
<p>
<%= f.text_field :percent %>
</p>
<% end %>
I just want to get a text_field to display sorry for the
simpleton question but I've been trying for 2 days to get
this text field to pop up.
You need to make percent attr_accessible. Add this to your model.
attr_accessible: :percent
Check it with following code in view:
<%= form_for :order do |f| %>
<%= f.text_field :percent %>
<% end %>
Have a page where there are multiple input fields of the same thing, Posts. Right now, when a user enters in a question for, let's say 3 fields, the only one that saves to the database is the last one. Whereas, it should save all three and give them each it's own post_id. Also; if the user doesn't enter anything in for the other fields, it should not save in the database either.
new_step_4_html.erb
<%= form_for(#post) do |f| %>
<%= f.text_field :content %>
<%= f.text_field :content %>
<%= f.text_field :content %>
<% end %>
projects_controller.rb
def new_step_4
#post = Post.new
end
Right now, all it does is submit one :content field, obviously because they all share the same id/value. Unfortunately, the Railscasts #197 applies for nested forms, so the javascript and helper stuff he does all applies for nested. I would think this is something simple. Person from IRC mentioned I could do some sort of '3.times' code into the view file or something?
First of all you will probably have to edit the model of you post.
post.rb
has_many :contents, :dependent => :destroy
accepts_nested_attributes_for :contents
You will need another model to store the content fields.
so first generate a model
rails g model content post_id:integer body:text
the model
content.rb
belongs_to :post
Now, in stead of doing <%= f.text_field :content %> a few times, let rails create them, because now you basically let them overwrite each other.
3.times do
content = #post.content.build
end
the form view will be something like this:
<%= form_for #post do |f| %>
<%= f.fields_for :contents do |builder| %>
<%= builder.label :body, "Question" %><br />
<%= builder.text_area :body, :rows => 3 %><br />
<%= end %>
<p><%= f.submit "Submit" %></p>
<% end %>
I did not test this code, but the idea should be correct. Let me know if you need more info.