Wrong controller is active when using an external SQL table. - sql

I am working on a back-office app. The apps I am deploying have a model/table of user_messages. The user messages are used to display admin messages from a central app. The idea is that I can use that app to publish messages to the individual apps such as "System will be unavailable from noon to 1 on Friday".
The individual apps use their own schema in the database. for example, the research library would be rl.user_messages etc.
Since I will need to access multiple tables, I set it up so I can access external tables.
production:
adapter: sqlserver
host: server1
port: 1435
database: web
username: XX
password: xXX
schema_search_path: umc
technical_libraries:
adapter: sqlserver
host: server1
port: 1435
database: XXXX
username: XX
password: XXXXXXXX
schema_search_path: tl
The model that lets me connect to the technical library as an external model is
class TechnicalLibrary < ActiveRecord::Base
self.abstract_class = true
def self.table_name_prefix
'tl_'
end
establish_connection "technical_libraries" # TODO might want to name this to a generic
end
class UserMessage < TechnicalLibrary
self.table_name = "tl.user_messages" # for this one, as opposed to the product development, we need to specify the schema.
end
My technical Libraries controller is
class TechnicalLibrariesController < ApplicationController
def index
#user_messages= TechnicalLibrary::UserMessage.all
end
def show
#technical_library = TechnicalLibrary::UserMessage.first # TODO HARDWIRED -
end
def new
#technical_library = TechnicalLibrary::UserMessage.new
end
def edit
#technical_library = TechnicalLibrary::UserMessage.find(params[:id])
end
def create
#technical_library = TechnicalLibrary::UserMessageRl.new(technical_library_params)
respond_to do |format|
if #technical_library.save
format.html { redirect_to #technical_library, notice: 'Technical library was successfully created.' }
format.json { render :show, status: :created, location: #technical_library }
else
format.html { render :new }
format.json { render json: #technical_library.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #technical_library.update(technical_library_params)
format.html { redirect_to #technical_library, notice: 'technical library was successfully updated.' }
format.json { render :show, status: :ok, location: #technical_library }
else
format.html { render :edit }
format.json { render json: #technical_library.errors, status: :unprocessable_entity }
end
end
end
def destroy
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_technical_library
#technical_library = TechnicalLibrary.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def technical_library_params
params.require(:technical_library).permit(:message, :expires)
end
My technical Libraries form is
<%= form_for(#technical_library) do |f| %>
<% if #technical_library.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#technical_library.errors.count, "error") %> prohibited this technical_library from being saved:</h2>
<ul>
<% #technical_library.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :message %><br>
<%= f.text_field :message %>
</div>
<div class="field">
<%= f.label :expires %><br>
<%= f.datetime_select :expires %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<hr>
Controller <%= controller_name %> | <%= action_name %>
<hr>
The form looks as follows. The submit button seems to be wrong. it is pointing to another model.
If I click on the submit button, I get an error message as follows. I suspect that the problem lies in inheriting from another model.
NameError in UserMessagesController#show
uninitialized constant TechnicalLibrary::UserMessageRl
Rails.root: C:/Users/cmendla/RubymineProjects/user_message_console_3
Application Trace | Framework Trace | Full Trace
app/controllers/user_messages_controller.rb:15:in `show'
Request
Parameters:
{"id"=>"1"}
I had a UserMessage model that I'm probably not going to use since I will connect to the individual application's tables.
class UserMessage < ActiveRecord::Base
end

OK - figured it out. I had to specify the controller and action in the form_for statement.
<%= form_for #technical_library, :url => { :controller => "technical_libraries", :action => "update" }, :html => {:method => :post} do |f| %>
That seems to be doing the trick

Related

ActiveStorage Image Upload Error with Rails 5.2: signed_id delegated to attachment, but attachment is nil

I'm having an issue with image/pdf uploads with ActiveStorage. The images appear to be uploading without issue, but they are causing errors when I try to show them.
My blog model has_one_attached :image and has_one_attached :pdf. The uploads used to work (so I know I have ActiveStorage installed and my amazon s3 set up properly), but something has gone wrong.
The only complicated bit is I need it to work if it has a PDF or not (not all blogs will have a pdf...all should have an image).
My blog#create method is:
def create
#blog = Blog.new(blog_params)
#blog.user_id = current_user.id
if #blog.published
#blog.published_on = DateTime.current
end
respond_to do |format|
if #blog.save
if #blog.image.attached?
#blog.image.purge
end
#blog.image.attach(params[:image])
if #blog.pdf.attached?
#blog.pdf.purge
end
#blog.pdf.attach(params[:pdf])
format.html { redirect_to #blog, notice: 'Blog was successfully created.' }
format.json { render :show, status: :created, location: #blog }
else
format.html { render :new }
format.json { render json: #blog.errors, status: :unprocessable_entity }
end
end
end
My blog#update method is:
def update
if #blog.published
#blog.published_on = DateTime.current
end
if #blog.image.attached?
#blog.image.purge
end
#blog.image.attach(params[:image])
if #blog.pdf.attached?
#blog.pdf.purge
end
#blog.pdf.attach(params[:pdf])
respond_to do |format|
if #blog.update(blog_params)
format.html { redirect_to #blog, notice: 'Blog was successfully updated.' }
format.json { render :show, status: :ok, location: #blog }
else
format.html { render :edit }
format.json { render json: #blog.errors, status: :unprocessable_entity }
end
end
end
My form is simple:
<%= simple_form_for(#blog) do |f| %>
<%= f.error_notification %>
<%= f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present? %>
...
<div class="form-group">
<%= f.label "Blog Image" %><br />
<%= f.file_field :image %>
</div>
<div class="form-group">
<%= f.label "Linked PDF" %><br />
<%= f.file_field :pdf %>
</div>
...
<div class="form-actions text-center">
<%= f.button :submit, class: "btn-outline-primary" %>
</div>
<% end %>
I'm trying to show the image in the blog like this:
<div class="frame" style="background-image: url(<%= rails_blob_url(#blog.image) %>)"></div>
And the PDF like this:
<h2 class="cta text-center"><%= link_to #blog.cta, rails_blob_url(#blog.pdf), target: "_blank" %></h2>
The error I'm getting is signed_id delegated to attachment, but attachment is nil on the place the image is called as a background image on the blog#show page. I get the same error on localhost and Heroku, if it helps.
Finally, I saw this error on this question and did try dropping and recreating my database, but to no avail.
Can anyone see what's going wrong here?
I just ran into this error and really struggled to figure out what could have been happening. It first appeared when I submitted a form and did not include an attachment. Turns out I needed to check to see if something was really attached and deal with that possibility.
Perhaps try moving #blog.pdf.attach(params[:pdf]) to before the respond_to in blog#create
Then, when trying to show the image, maybe you could try something like this
<% if blog.pdf.attached? == false %>
<p>No pdf attached</p>
<% elsif blog.pdf.previewable? %>
<%= link_to(image_tag(blog.pdf.preview(resize: "50x50>")), rails_blob_path(blog.pdf, disposition: "attachment"))
%>
<% elsif blog.pdf.variable? %>
<%= link_to(image_tag(blog.pdf.variant(resize: "50x50")), rails_blob_path(blog.pdf, disposition: "attachment"))%>
<% else %>
<%= link_to "Download file", rails_blob_path(#blog.pdf, disposition: "attachment") %>
<% end %>
Heroku has a good article on active storage here that may also help.

What are some possible reasons that you would get an undefined method 'TheModelName_path' error using a form_for in rails 3?

I can't figure out why I have this error from my knowledge everything is set up as it should to work.
this is the error i get:
NoMethodError at /short/new
undefined method `shorts_path' for #<#:0x007fbc441426e0>
my model is short not shortS
when I run rake routes there is no shorts_path so I'm not sure where this helper is coming from. I don't understand why the form_for is giving me this error when #short is defined in the def new section of my controller.
Can someone please explain this to me?
Thank you in advance
This is what my controller looks like
class ShortController < ApplicationController
def show
#short = Short.find(params[:id].to_i(36))
respond_to do |format|
#redirect directly to the url stored as long in the database
format.html { redirect_to #short.long}
end
end
def new
#short = Short.new
respond_to do |format|
format.html # new.html.erb
end
end
def create
#short = Short.new(params[:short])
respond_to do |format|
if #short.save
format.html { render action: "show" }
else
format.html { render action: "new" }
end
end
end
end
routes
Trainingproject::Application.routes.draw do
root :to => 'short#welcome'
resources :short, :only => [:new, :create, :show]
end
form partial which is rendered in the view for new
<%= form_for(#short) do |f| %>
<% if #short.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#short.errors.count,"error") %> prohibited this url from being saved:</h2>
<ul>
<% #short.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-field">
<%= f.label "Enter your URL" %><br />
<%= f.text_field :long %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
You're getting this error because form_for(#short), where #short is a new Short record, will attempt to use the path helper called shorts_path to route to where the form needs to go. You're missing this route definition in your config/routes.rb file:
resources :shorts
Please read the Getting Started and Routing guides, which should explain the things that you're missing.

Create a select from existing or create new in a form Rails 3

So I'm trying to set a name attribute of organizations and create a new organization or choose from a previously existing organization from the same form.
I've tried to follow Ryan Bates' railscast on the topic here: http://railscasts.com/episodes/57-create-model-through-text-field
I have also tried numerous solutions from stack. However, I can't quite seem to get it to run (that and I have a validation that does not recognize the virtual attribute I'm using)
so my organizations model:
class Organization < ActiveRecord::Base
has_many :materials
has_many :users
has_and_belongs_to_many :causes
has_and_belongs_to_many :schools, :join_table => 'organizations_schools'
####The following line has been edited ####
attr_accessible :name, :unlogged_books_num, :id, :new_organization_name
attr_accessor :new_organization_name
before_validation :create_org_from_name
validates_presence_of :name
def self.assign_school_to_organization(org, school)
orgschool = OrganizationsSchool.create(:organization_id=> org.id, :school_id=> school[0])
end
def create_org_from_name
create_organization(:name=>new_organization_name) unless new_organization_name.blank?
end
end
I have also tried the create_org_from_name as the following:
def create_org_from_name
self.name = new_organization_name
end
And this does not change the name to the organization name before validating or saving the instance.
I have also tried to change the before_save to before_validation, and that has not worked
My controller for organization (I also tried to change this in create)
def create
respond_to do |format|
#organization = Organization.new(params[:organization])
#organization.name = #organization.new_organization_name unless #organization.new_organization_name.blank?
if #organization.save
#school = params[:school]
Organization.assign_school_to_organization(#organization, #school)
format.html { redirect_to #organization, notice: 'Organization was successfully created.' }
format.json { render json: #organization, status: :created, location: #organization }
else
format.html { render action: "new" }
format.json { render json: #organization.errors, status: :unprocessable_entity }
end
end
end
And finally, I have what my form is doing currently:
<%= form_for(#organization) do |f| %>
<% if #organization.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#organization.errors.count, "error") %> prohibited this organization from being saved:</h2>
<ul>
<% #organization.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<% #schools = School.all %>
<% #organizations = Organization.all %>
<div class="field">
<%= f.label 'Organization Name' %><br />
<%= f.collection_select(:name, #organizations, :name, :name, :prompt=>"Existing Organization") %>
Or Create New
<%= f.text_field :new_organization_name %>
</div>
<div class="field">
<%= f.label :unlogged_books_num %><br />
<%= f.number_field :unlogged_books_num %>
</div>
<div class="field">
<%= f.label 'School' %><br />
<% school_id = nil %>
<%= collection_select(:school, school_id, #schools, :id, :name) %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
==================================EDIT============================================
So currently, when I try to make an organization with something only written in the virtual text field, My log tells me the following:
Processing by OrganizationsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"igoefz8Rwm/RHrHLTXQnG48ygTGLydZrzP4gEJOPbF0=", "organization"=> {"name"=>"", "new_organization_name"=>"Virtual Organization", "unlogged_books_num"=>""}, "school"=>["1"], "commit"=>"Create Organization"}
Rendered organizations/_form.html.erb (7.1ms)
Rendered organizations/new.html.erb within layouts/application (8.0ms)
Completed 200 OK in 17ms (Views: 12.2ms | ActiveRecord: 1.0ms)
================================EDIT 2============================================
So this is what I get from the rails console if I try to create a new organization running this command: Organization.create(:new_organization_name=>"Virtual Organization", :unlogged_books_num=>"3")
irb(main):001:0> Organization.create(:new_organization_name=>"Virtual Organization", :unlogged_books_num=>"3")
(0.1ms) BEGIN
(0.1ms) ROLLBACK
=> #<Organization id: nil, name: nil, unlogged_books_num: 3, created_at: nil, updated_at: nil>
If the function of create_org_from_name is self.name = new_organization_name, then the result of the same command from the console is blank:
irb(main):002:1> Organization.create(:new_organization_name=>"Virtual Organization", :unlogged_books_num=>"3")
irb(main):003:1>
You need:
before_validation :create_org_from_name
and
def create_org_from_name
self.name = new_organization_name if not new_organization_name.blank?
end
You don't want to do a create in your before_validation method.

How to move database operations from controller to model

I've started to work on old project with new tools. This time - Rails on Ruby. I managed to make some progress, and now i want to improve one element of my code.
Whole project is about bugtracking with full history search of all tracked bugs. Now i'm on stage where user is entering bugs. Every bug belong to table which belongs to projects.
Only problem - now - is autocompletion of table name when i'm using completely new name (with tables that are already present in database it's working just fine, fills table_id in Bug entry).
Part of view responsible for entering (or selecting from existing) table looks like this:
<div class="control-group">
<%= f.label :table_name, :class => 'control-label' %>
<div class="controls">
<%= f.autocomplete_field :table_name, autocomplete_table_name_bugs_path %>
</div>
</div>
Nothing unusual. This one goes to the model (Bug.rb)
class Bug < ActiveRecord::Base
attr_accessible :bugid, :fixdate, :fixnote, :fixstate_id, :milestone, :newtarget, :notes, :oldtarget, :project_id, :bugreason, :reason_id, :regressiondate, :regressionstate_id, :source, :stringid, :table_id
belongs_to :project
belongs_to :table
belongs_to :reason
belongs_to :state
def table_name
table.name if table
end
#def table_name=(name)
# self.table = Table.find_or_create_by_name(name) unless name.blank?
#end
end
No validation for now as you can see. table_name=(name) commented as it's apparently doing nothing in my code.
This is working with bugs controller (bugs_controller.rb)
def create
if params[:bug][:table_id].nil?
if Table.find_or_create_by_name(params[:bug][:table_name])
params[:bug][:table_id] = Table.find_by_name(params[:bug][:table_name]).id
params[:bug].delete :table_name
end
end
#bug = Bug.new(params[:bug])
respond_to do |format|
if #bug.save
format.html { redirect_to bugs_path, notice: 'Bug was successfully created.' }
format.json { render json: #bug, status: :created, location: #bug }
else
format.html { render action: "new" }
format.json { render json: #bug.errors, status: :unprocessable_entity }
end
end
end
I put here only part responsible for saving new bugs, i'll manage to handle update part when i do this part right.
What i want to improve is first part. Now it's responsible not only for changing table_name to table_id but for creation of new table if it doesn't exist. I'm aware that this part should be handled by model, but i've no idea how to do that, could use some help.
Another part, as btw. is my dropdown menu where user can select active project. It's handled by partial:
<% #projects.each do |project| %>
<% if project.id == session[:current_project].to_i %>
<li class="disabled"><%= link_to project.name, '#' %></li>
<% else %>
<li><%= link_to project.name, choose_project_path(project.id) %></li>
<% end %>
<% end %>
But it works fine only when used from projects controller. How - by the book - i can handle this from other controllers? To be exact, i want it working same way in whole project.
For now i'm handling it by snippet in every controller, but i'm pretty sure that RoR gods are not happy with me for that.
before_filter :projects
def projects
#projects = Project.all
end
How it should be done in proper way? :)
So i managed to move logic from controller to model. Also, it's saving all data i need - table_id to bugs table and project_id (stored in session) to tables table when creating new table.
So part of form render is not changed:
<div class="control-group">
<%= f.label :table_name, :class => 'control-label' %>
<div class="controls">
<%= f.autocomplete_field :table_name, autocomplete_table_name_bugs_path %>
</div>
</div>
Model now looks like this:
class Bug < ActiveRecord::Base
attr_accessible :table_name, :bugid, :fixdate, :fixnote, :fixstate_id, :milestone, :newtarget, :notes, :oldtarget, :project_id, :bugreason, :reason_id, :regressiondate, :regressionstate_id, :source, :stringid, :table_id
belongs_to :project
belongs_to :table
belongs_to :reason
belongs_to :state
def table_name
table.name if table
end
def table_name=(name)
self.table = Table.find_or_create_by_name(name, project_id: self.project_id ) unless name.blank?
end
end
So only change is uncommenting table_name= method and adding project_id to creation of new table (and lack of project_id was the reason it didn't work earlier).
Controller looks like this:
def create
#bug = Bug.new(params[:bug])
#bug.project_id = session[:current_project]
respond_to do |format|
if #bug.save
format.html { redirect_to bugs_path, notice: 'Bug was successfully created.' }
format.json { render json: #bug, status: :created, location: #bug }
else
format.html { render action: "new" }
format.json { render json: #bug.errors, status: :unprocessable_entity }
end
end
end
It's working like charm. Still i've question remaining, but will post it as separate one.

Passing an object through a link_to command to be referenced in the model#new page

I'm creating a basic loyalty card application, with model Merchant and Loyaltycard. In the merchant#show view I have this line
<%=link_to 'New Loyalty card', new_loyaltycard_path(:merchant_id=>1) %>
I'm trying to pass the merchant ID to the loyaltycard#new view so it will be automatically selected as the merchant for that card. In loyaltycard#_form (which gets called by loyaltycard#new) I have the lines
<%if #merchant%>
<%= f.hidden_field :merchant_id, :value => #merchant.id %>
<%else%>
<div class="field">
<%= f.label :merchant_id %><br />
<%= f.text_field :merchant_id %>
</div>
<%end%>
But I keep getting and error that says can't call id for class Nil. Is there a better way of doing this?
Here is the controller code for loyaltycard
def new
#loyaltycard = Loyaltycard.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #loyaltycard }
end
end
# GET /loyaltycards/1/edit
def edit
#loyaltycard = Loyaltycard.find(params[:id])
end
# POST /loyaltycards
# POST /loyaltycards.json
def create
#loyaltycard = Loyaltycard.new(params[:loyaltycard])
respond_to do |format|
if #loyaltycard.save
format.html { redirect_to #loyaltycard, notice: 'Loyaltycard was successfully created.' }
format.json { render json: #loyaltycard, status: :created, location: #loyaltycard }
else
format.html { render action: "new" }
format.json { render json: #loyaltycard.errors, status: :unprocessable_entity }
end
end
end
The error is
Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
What you need to do in your new action is using the params[:merchant_id] to look up and set #merchant
#merchant = Merchant.find(params[:merchant_id])
Then your code should work, without that, #merchant is nil, and you can't call the method :id on nil
You're not setting variable #merchant anywhere in your controller, but you use it the view.